Chrome · Parser
CVE-2026-79073
Logic Error in Parser
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifthird_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash.html |
modified | |
ifthird_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash.html |
modified | |
ifthird_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash.html |
modified | |
ifthird_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash.html |
modified |
Files Changed
third_party/blink/renderer/core/html/parser/html_construction_site.ccthird_party/blink/renderer/core/html/parser/html_construction_site.hthird_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash-expected.txtthird_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash.htmlthird_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash-expected.txtthird_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash.htmlthird_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash-expected.txtthird_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash.htmlthird_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash-expected.txtthird_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash.html
Patch
From 5d50303b9695b52ec773f27a6ecb3c2ca464f532 Mon Sep 17 00:00:00 2001
From: Noam Rosenthal <nrosenthal@chromium.org>
Date: Mon, 20 Jul 2026 15:36:21 -0700
Subject: [PATCH] HTML parser: Drop a node the adoption agency cannot reinsert
Make a few check when moving around nodes with AAA.
The tests are internal temporarily until the upstream WPT and spec PR
land, but that process shouldn't delay fixing the crash.
See https://github.com/whatwg/html/pull/12709
Bug: 536662911
Change-Id: Ia357a2efea8029129b68b7fe647de4d7ba450b42
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8124514
Commit-Queue: Noam Rosenthal <nrosenthal@google.com>
Reviewed-by: David Baron <dbaron@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1664983}
---
diff --git a/third_party/blink/renderer/core/html/parser/html_construction_site.cc b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
index 94ed802..8448e69 100644
--- a/third_party/blink/renderer/core/html/parser/html_construction_site.cc
+++ b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
@@ -293,6 +293,21 @@
DCHECK_EQ(task.operation,
HTMLConstructionSiteTask::kInsertAlreadyParsedChild);
+ // See https://github.com/whatwg/html/pull/12709
+ if (Document* parentDoc = DynamicTo<Document>(task.parent.Get())) {
+ if (parentDoc->documentElement()) {
+ if (task.child->parentNode()) {
+ task.child->parentNode()->ParserRemoveChild(*task.child);
+ }
+ return;
+ }
+ } else if (task.child->ContainsIncludingHostElements(*task.parent)) {
+ if (task.child->parentNode()) {
+ task.child->parentNode()->ParserRemoveChild(*task.child);
+ }
+ return;
+ }
+
Insert(task);
}
@@ -1224,7 +1239,7 @@
void HTMLConstructionSite::InsertAlreadyParsedChild(HTMLStackItem* new_parent,
HTMLStackItem* child) {
if (new_parent->CausesFosterParenting()) {
- FosterParent(child->GetNode());
+ FosterParentAlreadyParsedChild(child->GetNode());
return;
}
@@ -1613,6 +1628,15 @@
QueueTask(task, true);
}
+void HTMLConstructionSite::FosterParentAlreadyParsedChild(Node* child) {
+ HTMLConstructionSiteTask task(
+ HTMLConstructionSiteTask::kInsertAlreadyParsedChild);
+ FindFosterSite(task);
+ task.child = child;
+ DCHECK(task.parent);
+ QueueTask(task, true);
+}
+
void HTMLConstructionSite::PendingText::Trace(Visitor* visitor) const {
visitor->Trace(parent);
visitor->Trace(next_child);
diff --git a/third_party/blink/renderer/core/html/parser/html_construction_site.h b/third_party/blink/renderer/core/html/parser/html_construction_site.h
index 987bb598..968906f 100644
--- a/third_party/blink/renderer/core/html/parser/html_construction_site.h
+++ b/third_party/blink/renderer/core/html/parser/html_construction_site.h
@@ -189,6 +189,7 @@
bool ShouldFosterParent() const;
void FosterParent(Node*);
+ void FosterParentAlreadyParsedChild(Node*);
bool IndexOfFirstUnopenFormattingElement(
unsigned& first_unopen_element_index) const;
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash-expected.txt b/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash.html b/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash.html
new file mode 100644
index 0000000..edf7f06
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<div id=ca><b><p id=fb><script>
+window.fb = document.getElementById('fb');
+window.ca = document.getElementById('ca');
+document.body.appendChild(window.fb);
+window.fb.appendChild(window.ca);
+</script></b></div>
+<script>
+if (window.testRunner) {
+ testRunner.notifyDone();
+}
+</script>
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash-expected.txt b/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash.html b/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash.html
new file mode 100644
index 0000000..a2d7238
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<table><tbody><tr><b><div id=fb><script>
+window.fb = document.getElementById('fb');
+window.other = document.implementation.createHTMLDocument('');
+window.other.documentElement.remove();
+window.other.appendChild(document.querySelector('table'));
+</script></b></table>
+<script>
+if (window.testRunner) {
+ testRunner.notifyDone();
+}
+</script>
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash-expected.txt b/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash.html b/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash.html
new file mode 100644
index 0000000..f45e242
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<div id=ca><b><i><p id=fb><script>
+window.fb = document.getElementById('fb');
+window.ca = document.getElementById('ca');
+document.body.appendChild(window.fb);
+window.fb.appendChild(window.ca);
+</script></i></b></div>
+<script>
+if (window.testRunner) {
+ testRunner.notifyDone();
+}
+</script>
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash-expected.txt b/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash.html b/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash.html
new file mode 100644
index 0000000..1bb1fec
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<div id=ca><b><p id=fb><script>
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash-expected.txt b/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash.html b/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash.html
new file mode 100644
index 0000000..edf7f06
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-cycle-crash.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<div id=ca><b><p id=fb><script>
+window.fb = document.getElementById('fb');
+window.ca = document.getElementById('ca');
+document.body.appendChild(window.fb);
+window.fb.appendChild(window.ca);
+</script></b></div>
+<script>
+if (window.testRunner) {
+ testRunner.notifyDone();
+}
+</script>
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash-expected.txt b/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash.html b/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash.html
new file mode 100644
index 0000000..a2d7238
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-document-target-crash.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<table><tbody><tr><b><div id=fb><script>
+window.fb = document.getElementById('fb');
+window.other = document.implementation.createHTMLDocument('');
+window.other.documentElement.remove();
+window.other.appendChild(document.querySelector('table'));
+</script></b></table>
+<script>
+if (window.testRunner) {
+ testRunner.notifyDone();
+}
+</script>
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash-expected.txt b/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash.html b/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash.html
new file mode 100644
index 0000000..f45e242
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-inner-loop-cycle-crash.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<div id=ca><b><i><p id=fb><script>
+window.fb = document.getElementById('fb');
+window.ca = document.getElementById('ca');
+document.body.appendChild(window.fb);
+window.fb.appendChild(window.ca);
+</script></i></b></div>
+<script>
+if (window.testRunner) {
+ testRunner.notifyDone();
+}
+</script>
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash-expected.txt b/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash.html b/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash.html
new file mode 100644
index 0000000..1bb1fec
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-shadow-cycle-crash.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<div id=ca><b><p id=fb><script>
+window.fb = document.getElementById('fb');
+window.ca = document.getElementById('ca');
+var host = document.createElement('span');
+var root = host.attachShadow({mode:'open'});
+document.body.appendChild(window.fb);
+window.fb.appendChild(host);
+root.appendChild(window.ca);
+</script></b></div>
+<script>
+if (window.testRunner) {
+ testRunner.notifyDone();
+}
+</script>
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-template-cycle-crash-expected.txt b/third_party/blink/web_tests/fast/parser/adoption-agency-template-cycle-crash-expected.txt
new file mode 100644
index 0000000..c2541f4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-template-cycle-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash.
diff --git a/third_party/blink/web_tests/fast/parser/adoption-agency-template-cycle-crash.html b/third_party/blink/web_tests/fast/parser/adoption-agency-template-cycle-crash.html
new file mode 100644
index 0000000..ebd0cc5
--- /dev/null
+++ b/third_party/blink/web_tests/fast/parser/adoption-agency-template-cycle-crash.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+</script>
+<div id=ca><b><p id=fb><script>
+window.fb = document.getElementById('fb');
+window.ca = document.getElementById('ca');
+var tmpl = document.createElement('template');
+document.body.appendChild(window.fb);
+window.fb.appendChild(tmpl);
+tmpl.content.appendChild(window.ca);
+</script></b></div>
+<script>
+if (window.testRunner) {
+ testRunner.notifyDone();
+}
+</script>
+PASS if no crash.
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page