Summary
Deeply nested { in CSS input causes a crash. On Linux/CI the panic message is attempt to add with overflow in lightningcss/src/printer.rs. On macOS the same input causes a stack overflow via mutual recursion between StyleRule::to_css_base and CssRuleList::to_css.
Affected versions
lightningcss 1.0.0-alpha.70 (confirmed)
- Likely all versions with the same recursive printer structure
Reproducer
Minimized input (525 bytes) found via cargo-fuzz. Decode this base64 to a file and pass it to the Printer:
ACwACQkAVgAJVkEAAAlWewB7TgB7AHtOU04AeyYscywmLAB7AHsmLHMsJiwAe3VzZXItaW52YWxpZAB7TiYsAHsALAB7Tk5TAHsAewAsAAkJAFYACVZBAAAJVnsAe04AewB7TlNOAHsmLHMsJiwAewB7JixzLCYsAHt1c2UAe04mLAB7ACwAe05OUwB7AHtOAHsmLHMsJiwAewB7JixzLCYsAHsAe04mLAB7ACwAewB7TgB7AHtOU04AewB+entze04AewB7TgB7AHtOU04AeyYsc3sAe05TAHtOAHsAe05TTgB7AH56e3N7TgB7AHtOTgB7JixzLCYsAHsAeyYscywmLAB7AHtOJiwAewAsTiYsAHsALAB7Tk5TAHsAe04AeyYscywmLAB7AHsmLHMsJiwAewB7TiYsAHsALAB7AHtOAHsAe05TTgB7AH56e3N7TgB7AHtOAHsAe05TTgB7JixzewB7TlMAe04AewB7TlNOAHsAfnp7c3tOAHsAe05OAHsmLHMsJiwAewB7JixzLCYsAHsAe04mLAB7ACwAewB7TgB7AHtOU04AewB+entze04AAHsAe04AewB7TlNOAHsAfnp7c3tOAHsAe04AewB7TlNOAHsmLHN7AHtOUwB7TgB7AHtOU04AewB+entze04AewB7TlNOAHsAfnoNEQAAAAB+AHt+e3MAe05T
The fuzz target and artifact are available in this PR for compiler-rs (an Astro component compiler that uses lightningcss for CSS scoping): withastro/compiler-rs#5
The input can also be exercised directly:
use lightningcss::stylesheet::{StyleSheet, ParserOptions, PrinterOptions};
let css = /* base64-decoded bytes above, interpreted as lossy UTF-8 */;
let sheet = StyleSheet::parse(css, ParserOptions::default()).unwrap();
sheet.to_css(PrinterOptions::default()); // panics
Observed behaviour
Linux x86-64 (CI):
thread '<unnamed>' panicked at lightningcss-1.0.0-alpha.70/src/printer.rs:219:5:
attempt to add with overflow
macOS arm64 (local):
thread '<unnamed>' panicked at lightningcss-1.0.0-alpha.70/src/printer.rs:219:5:
attempt to add with overflow
Stack trace (macOS) shows 200+ alternating frames:
StyleRule::to_css_base (lightningcss/src/rules/style.rs)
CssRuleList::to_css (lightningcss/src/rules/mod.rs)
StyleRule::to_css_base (lightningcss/src/rules/style.rs)
...
The integer overflow occurs in the indentation arithmetic inside the printer once the recursion depth is large enough that the indent counter wraps.
Root cause
StyleRule::to_css_base calls CssRuleList::to_css for nested rules, which calls back into StyleRule::to_css_base — mutual recursion with no depth limit. lightningcss's parser accepts deeply nested CSS, so the printer receives input that overflows both the stack and the indent counter.
Expected behaviour
to_css should return an error for pathologically nested CSS rather than panicking. Any real-world CSS nesting limit (a few hundred levels) would be safe.
Fix suggestion
Add a depth counter to the printer (or parser) and return Err when the limit is exceeded. A limit of a few hundred levels is more than sufficient for real-world CSS.
Environment
lightningcss 1.0.0-alpha.70
- Rust stable / nightly
- Reproduced on Linux x86-64 (CI) and macOS arm64 (local)
- Found via cargo-fuzz (
css_scope_no_panic target)
Note: this issue was drafted with AI assistance (Claude), which also helped build the fuzzing setup, artifact minimization, and root cause analysis.
Summary
Deeply nested
{in CSS input causes a crash. On Linux/CI the panic message isattempt to add with overflowinlightningcss/src/printer.rs. On macOS the same input causes a stack overflow via mutual recursion betweenStyleRule::to_css_baseandCssRuleList::to_css.Affected versions
lightningcss1.0.0-alpha.70 (confirmed)Reproducer
Minimized input (525 bytes) found via cargo-fuzz. Decode this base64 to a file and pass it to the
Printer:The fuzz target and artifact are available in this PR for
compiler-rs(an Astro component compiler that uses lightningcss for CSS scoping): withastro/compiler-rs#5The input can also be exercised directly:
Observed behaviour
Linux x86-64 (CI):
macOS arm64 (local):
Stack trace (macOS) shows 200+ alternating frames:
The integer overflow occurs in the indentation arithmetic inside the printer once the recursion depth is large enough that the indent counter wraps.
Root cause
StyleRule::to_css_basecallsCssRuleList::to_cssfor nested rules, which calls back intoStyleRule::to_css_base— mutual recursion with no depth limit. lightningcss's parser accepts deeply nested CSS, so the printer receives input that overflows both the stack and the indent counter.Expected behaviour
to_cssshould return an error for pathologically nested CSS rather than panicking. Any real-world CSS nesting limit (a few hundred levels) would be safe.Fix suggestion
Add a depth counter to the printer (or parser) and return
Errwhen the limit is exceeded. A limit of a few hundred levels is more than sufficient for real-world CSS.Environment
lightningcss1.0.0-alpha.70css_scope_no_panictarget)Note: this issue was drafted with AI assistance (Claude), which also helped build the fuzzing setup, artifact minimization, and root cause analysis.