Skip to content

Make the WebP decoder tolerate reserved VP8X bits, trailing data and odd-length metadata chunks - #3233

Merged
JimBobSquarePants merged 4 commits into
SixLabors:mainfrom
jafin:jf/webp-decoder-container-robustness
Oct 27, 2026
Merged

JimBobSquarePants merged 4 commits into
SixLabors:mainfrom
jafin:jf/webp-decoder-container-robustness

Conversation

@jafin

@jafin jafin commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

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

The WebP decoder now ignores reserved VP8X fields and bytes after the declared RIFF payload. Odd-length ICC, EXIF and XMP payloads retain their exact contents; the following padding byte is skipped separately.

All boundary checks stay in the WebP parser. Required chunk headers and payloads must fit inside RIFF. Decoded frame image chunks must also fit inside their ANMF payload. Unknown chunks use an unsigned, widened size when skipping, so large declarations cannot wrap into a negative skip. BufferedReadStream is unchanged.

The animation reader now stops at RIFF, skips unknown chunks, counts only frames toward MaxFrames, and retains metadata read before ANIM. Bit readers and partially decoded images are disposed when parsing fails.

Incomplete image payloads at EOF are rejected under Strict and IgnoreAncillary. IgnoreImageData retains the existing compressed-data recovery where the declared chunk still fits inside its parent and its required header is complete. Incomplete ICC framing remains fatal in every mode. EXIF and XMP errors retain the existing ancillary recovery rules.

Tests use stored inputs. Runtime image encoders, container builders, byte patching and the every-prefix truncation loop have been removed from these container and metadata tests. Existing truncated-image tests now select IgnoreImageData explicitly and also check rejection under Strict and IgnoreAncillary. Tolerances and references are unchanged.

Validation uses the local libwebp 1.6.0 source at commit 1844042d1ca751e62e61df7617dba19c98588339:

  • dwebp produces identical pixels for the reserved-field and trailing-data still files.
  • webpmux confirms two animation frames and extracts unchanged odd-length ICC, EXIF and XMP payloads.
  • Both extracted animation frames decode to the stored source pixels.
  • Native parsing rejects image chunks outside RIFF and the frame image chunk that crosses ANMF.
  • The three existing recovery inputs are truncated; dwebp reports NOT_ENOUGH_DATA for each.

Release verification: 521 WebP and selected format regressions pass on .NET 10. The same regression set passed on .NET 11 before the two added animation metadata cases; all four still/animation metadata cases also pass on .NET 11.

V4 backport: #3256.

Fixes #3245

…odd-length metadata chunks

Readers must ignore the reserved VP8X flag bits, so they are no longer
validated. Chunks are now read only up to the end of the RIFF payload,
so bytes after it are ignored rather than parsed as more chunks, and
unknown chunks larger than the payload end the parsing instead of
becoming a negative skip. A stream that ends inside a chunk header,
a 24 bit field or the VP8L header now throws
InvalidImageContentException.

Metadata chunks with an odd payload length are read without the RIFF
padding byte, which is skipped before the next chunk.
@JimBobSquarePants
JimBobSquarePants merged commit 8901b17 into SixLabors:main Oct 27, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WebP decoder rejects files with reserved VP8X bits set or bytes after the RIFF payload, and keeps the padding byte of odd-length metadata chunks

2 participants