Judge a renamed element by the name the author wrote (#445, #450) - #479
Merged
Conversation
ElementAndAttributePolicyBasedSanitizerPolicy.writeOpenTag decided two things by the name an ElementPolicy emitted an element under, while the lexer, the tag balancer, deferOpenTag and disallowTextIn all go by the name the author wrote. Text: allowElements(ElementPolicy, String...) and allowTextIn register the input name as a text container, but the gate looked up the adjusted name, so a rename to a name not allowed in its own right kept the element and dropped its text (#445). The gate now follows the input name. A rename into an element whose content a browser reads literally, such as style, still needs allowTextIn on that name, so a rename is not a way around the bar the builder sets for raw-text elements. Void-ness: the push onto the open-element stack keyed on the adjusted name, so a void element renamed to a non-void one left an entry that no close tag ever popped (#450). The renamed element stayed open until its parent closed, swallowing every sibling after it, and since the balancer never counts a void input, such entries nested past its limit. The push now keys on the input name: a void input renamed to a non-void output is emitted and closed at once, and a non-void input renamed to a void output gets an entry with nothing to close, so its own close tag pops it rather than an outer element of the same input name. Fixes #445 Fixes #450 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Ydng7gBm6Ax5zfwt4vZip
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #445 and #450, which share one cause:
writeOpenTagin the policy class judged a renamed element by the name theElementPolicyemitted, while the lexer, the tag balancer,deferOpenTaganddisallowTextInall go by the name the author wrote.#445
allowElements(policy, "span")registersspanas a text container, but the text gate looked up the adjusted name, sospanrenamed todivwithoutallowElements("div")came out as<div></div>. The gate now follows the input name. One hold-out: a rename into an element whose content a browser reads literally, such asstyle, still needsallowTextInon that name, so a rename cannot get around the bar the builder sets for raw-text elements.#450 The push onto the policy's open-element stack keyed on the adjusted name, so
brrenamed tospanleft an entry no close tag ever popped. The span stayed open until its parent closed and swallowed every sibling, and because the balancer never counts a void input, 3000<br>came out as 3000 nested spans, past the balancer's cap of 256. The push now keys on the input name: a void input renamed to a non-void output is emitted and closed at once, giving<p>a<span></span>bcd</p><p>e</p>for the issue's example.The reverse rename,
spantobr, now gets a stack entry with nothing to close, so its own close tag pops it. Before, the close tag found the nearest open element of the same input name and ended an outer span early; anddisallowTextIn("span")now holds for it, as it does for every other renamed element.Seven regression tests in
HtmlPolicyBuilderTestpin each shape, including the nesting case. Both existing rename tests keep passing unchanged. Verified with./mvnw clean verifyon JDK 11, 17, 21 and 25.🤖 Generated with Claude Code
https://claude.ai/code/session_014Ydng7gBm6Ax5zfwt4vZip