Skip to content

[V4] Fix GIF LZW table bounds and frame clipping - #3253

Merged
JimBobSquarePants merged 2 commits into
release/4.1.xfrom
fix/gif-lzw-frame-geometry-v4
Oct 27, 2026
Merged

JimBobSquarePants merged 2 commits into
release/4.1.xfrom
fix/gif-lzw-frame-geometry-v4

Conversation

@JimBobSquarePants

Copy link
Copy Markdown
Member

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

Backport #3224, including its review corrections, to current release/4.1.x. Keep this draft until the main fix is merged.

Clip frame geometry to the logical screen, preserve visible rows from later interlace passes, and skip empty passes in short frames. Use the existing sub-block skipper when a frame has no visible pixels.

Reject the invalid first LZW code before indexing the code tables. Strict and IgnoreAncillary throw InvalidImageContentException. IgnoreImageData retains completed rows and skips the rest of the corrupt frame, then continues to the next frame. Header and palette parsing stay outside this recovery boundary. Dispose the partially decoded image when decoding fails.

All new inputs are stored files: the same 17 verified GIFs used by the main fix, totaling 2,310 bytes. Tests cover invalid codes before and after a clear, hidden-row index skipping, all integrity modes, short and clipped interlaced frames, and later animation frames. No test-time input generation remains in the added tests.

Verification

  • Release .NET 8.0.33: 216 GIF, GIF-related and shared decoder tests passed.
  • Release .NET 10.0.14: the same 216 tests passed.
  • Stored input hashes match the reviewed main branch. Pillow independently verifies the geometry fixtures' frame samples and following frames.
  • No public API changes, tolerance changes or reference-image changes.

Backports #3224. Addresses #3236 for V4.

jafin and others added 2 commits October 27, 2026 14:01
…past the code tables

An interlaced frame whose lines fall below the logical screen clamped the target row to the
screen height and threw from the row lookup, frames shorter than five lines wrote their lines
to the wrong rows, and a frame starting right of the screen threw while slicing the row.
Lines below the screen are now decoded and discarded only while a later interlace pass can
still reach the screen, and frames starting outside the screen are skipped.

With a minimum code size of 12 the first code after a clear code could index past the
4096-entry LZW tables. Decoding and skipping now stop at such a code.
Reject detected out-of-table LZW codes with InvalidImageContentException.
Only IgnoreImageData recovers by retaining completed rows and using the
existing sub-block skipper. Keep header and palette parsing outside recovery.
Dispose the partially decoded image when decoding fails; the new stored
regressions reproduce the missing cleanup on the original main branch.

Replace all input generation introduced by this PR with 17 stored GIFs
(2310 bytes). Independently verify descriptors, palettes, sub-block boundaries,
and malformed code sequences. Pillow checks every geometry fixture's frame
samples and following white-pixel frame. Cover code errors before and after
clear, hidden-row index skipping, all integrity modes, clipped interlace
passes, short interlace passes, and continued animation parsing.

Current main fails 13 of the 19 new cases. Release .NET 10: 158 GIF tests
and 60 GIF-related/shared decoder tests pass. Final focused run: 19 passed.
No reference images or tolerances changed.
@JimBobSquarePants
JimBobSquarePants marked this pull request as ready for review October 27, 2026 04:32
@JimBobSquarePants
JimBobSquarePants merged commit 8864c94 into release/4.1.x Oct 27, 2026
11 checks passed
@JimBobSquarePants
JimBobSquarePants deleted the fix/gif-lzw-frame-geometry-v4 branch October 27, 2026 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants