pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/WebKit/WebKit/pull/60816

assets/global-52276e82f63bb403.css" /> Deeply nested <div> causes hang in parser (realistic example) by rniwa · Pull Request #60816 · WebKit/WebKit · GitHub
Skip to content

Deeply nested <div> causes hang in parser (realistic example)#60816

Merged
webkit-commit-queue merged 1 commit intoWebKit:mainfrom
rniwa:fix309208-html-parser-depth-limit-hang
Mar 18, 2026
Merged

Deeply nested <div> causes hang in parser (realistic example)#60816
webkit-commit-queue merged 1 commit intoWebKit:mainfrom
rniwa:fix309208-html-parser-depth-limit-hang

Conversation

@rniwa
Copy link
Member

@rniwa rniwa commented Mar 17, 2026

aff0077

Deeply nested <div> causes hang in parser (realistic example)
https://bugs.webkit.org/show_bug.cgi?id=309208
rdar://171763407

Reviewed by Wenson Hsieh and Ryan Reno.

This PR fixes an infinite loop in the HTML parser that occurs when parser hits the tree depth limit.

The HTML parser limits the DOM tree depth at 512. When this limit is reached, HTMLConstructionSite's
attachLater pops the top element from the open elements stack before pushing the new element, keeping
the depth at 512.

The problem is that this pop-and-push happens blindly — it can pop table-internal elements such as
table, tbody, tr, td, th, that the parser's insertion mode state machine depends on. This creates
an inconsistency between the insertion mode and the actual stack contents and causes an infinite loop.

With the test case specifically, td fails to get inserted into the stack of open elements, resulting
in the parser state to be InsertionMode::InCell without having td/th in the stack of open elements.
When `</table>` arrives in this state, HTMLTreeBuilder's closeTheCell fails silently and falls into
an infinite loop.

To fix this problem, this PR adds a new boolean state in HTMLConstructionSite, which indicates that
we've reached the maximum tree depth, and checks this state in HTMLTreeBuilder. When the flag is set,
we call resetInsertionModeAppropriately to correct the insertion mode to be consistent with the stack
of open elements.

Analysis done with Claude AI.

Test: fast/parser/html-parser-depth-limit-hang.html

* LayoutTests/fast/parser/html-parser-depth-limit-hang-expected.txt: Added.
* LayoutTests/fast/parser/html-parser-depth-limit-hang.html: Added.
* Source/WebCore/html/parser/HTMLConstructionSite.cpp:
(WebCore::HTMLConstructionSite::attachLater): Set m_hasReachedMaxDOMTreeDepth to true when we've\
reached the maximum tree depth of 512.
* Source/WebCore/html/parser/HTMLConstructionSite.h:
(WebCore::HTMLConstructionSite::hasReachedMaxDOMTreeDepth const): Added.
* Source/WebCore/html/parser/HTMLTreeBuilder.cpp:
(WebCore::HTMLTreeBuilder::processStartTagForInBody):
(WebCore::HTMLTreeBuilder::processStartTagForInTable):
(WebCore::HTMLTreeBuilder::processStartTag): Ditto.
(WebCore::HTMLTreeBuilder::processEndTagForInTableBody):
(WebCore::HTMLTreeBuilder::processEndTagForInRow):
(WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
(WebCore::HTMLTreeBuilder::processTableEndTagForInTable):

Canonical link: https://commits.webkit.org/309454@main

c8d3c22

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows Apple Internal
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe 🛠 win loading 🛠 ios-apple
✅ 🧪 bindings ✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 🧪 win-tests loading 🛠 mac-apple
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe ⏳ 🛠 vision-apple
✅ 🧪 ios-wk2-wpt ✅ 🧪 api-mac-debug ✅ 🛠 gtk3-libwebrtc
✅ 🧪 api-ios ✅ 🧪 mac-wk1 ✅ 🛠 gtk
✅ 🛠 ios-safer-cpp ✅ 🧪 mac-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 vision ✅ 🧪 mac-AS-debug-wk2 ✅ 🧪 api-gtk
✅ 🛠 vision-sim ✅ 🧪 mac-wk2-stress ✅ 🛠 playstation
✅ 🛠 🧪 unsafe-merge ✅ 🧪 vision-wk2 ✅ 🧪 mac-intel-wk2
✅ 🛠 tv ✅ 🛠 mac-safer-cpp
✅ 🛠 tv-sim
✅ 🛠 watch
✅ 🛠 watch-sim

@rniwa rniwa requested a review from cdumez as a code owner March 17, 2026 23:06
@rniwa rniwa self-assigned this Mar 17, 2026
@rniwa rniwa added the DOM For bugs specific to XML/HTML DOM elements (including parsing). label Mar 17, 2026
@rniwa rniwa force-pushed the fix309208-html-parser-depth-limit-hang branch from 8b0bf99 to c8d3c22 Compare March 17, 2026 23:48
Copy link
Member

@rreno rreno left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test case hangs for me on shipping Safari, nice.

@rniwa rniwa added the unsafe-merge-queue Applied to send a pull request to merge-queue, but skip building and testing label Mar 18, 2026
https://bugs.webkit.org/show_bug.cgi?id=309208
rdar://171763407

Reviewed by Wenson Hsieh and Ryan Reno.

This PR fixes an infinite loop in the HTML parser that occurs when parser hits the tree depth limit.

The HTML parser limits the DOM tree depth at 512. When this limit is reached, HTMLConstructionSite's
attachLater pops the top element from the open elements stack before pushing the new element, keeping
the depth at 512.

The problem is that this pop-and-push happens blindly — it can pop table-internal elements such as
table, tbody, tr, td, th, that the parser's insertion mode state machine depends on. This creates
an inconsistency between the insertion mode and the actual stack contents and causes an infinite loop.

With the test case specifically, td fails to get inserted into the stack of open elements, resulting
in the parser state to be InsertionMode::InCell without having td/th in the stack of open elements.
When `</table>` arrives in this state, HTMLTreeBuilder's closeTheCell fails silently and falls into
an infinite loop.

To fix this problem, this PR adds a new boolean state in HTMLConstructionSite, which indicates that
we've reached the maximum tree depth, and checks this state in HTMLTreeBuilder. When the flag is set,
we call resetInsertionModeAppropriately to correct the insertion mode to be consistent with the stack
of open elements.

Analysis done with Claude AI.

Test: fast/parser/html-parser-depth-limit-hang.html

* LayoutTests/fast/parser/html-parser-depth-limit-hang-expected.txt: Added.
* LayoutTests/fast/parser/html-parser-depth-limit-hang.html: Added.
* Source/WebCore/html/parser/HTMLConstructionSite.cpp:
(WebCore::HTMLConstructionSite::attachLater): Set m_hasReachedMaxDOMTreeDepth to true when we've\
reached the maximum tree depth of 512.
* Source/WebCore/html/parser/HTMLConstructionSite.h:
(WebCore::HTMLConstructionSite::hasReachedMaxDOMTreeDepth const): Added.
* Source/WebCore/html/parser/HTMLTreeBuilder.cpp:
(WebCore::HTMLTreeBuilder::processStartTagForInBody):
(WebCore::HTMLTreeBuilder::processStartTagForInTable):
(WebCore::HTMLTreeBuilder::processStartTag): Ditto.
(WebCore::HTMLTreeBuilder::processEndTagForInTableBody):
(WebCore::HTMLTreeBuilder::processEndTagForInRow):
(WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
(WebCore::HTMLTreeBuilder::processTableEndTagForInTable):

Canonical link: https://commits.webkit.org/309454@main
@webkit-commit-queue webkit-commit-queue force-pushed the fix309208-html-parser-depth-limit-hang branch from c8d3c22 to aff0077 Compare March 18, 2026 05:51
@webkit-commit-queue
Copy link
Collaborator

Committed 309454@main (aff0077): https://commits.webkit.org/309454@main

Reviewed commits have been landed. Closing PR #60816 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit aff0077 into WebKit:main Mar 18, 2026
@webkit-commit-queue webkit-commit-queue removed the unsafe-merge-queue Applied to send a pull request to merge-queue, but skip building and testing label Mar 18, 2026
@rniwa rniwa deleted the fix309208-html-parser-depth-limit-hang branch March 18, 2026 07:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DOM For bugs specific to XML/HTML DOM elements (including parsing).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy