Skip to content

feat: add cargo-fuzz targets for transform and CSS scoping#5

Open
jasikpark wants to merge 1 commit intowithastro:feat/rustfrom
jasikpark:push-ouzykvtluvlq
Open

feat: add cargo-fuzz targets for transform and CSS scoping#5
jasikpark wants to merge 1 commit intowithastro:feat/rustfrom
jasikpark:push-ouzykvtluvlq

Conversation

@jasikpark
Copy link

Summary

Adds three libfuzzer fuzz targets (via cargo-fuzz) and a CI workflow:

  • transform_no_panic — arbitrary strings through the full parse → scan → codegen pipeline
  • css_scope_no_panic — arbitrary CSS through scope_css()
  • transform_valid_js_output — valid Astro input must produce valid JS output (idempotency/validity check, inspired by ezno's roundtrip fuzz)

Usage

cargo install cargo-fuzz
cargo +nightly fuzz run transform_no_panic   # from repo root
cargo +nightly fuzz run css_scope_no_panic
cargo +nightly fuzz run transform_valid_js_output

See fuzz/README.md for full usage including minimization instructions.

The fuzz/ crate is its own workspace ([workspace] in fuzz/Cargo.toml) so it doesn't affect normal workspace builds.

CI

Added fuzz.yml which runs:

  • Nightly on a schedule (2am UTC)
  • On pushes/PRs that touch fuzz/**

Uses workflow_dispatch with a configurable fuzz time (default 300s per target). Artifacts are uploaded on failure. Runs as a matrix across all three targets.

Bugs found

Running the fuzzer locally and in CI found two bugs:

1. OOM in withastro/oxc Astro JSX parser

Minimized input: <D} (3 bytes)

parse_astro_jsx_expression_container → parse_astro_jsx_element recurses without a depth limit, causing unbounded allocation.

Upstream issue: withastro/oxc#4

2. Crash in lightningcss printer (integer overflow / stack overflow)

Minimized input: ~525 bytes of deeply nested { CSS

StyleRule::to_css_base ↔ CssRuleList::to_css mutual recursion overflows the stack; on Linux this surfaces first as attempt to add with overflow in printer.rs:219.

Upstream issue: parcel-bundler/lightningcss#1155

Notes

  • libafl_libfuzzer (the modern libFuzzer replacement built on LibAFL) was investigated as a drop-in via libfuzzer-sys = { version = "0.15", package = "libafl_libfuzzer" } — works on Linux but has a macOS build script issue (can't find llvm-nm in PATH from rustup's llvm-tools). Sticking with libfuzzer-sys = "0.4" for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant