Skip to content

fix(dds): reject corrupt bytes-per-pixel before it forces a huge allocation#5286

Merged
lgritz merged 1 commit into
AcademySoftwareFoundation:mainfrom
lgritz:lg-dds-rejectbpp
Jul 2, 2026
Merged

fix(dds): reject corrupt bytes-per-pixel before it forces a huge allocation#5286
lgritz merged 1 commit into
AcademySoftwareFoundation:mainfrom
lgritz:lg-dds-rejectbpp

Conversation

@lgritz

@lgritz lgritz commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

A DDS file with a garbage pixel-format bpp field (e.g. fmt.bpp ~2.5e9) yields a native bytes-per-pixel (m_Bpp) of hundreds of millions. internal_readimg() then does new uint8_t[width * m_Bpp], a multi-GB allocation that OOMs. The core resolution/imagesize limits do not catch this: they only see the small output ImageSpec, not the native pixel size, and the existing fmt.bpp check is gated on RGB/LUM/YUV/ALPHA flags that a corrupt header can simply omit.

Validate m_Bpp for uncompressed formats right after it is computed in open(): the largest real uncompressed DDS/DXGI pixel is 128-bit (16 bytes), so anything outside [1,16] is a corrupt header and is rejected before any allocation. The check is confined to uncompressed formats because m_Bpp is neither set nor used for compressed (block) formats, which size their data via GetStorageRequirements.

Assisted-by: Claude Code / Claude Opus 4.8

…cation

A DDS file with a garbage pixel-format bpp field (e.g. fmt.bpp ~2.5e9) yields a
native bytes-per-pixel (m_Bpp) of hundreds of millions. internal_readimg() then
does `new uint8_t[width * m_Bpp]`, a multi-GB allocation that OOMs under the
fuzzer's RSS limit. The core resolution/imagesize limits do not catch this:
they only see the small output ImageSpec, not the native pixel size, and the
existing fmt.bpp check is gated on RGB/LUM/YUV/ALPHA flags that a corrupt header
can simply omit.

Validate m_Bpp for uncompressed formats right after it is computed in open():
the largest real uncompressed DDS/DXGI pixel is 128-bit (16 bytes), so anything
outside [1,16] is a corrupt header and is rejected before any allocation. The
check is confined to uncompressed formats because m_Bpp is neither set nor used
for compressed (block) formats, which size their data via GetStorageRequirements.

Add the fuzzer reproducer as testsuite/dds/src/crash-bpp.dds. crash-1635.dds now
reports this error slightly earlier than the prior "bit depth" message; update
the reference accordingly.

Assisted-by: Claude Code / Claude Opus 4.8

Signed-off-by: Larry Gritz <lg@larrygritz.com>

@jessey-git jessey-git left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good.

@lgritz lgritz merged commit 94b73bd into AcademySoftwareFoundation:main Jul 2, 2026
28 checks passed
@lgritz lgritz deleted the lg-dds-rejectbpp branch July 2, 2026 20:18
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.

2 participants