Repository navigation
Conversation
…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.
3 of 4 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prerequisites
Description
Some corrupt or non-conforming GIFs made the decoder throw
IndexOutOfRangeExceptionorArgumentOutOfRangeExceptioninstead of decoding the image or throwingInvalidImageContentException.LZW codes past the code tables
With an LZW minimum code size of 12, the clear code is 4096. The first code after a clear code (or at the start of the data) can then be the next available code, 4098. That code is past the end of the 4096-entry prefix/suffix tables, so
LzwDecoder.DecodePixelRowandLzwDecoder.SkipIndicesthrewIndexOutOfRangeException.Image.LoadandImage.Identifyboth failed.Both methods now stop decoding at such a code. The check is in the branch that handles the first code after a clear code, so it adds no per-pixel cost.
Frames that extend past the logical screen
GifDecoderCore.ReadFrameColorsclamped the target row toimage.Height. That row is out of range, so the decoder threwArgumentOutOfRangeExceptionfromDangerousGetRowSpan. Examples are a 20x20 interlaced frame on a 10x10 screen, or a 10x10 interlaced frame at top 5. The row loop was also limited by the screen height. For an interlaced frame that limit cuts off lines of later passes that are still on the screen.ArgumentOutOfRangeExceptionwhen the row was sliced.Now the row loop covers every frame line. Lines below the screen are dropped. For an interlaced frame they are decoded and discarded only while a later pass can still reach the screen, and decoding stops after that. Empty interlace passes are skipped. A frame that starts at or past the right or bottom edge of the screen is not decoded; the existing sub-block skipping consumes its data. Sequential frames are clipped as before.
Valid GIFs, including the existing deferred clear code and bad descriptor dimension test images, decode as before. Their reference-output comparisons are unchanged.
Testing
New tests in
GifDecoderTestsuse GIFs built in memory, so no new image files are added:Decode_LzwCodePastCodeTables_StopsDecodingFrameandIdentify_LzwCodePastCodeTables_ReturnsImageInfocover the full decode path and the index skipping path.Decode_FrameExceedingLogicalScreen_WritesOnlyRowsInsideCanvasencodes interlaced and sequential frames with the internalLzwEncoder. The frames have different sizes, top offsets (including at the bottom edge and with a single visible line) and left offsets past the right edge. The test checks that every on-screen pixel has the right color and that pixels outside the frame are untouched.Before the change, 11 of the 17 new test cases failed, and each defect above had at least one failing case. The other cases pin behavior that already worked, such as sequential frames below the screen. All GIF tests pass in Release on net10.0 (156 in
Formats.Gif, plus 10 GIF-related tests in other areas).Fixes #3236