Merge pull request #2547 from Silvertree2010/fix/h3260-svg-css-parser-applies-the-secon

Skip whole CSS at-rule blocks in the SVG parser by brace depth
This commit is contained in:
BFlat
2026-10-29 10:08:59 +07:00
committed by GitHub
2 changed files with 33 additions and 3 deletions
+21 -3
View File
@@ -510,12 +510,30 @@ fn parse_css(css: &str, sheet: &mut StyleSheet) -> Result<(), Error> {
let mut rest = css.as_str();
while let Some(open) = rest.find('{') {
let sel = rest[..open].trim();
if sel.starts_with('@') {
// Skip the whole at-rule block, matching nested braces by depth.
let mut depth = 0usize;
let mut end = None;
for (i, c) in rest[open..].char_indices() {
match c {
'{' => depth = depth.saturating_add(1),
'}' => {
depth = depth.saturating_sub(1);
if depth == 0 {
end = Some(open + i + 1);
break;
}
}
_ => {}
}
}
let Some(end) = end else { break };
rest = &rest[end..];
continue;
}
let Some(close) = rest[open..].find('}') else { break };
let body = &rest[open + 1..open + close];
rest = &rest[open + close + 1..];
if sel.starts_with('@') {
continue;
}
let mut decls = parse_decls(body);
sheet.decls = sheet.decls.saturating_add(decls.len());
if sheet.decls > MAX_CSS_DECLARATIONS {
+12
View File
@@ -422,3 +422,15 @@ fn font_size_percentage_resolves_against_the_parent_font_size() {
assert!(matches!(shapes[0].2.geom, Geom::Rect { w, .. } if w == expected), "{body}: {:?}", shapes[0].2.geom);
}
}
#[test]
fn at_rule_blocks_are_skipped_by_brace_depth() {
let mut sheet = StyleSheet::default();
parse_css("@media print { .a{fill:#ff0000} .b{fill:#0000ff} } .c{fill:red}", &mut sheet).unwrap();
assert_eq!(sheet.rules.len(), 1);
assert_eq!(sheet.rules[0].classes, vec!["c".to_string()]);
let mut sheet = StyleSheet::default();
parse_css("@media x { @supports y { .c{} } .d{} } .e{fill:red}", &mut sheet).unwrap();
assert_eq!(sheet.rules.len(), 1);
assert_eq!(sheet.rules[0].classes, vec!["e".to_string()]);
}