Skip to content

Reject Oversized Images in DecodeImage#1037

Merged
sayanshaw24 merged 5 commits intomainfrom
sayanshaw/decode-image-icm
Mar 27, 2026
Merged

Reject Oversized Images in DecodeImage#1037
sayanshaw24 merged 5 commits intomainfrom
sayanshaw/decode-image-icm

Conversation

@sayanshaw24
Copy link
Copy Markdown
Collaborator

@sayanshaw24 sayanshaw24 commented Mar 20, 2026

Reject oversized images in DecodeImage to prevent decompression bomb attacks

Summary

The DecodeImage operator reads image dimensions from PNG/JPEG headers and immediately allocates output buffers without validating the size. An attacker with access to an inference endpoint can submit a crafted image with extremely large declared dimensions (e.g., 20000x20000), causing the decoder to attempt multi-gigabyte allocations. This serves as an amplification vector — a small compressed payload triggers disproportionate memory consumption, potentially leading to denial of service.

Root Cause

All decode paths (libjpeg, libpng, WIC on Windows, CoreGraphics on macOS) read width/height from the image header and pass them directly to output.Allocate() without any bounds check. A 20000x20000 RGB image would attempt a ~1.2 GB allocation from a few hundred bytes of input.

Changes

operators/vision/image_decoder.hpp (libjpeg/libpng path — Linux and fallback)

  • PNG path: Added dimension validation after png_read_update_info() and before output.Allocate(). Rejects images where either dimension exceeds 16384 pixels or the total pixel count exceeds 100 megapixels (100M). Cleans up with png_destroy_read_struct on rejection.
  • JPEG path: Added the same dimension validation after jpeg_start_decompress() and before output.Allocate(). Cleans up with jpeg_destroy_decompress on rejection.

operators/vision/image_decoder_win32.hpp (WIC path — Windows)

  • Added dimension validation after pIDecoderFrame->GetSize() and before output.Allocate(). Uses the same 16384 / 100M limits.

operators/vision/image_decoder_darwin.hpp (CoreGraphics path — macOS)

  • Added dimension validation after CGImageGetWidth/Height() and before output.Allocate(). Properly releases the CGImage on rejection.

test/pp_api_test/test_imgcodec.cc

  • TestPngOversizeDimensionsRejected: Crafts a minimal PNG with a valid IHDR header declaring 20000x20000 dimensions. Verifies the decoder rejects it.
  • TestJpegOversizeDimensionsRejected: Crafts a structurally valid JPEG (SOI + DQT + SOF0 + DHT + SOS) declaring 17000x17000 dimensions. Verifies the decoder rejects it.
  • Both tests log [Expected rejection] with the error message for clear CI output.

Limits

Limit Value Rationale
Max single dimension 16,384 px Covers all practical inference use cases; matches common GPU texture limits
Max total pixels 100,000,000 (100 MP) Caps the output buffer at ~300 MB (RGB), preventing OOM from crafted inputs

These are compile-time constants (kMaxImageDimension, kMaxPixelCount) and can be made configurable in the future if deployment scenarios require larger images.

@sayanshaw24 sayanshaw24 requested a review from a team as a code owner March 20, 2026 00:36
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds size-based input validation to DecodeImage decoders to mitigate decompression-bomb style DoS by rejecting images with overly large declared dimensions before allocating output buffers.

Changes:

  • Add max-dimension and max-pixel-count checks across PNG/JPEG (libpng/libjpeg), WIC (Windows), and CoreGraphics (macOS) decode paths.
  • Add new security regression tests that attempt to decode oversized PNG/JPEG headers and expect rejection.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.

File Description
operators/vision/image_decoder.hpp Adds oversize checks for libpng and libjpeg decode paths before output.Allocate().
operators/vision/image_decoder_win32.hpp Adds oversize checks for WIC decode path before output.Allocate().
operators/vision/image_decoder_darwin.hpp Adds oversize checks for CoreGraphics decode path before output.Allocate().
test/pp_api_test/test_imgcodec.cc Adds tests that craft oversized PNG/JPEG headers and assert decode rejection.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

vraspar
vraspar previously approved these changes Mar 27, 2026
@sayanshaw24 sayanshaw24 merged commit 9939a06 into main Mar 27, 2026
36 of 38 checks passed
@sayanshaw24 sayanshaw24 deleted the sayanshaw/decode-image-icm branch March 27, 2026 04:28
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.

4 participants