Summary
Decoding Panasonic RW2 files from newer cameras (S5 II / S1R II / G9 II generation) panics in decode_panasonic with an out-of-bounds slice index.
Panic
thread '<unnamed>' panicked at rawloader-0.37.2/src/decoders/rw2.rs:94:21:
range start index 26329088 out of range for slice of length 24175632
Reproducible on both 0.37.2 (crates.io) and current master — the code at the panic site is identical:
let skip = ((width * row * 9) + (width/14 * 2 * row)) / 8;
let blocks = skip / 0x4000;
let src = &buf[blocks*0x4000..]; // <- line 94: unguarded slice
Analysis
The failing file's raw section is ~1.0 byte/pixel (24,175,632 bytes for a ~23.6 MP image), while decode_panasonic assumes the classic 9/8 bytes-per-pixel encoding. The branch selection in Rw2Decoder::image doesn't catch this variant:
src.len() >= width*height*2 → false
src.len() >= width*height*3/2 → false
- falls through to
decode_panasonic(src, width, height, false, …), which computes block offsets from the assumed 9/8 packing and overruns the buffer near the bottom rows.
Newer Panasonic bodies write RW2 with a different compression (~8-bit/pixel), which this decoder path was never written for.
Expected behavior
Return an Err (unsupported encoding) instead of panicking — a panic on a rayon worker thread aborts the whole decode and is unfriendly to downstream FFI consumers. At minimum a bounds check before the slice; ideally support for the newer compression.
Environment
- rawloader 0.37.2 (also reproduced against
master)
- macOS arm64, called via FFI (panic crosses
catch_unwind only because rayon re-raises on the join)
Summary
Decoding Panasonic RW2 files from newer cameras (S5 II / S1R II / G9 II generation) panics in
decode_panasonicwith an out-of-bounds slice index.Panic
Reproducible on both 0.37.2 (crates.io) and current
master— the code at the panic site is identical:Analysis
The failing file's raw section is ~1.0 byte/pixel (24,175,632 bytes for a ~23.6 MP image), while
decode_panasonicassumes the classic 9/8 bytes-per-pixel encoding. The branch selection inRw2Decoder::imagedoesn't catch this variant:src.len() >= width*height*2→ falsesrc.len() >= width*height*3/2→ falsedecode_panasonic(src, width, height, false, …), which computes block offsets from the assumed 9/8 packing and overruns the buffer near the bottom rows.Newer Panasonic bodies write RW2 with a different compression (~8-bit/pixel), which this decoder path was never written for.
Expected behavior
Return an
Err(unsupported encoding) instead of panicking — a panic on a rayon worker thread aborts the whole decode and is unfriendly to downstream FFI consumers. At minimum a bounds check before the slice; ideally support for the newer compression.Environment
master)catch_unwindonly because rayon re-raises on the join)