Open Bug 1979396 Opened 1 year ago Updated 1 year ago

stack-overflow in [@ selectors::parser::parse_selector] with deeply-nested `@media` queries in a stylesheet

Categories

(Core :: CSS Parsing and Computation, defect)

defect

Tracking

()

Tracking Status
firefox143 --- affected

People

(Reporter: tsmith, Unassigned)

References

(Blocks 1 open bug, )

Details

(Keywords: crash, pernosco)

Crash Data

Attachments

(7 files)

Found with m-c 20250627-262215ce9b55 (--enable-address-sanitizer)

This was found by visiting a live website with an ASan build.

STR:

  • Launch browser and visit site

This issue was triggered by visiting https://www.aflglobal.com/en/Solutions/Service-Provider/Edge-Computing-Solutions. A Pernosco session is available here: https://pernos.co/debug/KIPSYVtO8o9n1OvICNwbxA/index.html

==2824659==ERROR: AddressSanitizer: stack-overflow on address 0x7fffcf121e68 (pc 0x5555556ad3d6 bp 0x7fffcf1226b0 sp 0x7fffcf121e70 T6)
    #0 0x5555556ad3d6 in __asan_memcpy _asan_rtl_:3
    #1 0x7fffea9ae498 in cssparser::tokenizer::next_token::h7844f1a592a2c78d /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/tokenizer.rs:693:5
    #2 0x7fffea9aba89 in cssparser::tokenizer::Tokenizer::next::h43ee4f4e40489c5e /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/tokenizer.rs:267:9
    #3 0x7fffea9aba89 in cssparser::parser::Parser::next_including_whitespace_and_comments::h793a06d662649f92 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:668:18
    #4 0x7fffea9b8638 in cssparser::parser::Parser::next_including_whitespace::h2c2e4c5bc930e64e /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:622:19
    #5 0x7fffed35ad1b in selectors::parser::parse_qualified_name::h16047ff0a9ec289f /builds/worker/checkouts/gecko/servo/components/selectors/parser.rs:2963:19
    #6 0x7fffed34eb55 in selectors::parser::parse_type_selector::hd252176424f4b825 /builds/worker/checkouts/gecko/servo/components/selectors/parser.rs:2838:11
    #7 0x7fffed34eb55 in selectors::parser::parse_compound_selector::hba83dfd6f99f7713 /builds/worker/checkouts/gecko/servo/components/selectors/parser.rs:3241:8
    #8 0x7fffed34eb55 in selectors::parser::parse_selector::h7a2f0b13d608229c /builds/worker/checkouts/gecko/servo/components/selectors/parser.rs:2763:21
    #9 0x7fffed34c189 in selectors::parser::SelectorList$LT$Impl$GT$::parse_with_state::_$u7b$$u7b$closure$u7d$$u7d$::hbd295363f593e527 /builds/worker/checkouts/gecko/servo/components/selectors/parser.rs:573:36
    #10 0x7fffed34c189 in cssparser::parser::Parser::parse_entirely::h3257f9b6e1b6749f /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:693:22
    #11 0x7fffed34c189 in cssparser::parser::parse_until_before::hff89329d5c3447fe /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:1063:18
    #12 0x7fffed34c189 in cssparser::parser::Parser::parse_until_before::h54307f71941d088c /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:801:9
    #13 0x7fffed34c189 in selectors::parser::SelectorList$LT$Impl$GT$::parse_with_state::h1ebe578b0afd8d80 /builds/worker/checkouts/gecko/servo/components/selectors/parser.rs:571:34
    #14 0x7fffed3fed59 in selectors::parser::SelectorList$LT$Impl$GT$::parse::h919241c1b99ed571 /builds/worker/checkouts/gecko/servo/components/selectors/parser.rs:513:9
    #15 0x7fffed3fed59 in _$LT$style..stylesheets..rule_parser..NestedRuleParser$u20$as$u20$cssparser..rules_and_declarations..QualifiedRuleParser$GT$::parse_prelude::h44d9f075117a8961 /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:984:9
    #16 0x7fffed3fed59 in cssparser::rules_and_declarations::parse_qualified_rule::_$u7b$$u7b$closure$u7d$$u7d$::h971e8d7077ae350f /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/rules_and_declarations.rs:533:54
    #17 0x7fffed3fed59 in cssparser::parser::Parser::parse_entirely::hc3d7dfdbec7929ec /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:693:22
    #18 0x7fffed3fed59 in cssparser::parser::parse_until_before::hd242b9e05b176045 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:1063:18
    #19 0x7fffed3fed59 in cssparser::parser::Parser::parse_until_before::h24acabd5ff9f7712 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:801:9
    #20 0x7fffed3fed59 in cssparser::rules_and_declarations::parse_qualified_rule::h3a4c9965e82baf30 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/rules_and_declarations.rs:533:15
    #21 0x7fffed3fb06b in _$LT$cssparser..rules_and_declarations..RuleBodyParser$LT$P$C$I$C$E$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$::next::hfe0df296b010eb41 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/rules_and_declarations.rs:307:25
    #22 0x7fffed3fb06b in style::stylesheets::rule_parser::NestedRuleParser::parse_nested::_$u7b$$u7b$closure$u7d$$u7d$::h3c9bfd889caca67e /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:571:38
    #23 0x7fffed3f2195 in style::stylesheets::rule_parser::NestedRuleParser::nest_for_rule::h0dd052576ae44d88 /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:544:17
    #24 0x7fffed3f2195 in style::stylesheets::rule_parser::NestedRuleParser::parse_nested::hefc435e3493f44ac /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:565:9
    #25 0x7fffed3f2195 in style::stylesheets::rule_parser::NestedRuleParser::parse_nested_rules::hf9f112d238e7fa9d /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:554:21
    #26 0x7fffed3f2195 in _$LT$style..stylesheets..rule_parser..NestedRuleParser$u20$as$u20$cssparser..rules_and_declarations..AtRuleParser$GT$::parse_block::hda21e37d5265d3ee /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:818:28
    #27 0x7fffed3fc99d in cssparser::rules_and_declarations::parse_at_rule::_$u7b$$u7b$closure$u7d$$u7d$::h6cabb9b05e507843 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/rules_and_declarations.rs:473:55
    #28 0x7fffed3fc99d in cssparser::parser::Parser::parse_entirely::h2aea0417818a0a7c /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:693:22
    #29 0x7fffed3fc99d in cssparser::parser::parse_nested_block::hb60aed3bbef66231 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:1143:18
    #30 0x7fffed3fc99d in cssparser::rules_and_declarations::parse_at_rule::h40269055a662d0a1 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/rules_and_declarations.rs:473:21
    #31 0x7fffed3fc99d in _$LT$cssparser..rules_and_declarations..RuleBodyParser$LT$P$C$I$C$E$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$::next::hfe0df296b010eb41 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/rules_and_declarations.rs:262:33
    #32 0x7fffed3fc99d in style::stylesheets::rule_parser::NestedRuleParser::parse_nested::_$u7b$$u7b$closure$u7d$$u7d$::h3c9bfd889caca67e /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:571:38
    #33 0x7fffed3f2195 in style::stylesheets::rule_parser::NestedRuleParser::nest_for_rule::h0dd052576ae44d88 /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:544:17
    #34 0x7fffed3f2195 in style::stylesheets::rule_parser::NestedRuleParser::parse_nested::hefc435e3493f44ac /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:565:9
    #35 0x7fffed3f2195 in style::stylesheets::rule_parser::NestedRuleParser::parse_nested_rules::hf9f112d238e7fa9d /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:554:21
    #36 0x7fffed3f2195 in _$LT$style..stylesheets..rule_parser..NestedRuleParser$u20$as$u20$cssparser..rules_and_declarations..AtRuleParser$GT$::parse_block::hda21e37d5265d3ee /builds/worker/checkouts/gecko/servo/components/style/stylesheets/rule_parser.rs:818:28
    #37 0x7fffed3fc99d in cssparser::rules_and_declarations::parse_at_rule::_$u7b$$u7b$closure$u7d$$u7d$::h6cabb9b05e507843 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/rules_and_declarations.rs:473:55
    #38 0x7fffed3fc99d in cssparser::parser::Parser::parse_entirely::h2aea0417818a0a7c /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:693:22
    #39 0x7fffed3fc99d in cssparser::parser::parse_nested_block::hb60aed3bbef66231 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/parser.rs:1143:18
    #40 0x7fffed3fc99d in cssparser::rules_and_declarations::parse_at_rule::h40269055a662d0a1 /builds/worker/checkouts/gecko/third_party/rust/cssparser/src/rules_and_declarations.rs:473:21
    ...
Crash Signature: [@ stackoverflow | selectors::parser::parse_selector<T> ] → [@ stackoverflow | selectors::parser::parse_selector<T> ] [@ stackoverflow | cssparser::parser::Parser::next_including_whitespace ]

This seems to be a regression, but an old one:
Last good revision: b109fa8d1c86af435d42db733a3975891db26095 (2023-04-20)
First bad revision: 38967ad7e8f29d5aeb963ccc61480124a6bae15a (2023-04-21)
Pushlog:
https://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=b109fa8d1c86af435d42db733a3975891db26095&tochange=38967ad7e8f29d5aeb963ccc61480124a6bae15a

emilio, anything in that pushlog jump out at you? In any case, probably S3 given the low crash volume & given that we've been shipping with this for a while.

Severity: -- → S3
Flags: needinfo?(emilio)

I've got a reduced testcase - the key part seems to be this stylesheet:
https://webapps.aflglobal.com/InteractiveMaps/edge_solutions/css/webmap.css

which has a bunch of accidentally-unclosed @media style rules like this:

@media only screen and (max-width: 447px) {.newLinks {left: 333px;top: 58px;}
@media only screen and (max-width: 441px) {.newLinks {left: 327px;top: 58px;}
@media only screen and (max-width: 434px) {.newLinks {left: 323px;top: 58px;}
@media only screen and (max-width: 427px) {.newLinks {left: 317px;top: 56px;}
@media only screen and (max-width: 419px) {.newLinks {left: 309px;top: 55px;}

The } at the end of each line is closing the .newLinks rule, but the media-query rule is left unclosed, so the next line's @media rule ends up nested, I think. And presumably we're running out of stack space due to deep recursion from parsing such a deeply nested pile of rules there.

This testcase (same as #2 but just more copies of the unclosed @media line) crashes in builds much further back, in builds from before the regression range in comment 2.

I've dialed it up to 300, but even lower amounts (200ish I think) are enough to trigger the crash in older builds. So: the regression range in comment 2 isn't when this crash was introduced, but just when it got a bit easier to trigger (not requiring as much nesting).

This testcase here starts crashing as-of this regression range:
INFO: Last good revision: 5d73549d363f2a52854ff43fabac9c6fd05b90b0 (2018-04-19)
INFO: First bad revision: cc0d7de218cb0c260c8ba0cf6637845ad2222f49 (2018-04-20)
INFO: Pushlog:
https://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=5d73549d363f2a52854ff43fabac9c6fd05b90b0&tochange=cc0d7de218cb0c260c8ba0cf6637845ad2222f49

In that range, this is from "Bug 1455115 - Enable parallel parsing", which toggled layout.css.parsing.parallel to true. I confirmed that the "first-bad" build there (2018-04-20) switches to being "good" if I toggle that pref to false, so that was the relevant change in that pushlog that made this crashy.

Presumably parallel parsing has some stack-space overhead for this sort of nested-media-query scenario which ends up being crashy.

Summary: stack-overflow in [@ selectors::parser::parse_selector] → stack-overflow in [@ selectors::parser::parse_selector] with deeply-nested `@media` queries in a stylesheet

(In reply to Daniel Holbert [:dholbert] from comment #3)

emilio, anything in that pushlog jump out at you? In any case, probably S3 given the low crash volume & given that we've been shipping with this for a while.

From the pushlog in comment 2, probably bug 1821227 which updated rustc.

Presumably parallel parsing has some stack-space overhead for this sort of nested-media-query scenario which ends up being crashy.

Not really, what happens is that style worker threads have smaller stacks than the main thread...

Something we could do is to use something similar to https://searchfox.org/mozilla-central/rev/ab26427a8d31be475be11bbae0e04c84cc7f20ef/servo/components/style/context.rs#623 to avoid crashing if we're close to the stack limit...

Probably https://searchfox.org/mozilla-central/rev/ab26427a8d31be475be11bbae0e04c84cc7f20ef/servo/components/style/stylesheets/rule_parser.rs#563 or so is a good place to put this in.

Flags: needinfo?(emilio)

This seems to work for me, I'm checking whether we run close to the limits in tests or what not, but I think it'd be reasonable. WDYT?

Flags: needinfo?(dholbert)

Seems reasonable - thanks!

Flags: needinfo?(dholbert)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: