summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Klocek <michal.klocek@qt.io>2018-03-16 05:33:23 +0000
committerMichal Klocek <michal.klocek@qt.io>2018-06-06 12:44:11 +0000
commitfa38dc29054d6895758bcc75e031a89597f3aaf6 (patch)
treea3081fc7fc76c2f6dd2038faa35c3ac6302462d6
parentdf086394e015eca4bcaaac71a3da87837d9b8988 (diff)
[Backport] CVE-2018-6145
HTML parser: Fix "HTML integration point" implementation in HTMLTreeBuilderSimulator. HTMLTreeBuilderSimulator assumed only <foreignObject> as an HTML integration point. This CL adds <annotation-xml>, <desc>, and SVG <title>. Bug: 805924 Reviewed-on: https://chromium-review.googlesource.com/964038 Change-Id: If99f8fdeb9b2b594925f04491d004709d8f774ad Reviewed-by: Kai Koehne <kai.koehne@qt.io> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--chromium/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html-integration-point.html31
-rw-r--r--chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp71
-rw-r--r--chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.h2
3 files changed, 92 insertions, 12 deletions
diff --git a/chromium/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html-integration-point.html b/chromium/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html-integration-point.html
new file mode 100644
index 00000000000..be6b42d07d0
--- /dev/null
+++ b/chromium/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html-integration-point.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/parsing.html#tree-construction:html-integration-point">
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<math><annotation-xml id="point-1" encoding="text/html"><xmp>&lt;/xmp&gt;&lt;img></xmp></annotation-xml></math>
+<math><annotation-xml id="point-2" encoding="application/xhtml+xml"><style>&lt;/style&gt;&lt;img></style></annotation-xml></math>
+<svg><foreignObject id="point-3"><iframe>&lt;/iframe&gt;&lt;img></iframe></foreignObject></svg>
+<svg><desc id="point-4"><noembed>&lt;/noembed&gt;&lt;img></noembed></desc></svg>
+<svg><title id="point-5"><noframes>&lt;/noframes&gt;&lt;img></noframes></title></svg>
+
+<script>
+function generate_test(id) {
+ return () => {
+ let point = document.querySelector('#' + id);
+ assert_not_equals(point.namespaceURI, 'http://www.w3.org/1999/xhtml');
+ let rawTextElement = point.firstChild;
+ assert_equals(rawTextElement.namespaceURI, 'http://www.w3.org/1999/xhtml');
+ assert_equals(rawTextElement.textContent.substr(0, 4), '&lt;',
+ 'Entity references should not be decoded.');
+ };
+}
+
+test(generate_test('point-1'), 'MathML annotation-xml with encoding=text/html should be an HTML integration point');
+test(generate_test('point-2'), 'MathML annotation-xml with encoding=application/xhtml+xml should be an HTML integration point');
+test(generate_test('point-3'), 'SVG foreignObject should be an HTML integration point');
+test(generate_test('point-4'), 'SVG desc should be an HTML integration point');
+test(generate_test('point-5'), 'SVG title should be an HTML integration point');
+</script>
+</body>
diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp
index 34a3fbcdf96..1029c22a1af 100644
--- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp
+++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp
@@ -82,13 +82,6 @@ static bool TokenExitsForeignContent(const CompactHTMLToken& token) {
token.GetAttributeItem(sizeAttr)));
}
-static bool TokenExitsSVG(const CompactHTMLToken& token) {
- // FIXME: It's very fragile that we special case foreignObject here to be
- // case-insensitive.
- return DeprecatedEqualIgnoringCase(token.Data(),
- SVGNames::foreignObjectTag.LocalName());
-}
-
static bool TokenExitsMath(const CompactHTMLToken& token) {
// FIXME: This is copied from HTMLElementStack::isMathMLTextIntegrationPoint
// and changed to use threadSafeMatch.
@@ -148,10 +141,10 @@ HTMLTreeBuilderSimulator::SimulatedToken HTMLTreeBuilderSimulator::Simulate(
namespace_stack_.push_back(kMathML);
if (InForeignContent() && TokenExitsForeignContent(token))
namespace_stack_.pop_back();
- if ((namespace_stack_.back() == SVG && TokenExitsSVG(token)) ||
- (namespace_stack_.back() == kMathML && TokenExitsMath(token)))
+ if (IsHTMLIntegrationPointForStartTag(token) ||
+ (namespace_stack_.back() == kMathML && TokenExitsMath(token))) {
namespace_stack_.push_back(HTML);
- if (!InForeignContent()) {
+ } else if (!InForeignContent()) {
// FIXME: This is just a copy of Tokenizer::updateStateFor which uses
// threadSafeMatches.
if (ThreadSafeMatch(tag_name, textareaTag) ||
@@ -203,8 +196,7 @@ HTMLTreeBuilderSimulator::SimulatedToken HTMLTreeBuilderSimulator::Simulate(
ThreadSafeMatch(tag_name, SVGNames::svgTag)) ||
(namespace_stack_.back() == kMathML &&
ThreadSafeMatch(tag_name, MathMLNames::mathTag)) ||
- (namespace_stack_.Contains(SVG) && namespace_stack_.back() == HTML &&
- TokenExitsSVG(token)) ||
+ IsHTMLIntegrationPointForEndTag(token) ||
(namespace_stack_.Contains(kMathML) &&
namespace_stack_.back() == HTML && TokenExitsMath(token))) {
namespace_stack_.pop_back();
@@ -226,4 +218,59 @@ HTMLTreeBuilderSimulator::SimulatedToken HTMLTreeBuilderSimulator::Simulate(
return simulated_token;
}
+// https://html.spec.whatwg.org/multipage/parsing.html#html-integration-point
+bool HTMLTreeBuilderSimulator::IsHTMLIntegrationPointForStartTag(
+ const CompactHTMLToken& token) const {
+ DCHECK(token.GetType() == HTMLToken::kStartTag) << token.GetType();
+
+ Namespace tokens_ns = namespace_stack_.back();
+ const String& tag_name = token.Data();
+ if (tokens_ns == kMathML) {
+ if (!ThreadSafeMatch(tag_name, MathMLNames::annotation_xmlTag))
+ return false;
+ if (auto* encoding = token.GetAttributeItem(MathMLNames::encodingAttr)) {
+ return EqualIgnoringASCIICase(encoding->Value(), "text/html") ||
+ EqualIgnoringASCIICase(encoding->Value(), "application/xhtml+xml");
+ }
+ } else if (tokens_ns == SVG) {
+ // FIXME: It's very fragile that we special case foreignObject here to be
+ // case-insensitive.
+ if (DeprecatedEqualIgnoringCase(tag_name,
+ SVGNames::foreignObjectTag.LocalName()))
+ return true;
+ return ThreadSafeMatch(tag_name, SVGNames::descTag) ||
+ ThreadSafeMatch(tag_name, SVGNames::titleTag);
+ }
+ return false;
+}
+
+// https://html.spec.whatwg.org/multipage/parsing.html#html-integration-point
+bool HTMLTreeBuilderSimulator::IsHTMLIntegrationPointForEndTag(
+ const CompactHTMLToken& token) const {
+ if (token.GetType() != HTMLToken::kEndTag)
+ return false;
+
+ // If it's inside an HTML integration point, the top namespace is
+ // HTML, and its next namespace is not HTML.
+ if (namespace_stack_.back() != HTML)
+ return false;
+ if (namespace_stack_.size() < 2)
+ return false;
+ Namespace tokens_ns = namespace_stack_[namespace_stack_.size() - 2];
+
+ const String& tag_name = token.Data();
+ if (tokens_ns == kMathML)
+ return ThreadSafeMatch(tag_name, MathMLNames::annotation_xmlTag);
+ if (tokens_ns == SVG) {
+ // FIXME: It's very fragile that we special case foreignObject here to be
+ // case-insensitive.
+ if (DeprecatedEqualIgnoringCase(tag_name,
+ SVGNames::foreignObjectTag.LocalName()))
+ return true;
+ return ThreadSafeMatch(tag_name, SVGNames::descTag) ||
+ ThreadSafeMatch(tag_name, SVGNames::titleTag);
+ }
+ return false;
+}
+
} // namespace blink
diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.h
index 3aae7853f3a..2fd9f921ce3 100644
--- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.h
+++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.h
@@ -64,6 +64,8 @@ class CORE_EXPORT HTMLTreeBuilderSimulator {
private:
bool InForeignContent() const { return namespace_stack_.back() != HTML; }
+ bool IsHTMLIntegrationPointForStartTag(const CompactHTMLToken&) const;
+ bool IsHTMLIntegrationPointForEndTag(const CompactHTMLToken&) const;
HTMLParserOptions options_;
State namespace_stack_;