When I fuzz this crate using cargo fuzz, it seems when the parser encounters a syntax error, it constructs a diagnostic via grass_compiler::raw_to_parse_error, which hands the byte-offset error span to the codemap crate for line/column resolution. If the error span boundary falls inside a multi-byte UTF-8 character, codemap::File::find_line_col attempts &source[start..end] on a non-char-boundary index and Rust panics with "byte index N is not a char boundary; it is inside ...".
The panic propagates up through the public grass::from_string API and aborts the process.
Affected versions
grass <= 0.13.4 (all released versions; latest on crates.io as of 2026-06-02).
Both the binary CLI (grass) and library API (grass::from_string) are affected.
Proof of concept
:v(url(:1B\\\\\cb16 2BqƮx\1\ٯ&<NUL>{}
Minimal Rust program:
fn main() {
// 35-byte SCSS source (from SBOMFuzz Round-3 corpus, byte-for-byte minimal).
// Contains:
// - Multi-byte UTF-8 chars: U+01AE (Ʈ, 2 bytes) and U+066F (ٯ, 2 bytes)
// - A NUL byte (0x00)
// - A CSS hex-escape `\cb16` plus other syntactically-invalid constructs.
let repro: &[u8] = &[
0x3a, 0x76, 0x28, 0x75, 0x72, 0x6c, 0x28, 0x3a, 0x31, 0x42, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x63, 0x62, 0x31, 0x36, 0x20, 0x32, 0x42, 0x71, 0xc6,
0xae, 0x78, 0x5c, 0x31, 0x5c, 0xd9, 0xaf, 0x26, 0x00, 0x7b, 0x7d,
];
let source = std::str::from_utf8(repro).expect("repro is valid UTF-8");
println!("compiling {} bytes of SCSS...", source.len());
// We expect Err here — instead the compiler aborts the process.
let result = grass::from_string(source.to_string(), &grass::Options::default());
println!("UNEXPECTED: compiler did not panic. result = {:?}", result);
}
Output:
compiling 35 bytes of SCSS...
thread 'main' (639240) panicked at /home/yzzhao3/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/codemap-0.1.3/src/lib.rs:257:50:
byte index 30 is not a char boundary; it is inside 'ٯ' (bytes 29..31) of `:v(url(:1B\\\\\cb16 2BqƮx\1\ٯ&{}`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
When I fuzz this crate using cargo fuzz, it seems when the parser encounters a syntax error, it constructs a diagnostic via
grass_compiler::raw_to_parse_error, which hands the byte-offset error span to thecodemapcrate for line/column resolution. If the error span boundary falls inside a multi-byte UTF-8 character,codemap::File::find_line_colattempts&source[start..end]on a non-char-boundary index and Rust panics with"byte index N is not a char boundary; it is inside ...".The panic propagates up through the public
grass::from_stringAPI and aborts the process.Affected versions
grass <= 0.13.4(all released versions; latest on crates.io as of 2026-06-02).Both the binary CLI (
grass) and library API (grass::from_string) are affected.Proof of concept
Minimal Rust program:
Output: