Diff
Modified: trunk/LayoutTests/ChangeLog (89452 => 89453)
--- trunk/LayoutTests/ChangeLog 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/LayoutTests/ChangeLog 2011-06-22 18:26:03 UTC (rev 89453)
@@ -1,3 +1,14 @@
+2011-06-22 Sam Weinig <[email protected]>
+
+ Reviewed by Adam Barth.
+
+ HTML parser should limit element depth of produced tree
+ https://bugs.webkit.org/show_bug.cgi?id=63082
+
+ * fast/parser/block-nesting-cap-expected.txt:
+ * fast/parser/element-nesting-cap-expected.txt:
+ Update expectations for new parser depth limit.
+
2011-06-22 Adam Barth <[email protected]>
Rollout 88332.
Modified: trunk/LayoutTests/fast/parser/block-nesting-cap-expected.txt (89452 => 89453)
--- trunk/LayoutTests/fast/parser/block-nesting-cap-expected.txt 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/LayoutTests/fast/parser/block-nesting-cap-expected.txt 2011-06-22 18:26:03 UTC (rev 89453)
@@ -3,9 +3,9 @@
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-FAIL d4096.parentNode === d4094 should be true. Was false.
+PASS d4096.parentNode === d4094 is true
PASS d4095.parentNode === d4094 is true
-FAIL d4096.previousSibling === d4095 should be true. Was false.
+PASS d4096.previousSibling === d4095 is true
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/parser/element-nesting-cap-expected.txt (89452 => 89453)
--- trunk/LayoutTests/fast/parser/element-nesting-cap-expected.txt 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/LayoutTests/fast/parser/element-nesting-cap-expected.txt 2011-06-22 18:26:03 UTC (rev 89453)
@@ -4,8 +4,8 @@
FAIL s3.parentNode === s1 should be true. Was false.
-PASS s2.parentNode === s1 is true
-FAIL s3.previousSibling === s2 should be true. Was false.
+FAIL s2.parentNode === s1 should be true. Was false.
+PASS s3.previousSibling === s2 is true
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/Source/WebCore/ChangeLog (89452 => 89453)
--- trunk/Source/WebCore/ChangeLog 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/ChangeLog 2011-06-22 18:26:03 UTC (rev 89453)
@@ -1,3 +1,51 @@
+2011-06-22 Sam Weinig <[email protected]>
+
+ Reviewed by Adam Barth.
+
+ HTML parser should limit element depth of produced tree
+ https://bugs.webkit.org/show_bug.cgi?id=63082
+
+ Test by:
+ fast/parser/block-nesting-cap.html
+ fast/parser/element-nesting-cap.html
+
+ * html/parser/HTMLConstructionSite.cpp:
+ (WebCore::HTMLConstructionSite::attach):
+ (WebCore::HTMLConstructionSite::HTMLConstructionSite):
+ * html/parser/HTMLConstructionSite.h:
+ Limit the DOM tree depth by turning attempts to add a child passed a certain
+ threshold (configurable by Settings::maximumDOMTreeDepth) into a sibling.
+
+ * html/parser/HTMLDocumentParser.cpp:
+ (WebCore::HTMLDocumentParser::HTMLDocumentParser):
+ (WebCore::HTMLDocumentParser::maximumDOMTreeDepth):
+ * html/parser/HTMLDocumentParser.h:
+ Pass the maximumDOMTreeDepth to the TreeBuilder.
+
+ * html/parser/HTMLElementStack.cpp:
+ (WebCore::HTMLElementStack::HTMLElementStack):
+ (WebCore::HTMLElementStack::popAll):
+ (WebCore::HTMLElementStack::insertAbove):
+ (WebCore::HTMLElementStack::pushCommon):
+ (WebCore::HTMLElementStack::popCommon):
+ (WebCore::HTMLElementStack::removeNonTopCommon):
+ * html/parser/HTMLElementStack.h:
+ (WebCore::HTMLElementStack::size):
+ Keep track of the size of the element stack.
+
+ * html/parser/HTMLTreeBuilder.cpp:
+ (WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
+ * html/parser/HTMLTreeBuilder.h:
+ (WebCore::HTMLTreeBuilder::create):
+ Pass the maximumDOMTreeDepth to the construction site.
+
+ * page/Settings.cpp:
+ (WebCore::Settings::Settings):
+ * page/Settings.h:
+ (WebCore::Settings::setMaximumHTMLParserDOMTreeDepth):
+ (WebCore::Settings::maximumHTMLParserDOMTreeDepth):
+ Add a setting to control the maximum DOM tree depth that the parser will produce.
+
2011-06-22 Adam Barth <[email protected]>
Rollout 88332. As discussed on webkit-dev, we'd like to iterate on
Modified: trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp (89452 => 89453)
--- trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp 2011-06-22 18:26:03 UTC (rev 89453)
@@ -96,6 +96,10 @@
return child.release();
}
+ // Add as a sibling of the parent if we have reached the maximum depth allowed.
+ if (m_openElements.stackDepth() > m_maximumDOMTreeDepth)
+ parent = parent->parentNode();
+
parent->parserAddChild(child);
// An event handler (DOM Mutation, beforeload, et al.) could have removed
@@ -126,21 +130,23 @@
child->attach();
}
-HTMLConstructionSite::HTMLConstructionSite(Document* document)
+HTMLConstructionSite::HTMLConstructionSite(Document* document, unsigned maximumDOMTreeDepth)
: m_document(document)
, m_attachmentRoot(document)
, m_fragmentScriptingPermission(FragmentScriptingAllowed)
, m_isParsingFragment(false)
, m_redirectAttachToFosterParent(false)
+ , m_maximumDOMTreeDepth(maximumDOMTreeDepth)
{
}
-HTMLConstructionSite::HTMLConstructionSite(DocumentFragment* fragment, FragmentScriptingPermission scriptingPermission)
+HTMLConstructionSite::HTMLConstructionSite(DocumentFragment* fragment, FragmentScriptingPermission scriptingPermission, unsigned maximumDOMTreeDepth)
: m_document(fragment->document())
, m_attachmentRoot(fragment)
, m_fragmentScriptingPermission(scriptingPermission)
, m_isParsingFragment(true)
, m_redirectAttachToFosterParent(false)
+ , m_maximumDOMTreeDepth(maximumDOMTreeDepth)
{
}
Modified: trunk/Source/WebCore/html/parser/HTMLConstructionSite.h (89452 => 89453)
--- trunk/Source/WebCore/html/parser/HTMLConstructionSite.h 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/html/parser/HTMLConstructionSite.h 2011-06-22 18:26:03 UTC (rev 89453)
@@ -44,8 +44,8 @@
class HTMLConstructionSite {
WTF_MAKE_NONCOPYABLE(HTMLConstructionSite);
public:
- HTMLConstructionSite(Document*);
- HTMLConstructionSite(DocumentFragment*, FragmentScriptingPermission);
+ HTMLConstructionSite(Document*, unsigned maximumDOMTreeDepth);
+ HTMLConstructionSite(DocumentFragment*, FragmentScriptingPermission, unsigned maximumDOMTreeDepth);
~HTMLConstructionSite();
void detach();
@@ -152,6 +152,8 @@
// "whenever a node would be inserted into the current node, it must instead
// be foster parented." This flag tracks whether we're in that state.
bool m_redirectAttachToFosterParent;
+
+ unsigned m_maximumDOMTreeDepth;
};
}
Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp (89452 => 89453)
--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp 2011-06-22 18:26:03 UTC (rev 89453)
@@ -78,7 +78,7 @@
: ScriptableDocumentParser(document)
, m_tokenizer(HTMLTokenizer::create(usePreHTML5ParserQuirks(document)))
, m_scriptRunner(HTMLScriptRunner::create(document, this))
- , m_treeBuilder(HTMLTreeBuilder::create(this, document, reportErrors, usePreHTML5ParserQuirks(document)))
+ , m_treeBuilder(HTMLTreeBuilder::create(this, document, reportErrors, usePreHTML5ParserQuirks(document), maximumDOMTreeDepth(document)))
, m_parserScheduler(HTMLParserScheduler::create(this))
, m_xssAuditor(this)
, m_endWasDelayed(false)
@@ -91,7 +91,7 @@
HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission)
: ScriptableDocumentParser(fragment->document())
, m_tokenizer(HTMLTokenizer::create(usePreHTML5ParserQuirks(fragment->document())))
- , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, scriptingPermission, usePreHTML5ParserQuirks(fragment->document())))
+ , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, scriptingPermission, usePreHTML5ParserQuirks(fragment->document()), maximumDOMTreeDepth(fragment->document())))
, m_xssAuditor(this)
, m_endWasDelayed(false)
, m_pumpSessionNestingLevel(0)
@@ -569,6 +569,12 @@
return document->settings() && document->settings()->usePreHTML5ParserQuirks();
}
+unsigned HTMLDocumentParser::maximumDOMTreeDepth(Document* document)
+{
+ ASSERT(document);
+ return document->settings() ? document->settings()->maximumHTMLParserDOMTreeDepth() : Settings::defaultMaximumHTMLParserDOMTreeDepth;
+}
+
void HTMLDocumentParser::suspendScheduledTasks()
{
if (m_parserScheduler)
Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.h (89452 => 89453)
--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.h 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.h 2011-06-22 18:26:03 UTC (rev 89453)
@@ -73,6 +73,7 @@
static void parseDocumentFragment(const String&, DocumentFragment*, Element* contextElement, FragmentScriptingPermission = FragmentScriptingAllowed);
static bool usePreHTML5ParserQuirks(Document*);
+ static unsigned maximumDOMTreeDepth(Document*);
HTMLTokenizer* tokenizer() const { return m_tokenizer.get(); }
String sourceForToken(const HTMLToken&);
Modified: trunk/Source/WebCore/html/parser/HTMLElementStack.cpp (89452 => 89453)
--- trunk/Source/WebCore/html/parser/HTMLElementStack.cpp 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/html/parser/HTMLElementStack.cpp 2011-06-22 18:26:03 UTC (rev 89453)
@@ -164,6 +164,7 @@
: m_rootNode(0)
, m_headElement(0)
, m_bodyElement(0)
+ , m_stackDepth(0)
{
}
@@ -207,6 +208,7 @@
m_rootNode = 0;
m_headElement = 0;
m_bodyElement = 0;
+ m_stackDepth = 0;
while (m_top) {
topNode()->finishParsingChildren();
m_top = m_top->releaseNext();
@@ -343,6 +345,7 @@
if (recordAbove->next() != recordBelow)
continue;
+ m_stackDepth++;
recordAbove->setNext(adoptPtr(new ElementRecord(element, recordAbove->releaseNext())));
recordAbove->next()->element()->beginParsingChildren();
return;
@@ -553,6 +556,8 @@
void HTMLElementStack::pushCommon(PassRefPtr<ContainerNode> node)
{
ASSERT(m_rootNode);
+
+ m_stackDepth++;
m_top = adoptPtr(new ElementRecord(node, m_top.release()));
topNode()->beginParsingChildren();
}
@@ -564,6 +569,8 @@
ASSERT(!top()->hasTagName(HTMLNames::bodyTag) || !m_bodyElement);
top()->finishParsingChildren();
m_top = m_top->releaseNext();
+
+ m_stackDepth--;
}
void HTMLElementStack::removeNonTopCommon(Element* element)
@@ -577,6 +584,7 @@
// when the children aren't actually finished?
element->finishParsingChildren();
pos->setNext(pos->next()->releaseNext());
+ m_stackDepth--;
return;
}
}
Modified: trunk/Source/WebCore/html/parser/HTMLElementStack.h (89452 => 89453)
--- trunk/Source/WebCore/html/parser/HTMLElementStack.h 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/html/parser/HTMLElementStack.h 2011-06-22 18:26:03 UTC (rev 89453)
@@ -75,6 +75,8 @@
OwnPtr<ElementRecord> m_next;
};
+ unsigned stackDepth() const { return m_stackDepth; }
+
// Inlining this function is a (small) performance win on the parsing
// benchmark.
Element* top() const
@@ -167,6 +169,7 @@
ContainerNode* m_rootNode;
Element* m_headElement;
Element* m_bodyElement;
+ unsigned m_stackDepth;
};
inline bool isInHTMLNamespace(Node* node)
Modified: trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp (89452 => 89453)
--- trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp 2011-06-22 18:26:03 UTC (rev 89453)
@@ -341,10 +341,10 @@
};
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, HTMLDocument* document, bool reportErrors, bool usePreHTML5ParserQuirks)
+HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, HTMLDocument* document, bool reportErrors, bool usePreHTML5ParserQuirks, unsigned maximumDOMTreeDepth)
: m_framesetOk(true)
, m_document(document)
- , m_tree(document)
+ , m_tree(document, maximumDOMTreeDepth)
, m_reportErrors(reportErrors)
, m_isPaused(false)
, m_insertionMode(InitialMode)
@@ -359,11 +359,11 @@
// FIXME: Member variables should be grouped into self-initializing structs to
// minimize code duplication between these constructors.
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks)
+HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks, unsigned maximumDOMTreeDepth)
: m_framesetOk(true)
, m_fragmentContext(fragment, contextElement, scriptingPermission)
, m_document(fragment->document())
- , m_tree(fragment, scriptingPermission)
+ , m_tree(fragment, scriptingPermission, maximumDOMTreeDepth)
, m_reportErrors(false) // FIXME: Why not report errors in fragments?
, m_isPaused(false)
, m_insertionMode(InitialMode)
Modified: trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h (89452 => 89453)
--- trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h 2011-06-22 18:26:03 UTC (rev 89453)
@@ -55,13 +55,13 @@
class HTMLTreeBuilder {
WTF_MAKE_NONCOPYABLE(HTMLTreeBuilder); WTF_MAKE_FAST_ALLOCATED;
public:
- static PassOwnPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, HTMLDocument* document, bool reportErrors, bool usePreHTML5ParserQuirks)
+ static PassOwnPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, HTMLDocument* document, bool reportErrors, bool usePreHTML5ParserQuirks, unsigned maximumDOMTreeDepth)
{
- return adoptPtr(new HTMLTreeBuilder(parser, document, reportErrors, usePreHTML5ParserQuirks));
+ return adoptPtr(new HTMLTreeBuilder(parser, document, reportErrors, usePreHTML5ParserQuirks, maximumDOMTreeDepth));
}
- static PassOwnPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks)
+ static PassOwnPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks, unsigned maximumDOMTreeDepth)
{
- return adoptPtr(new HTMLTreeBuilder(parser, fragment, contextElement, scriptingPermission, usePreHTML5ParserQuirks));
+ return adoptPtr(new HTMLTreeBuilder(parser, fragment, contextElement, scriptingPermission, usePreHTML5ParserQuirks, maximumDOMTreeDepth));
}
~HTMLTreeBuilder();
@@ -116,8 +116,8 @@
AfterAfterFramesetMode,
};
- HTMLTreeBuilder(HTMLDocumentParser* parser, HTMLDocument*, bool reportErrors, bool usePreHTML5ParserQuirks);
- HTMLTreeBuilder(HTMLDocumentParser* parser, DocumentFragment*, Element* contextElement, FragmentScriptingPermission, bool usePreHTML5ParserQuirks);
+ HTMLTreeBuilder(HTMLDocumentParser*, HTMLDocument*, bool reportErrors, bool usePreHTML5ParserQuirks, unsigned maximumDOMTreeDepth);
+ HTMLTreeBuilder(HTMLDocumentParser*, DocumentFragment*, Element* contextElement, FragmentScriptingPermission, bool usePreHTML5ParserQuirks, unsigned maximumDOMTreeDepth);
void processToken(AtomicHTMLToken&);
Modified: trunk/Source/WebCore/page/Settings.cpp (89452 => 89453)
--- trunk/Source/WebCore/page/Settings.cpp 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/page/Settings.cpp 2011-06-22 18:26:03 UTC (rev 89453)
@@ -100,6 +100,7 @@
#endif
, m_pluginAllowedRunTime(numeric_limits<unsigned>::max())
, m_editingBehaviorType(editingBehaviorTypeForPlatform())
+ , m_maximumHTMLParserDOMTreeDepth(defaultMaximumHTMLParserDOMTreeDepth)
, m_isSpatialNavigationEnabled(false)
, m_isJavaEnabled(false)
, m_loadsImagesAutomatically(false)
Modified: trunk/Source/WebCore/page/Settings.h (89452 => 89453)
--- trunk/Source/WebCore/page/Settings.h 2011-06-22 18:12:43 UTC (rev 89452)
+++ trunk/Source/WebCore/page/Settings.h 2011-06-22 18:26:03 UTC (rev 89453)
@@ -388,6 +388,10 @@
void setUsePreHTML5ParserQuirks(bool flag) { m_usePreHTML5ParserQuirks = flag; }
bool usePreHTML5ParserQuirks() const { return m_usePreHTML5ParserQuirks; }
+ static const unsigned defaultMaximumHTMLParserDOMTreeDepth = 4096;
+ void setMaximumHTMLParserDOMTreeDepth(unsigned maximumHTMLParserDOMTreeDepth) { m_maximumHTMLParserDOMTreeDepth = maximumHTMLParserDOMTreeDepth; }
+ unsigned maximumHTMLParserDOMTreeDepth() const { return m_maximumHTMLParserDOMTreeDepth; }
+
void setHyperlinkAuditingEnabled(bool flag) { m_hyperlinkAuditingEnabled = flag; }
bool hyperlinkAuditingEnabled() const { return m_hyperlinkAuditingEnabled; }
@@ -436,6 +440,7 @@
#endif
unsigned m_pluginAllowedRunTime;
unsigned m_editingBehaviorType;
+ unsigned m_maximumHTMLParserDOMTreeDepth;
bool m_isSpatialNavigationEnabled : 1;
bool m_isJavaEnabled : 1;
bool m_loadsImagesAutomatically : 1;