Repository navigation
Release 1.3.2 - #265
Merged
Merged
Release 1.3.2#265
Conversation
A value or condition nesting parentheses deeply ended the process with a stack overflow, which no caller can catch: the parser recurses once per level of parentheses and math functions in values (calc(), min(), max(), clamp()) and of parentheses in @media and @supports conditions, also when a value is set through the CSSOM. On a 256 KB thread stack, about 430 parentheses in calc() were enough (.NET 8, before the JIT optimizes); on a 1 MB stack about 1,900. - Add CssParserOptions.MaxValueNestingDepth (default 64). A value or condition nested deeper is invalid. The value parsers run inside the converters, which do not see the options, so a parser makes its limit current while it builds (ValueNesting); values set through the CSSOM without a parser get the default - Add tests at depths that crashed before and at the limit, parsing on a 256 KB thread stack, and for the option per parser, per browsing context and its scope - Add calc() and @supports shapes to the nesting benchmark This is a mitigation, not a fix: parsing still recurses once per level, and only the limit stops it. Raising the limit brings the crash back.
Limit how deep values and conditions nest
Indexing a rule for the cascade looks into the arguments of :is(), :where() and :matches(), parsing them again at every level, so the cost grows quadratically with the nesting: computing a style with 75 nested :is() took 45 us, 35 us with the cap (allocating 132 KB, 82 KB with it). - Look into at most 8 levels; a rule nested deeper stays ungrouped, i.e., it is a candidate for every element, which is always correct - Add tests for the boundary and for matching beyond it - Add DeepSelectorBenchmarks with 10, 50 and 75 levels
Limit how deep the rule index looks into :is()
A computed style looks inherited declarations up through the snapshots of its parents. A property that no ancestor declares, e.g. visibility, was looked up through every ancestor for every element, so GetInnerText and IsVisible on the render tree grew quadratically with the depth (#262). - Keep the nearest declaration found for a name, or that there is none, on the snapshots passed; they never change, so each one is walked once per name. The entries are copied on write and published atomically - Leave the lookup of explicitly inherited declarations as it was - Add tests for deep chains, read deepest first and twice - Add DeepTreeBenchmarks for GetInnerText and IsVisible at 100 and 500 levels
The cascade allocated a new list for the matching rules of every element and grew the explicit style one declaration at a time; on a real document this growth and the garbage it leaves dominate the render tree. - Reuse the list of matching rules from element to element; it is taken and given back atomically, so a concurrent cascade gets its own - Size the explicit style for the declarations of the matching rules
…ache Remember inherited lookups on the way up
This was referenced Nov 3, 2026
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.
Types of Changes
Prerequisites
Please make sure you can check the following two boxes:
Contribution Type
What types of changes does your code introduce? Put an
xin all the boxes that apply:Description
This pull request introduces several improvements and fixes to the AngleSharp.Css library, focusing on parser robustness, standards compliance, and default styling. The most notable changes include the introduction of a configurable nesting limit for value and condition parsing, enhanced support for CSS functions and properties, updates to default form control styles to better match browsers, and several bug fixes and standards alignments.
These changes collectively improve the reliability, standards compliance, and usability of the AngleSharp.Css library.