Repository navigation
Conversation
…ts into the headers Some writers leave bfOffBits at 0. The lenient clamp from image-rs#2919 only covered offsets from 14 up to the end of the DIB header, so 0..13 still seeked into the file header and decoded the wrong picture silently. Its target, the end of the DIB header, also lies before any bitmasks and palette, which were then read as pixels. In lenient mode, any data_offset below the end of the DIB header now becomes the reader position after the bitmasks and palette, the same position the no-file-header (ICO) path already uses. Offsets at or past the end of the DIB header, and strict mode, are unchanged. Fixes image-rs#3131 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
|
A note on one limit, so it isn't a surprise in review. An offset exactly at The same accounting means a V4/V5 🤖 Generated with Claude Code |
In lenient mode the last row's length check subtracted the reader position from the file length. With the pixel data offset past the end of the file (declared that way, or reached by a V4/V5 bitfields file whose offset is inside its headers) that underflowed: a panic in debug builds and a wrapped length in release. It now falls through to the normal read, which reports the short file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
|
Correction to my note above, after checking it with a synthetic V4 file (108-byte header, 16-bit With an offset of 0, the reader position after the palette is 16 bytes past the real data. For this small file that is past the end of the file, and that turned up a separate bug that is already on This PR would have made that easier to reach, so I've added 33e7bd9: the subtraction is checked, and such a file now returns the short-read error. There is a regression test ( The V4/V5 mask accounting itself is unchanged, as described above. 🤖 Generated with Claude Code |
Fixes #3131.
Some writers leave
bfOffBitsat 0. The lenient clamp from #2919 only covers14 <= data_offset < bmp_header_end, so 0 to 13 still seek into the file header and thepicture decodes wrong with no error. Its target,
bmp_header_end, is also before any bitmasksand palette, so a paletted or
BI_BITFIELDSimage clamped there read those bytes as pixels.In lenient mode, any
data_offsetbelowbmp_header_endnow becomes the reader position afterread_palette(), the position theno_file_headerpath already takes. These cases areunchanged:
bmp_header_end, so a file whosebiClrUsedoverstates its palette buthas a correct offset still decodes as before;
Strict mode could reject these offsets instead, as the issue suggests. I left that out to keep
this to the lenient fix, but I can add it if you'd like.
One limit: like the
no_file_headerpath, this doesn't skip a colour table in a 16/24/32-bitfile (
biClrUsed > 0with no palette use). Such a file withbfOffBits = 0would still readits table as pixels.
Tests
test_data_offset_inside_the_headers_starts_after_the_palette_and_bitmasksbuilds 2×1red/blue BMPs and checks each decodes to
[255, 0, 0, 0, 0, 255]:BI_BITFIELDS5-6-5 with offsets 0, 13, 53, and the correct 66.With the old clamp restored, the test fails:
[62, 77, 66, 0, 0, 0], the output the issue predicted;[255, 0, 0, 255, 0, 0];[255, 0, 0, 0, 0, 0].test_invalid_data_offset_into_dib_header(#2919) still passes.These pass locally on stable:
cargo fmt -- --check;cargo clippy --all-targets --features bmp,ico -- -D warnings;cargo test --lib(333 tests);cargo test --test reference_images.I found this while fixing the same file in a PDF editor (storytold/pdfcraft#4943), which works
around it before decoding.
🤖 Generated with Claude Code
https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9