Skip to content

Fix crash decoding a corrupt page during scanning - #84

Open
sjg20 wants to merge 1 commit into
masterfrom
scan-decode-crash
Open

Fix crash decoding a corrupt page during scanning#84
sjg20 wants to merge 1 commit into
masterfrom
scan-decode-crash

Conversation

@sjg20

@sjg20 sjg20 commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Scanning a stack and viewing it at the same time can crash with a SIGSEGV in jpeg_decode (utils.cpp:284).

Cause: while scanning, the scan pumps the event loop to stay responsive, which lets the background thumbnail timer decode the page that's still being written. When a scanner double-feed leaves that page corrupt, its chunk header describes tile geometry that no longer matches the allocated image buffer. get_tile_size() assumes consistent geometry, so it returns a tile whose position + height run past the end of the buffer, and the JPEG decode walks the destination pointer off the end.

Fix: in decode_tiledata(), bound every tile to the image buffer — skip a tile that starts outside the buffer or has a non-positive size, and clamp its height to the rows that remain. A corrupt/partial page then produces a garbage thumbnail instead of crashing. For a valid file the tiles always lie within the buffer, so the checks are no-ops (the existing decode tests confirm normal decoding is unchanged).

Reported from a real crash (full backtrace through Pagemodel::nextUpdategetImagedecode_tiledatajpeg_decode) that happened on a scanner double-feed.

🤖 Generated with Claude Code

Scanning a stack and viewing it at the same time decodes a page while
it is still being written: the scan keeps the UI responsive by pumping
events, which lets the background thumbnail timer decode the
half-finished page.  When a scanner double-feed leaves that page
corrupt, its chunk header can describe tile geometry that no longer
matches the allocated image buffer, and get_tile_size() then hands back
a tile whose position and height run past the end of the buffer.  The
JPEG decode walks the destination pointer off the end and crashes.

Bound every tile to the image buffer in decode_tiledata(): skip a tile
that starts outside the buffer or has a non-positive size, and clamp
its height to the rows that remain, so a corrupt or partially-written
page can never write past the buffer.  For a valid file the tiles
always lie within the buffer, so the checks are no-ops.

Co-developed-by: Claude Fable 5 <noreply@anthropic.com>
@sjg20
sjg20 force-pushed the scan-decode-crash branch from 10363c3 to 95addac Compare June 15, 2026 00:17
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