Skip to content

fix uberz offset to pointer out of bounds write#9853

Closed
Sakura-501 wants to merge 1 commit intogoogle:mainfrom
Sakura-501:fix-uberz-offset-pointer-oob-write
Closed

fix uberz offset to pointer out of bounds write#9853
Sakura-501 wants to merge 1 commit intogoogle:mainfrom
Sakura-501:fix-uberz-offset-pointer-oob-write

Conversation

@Sakura-501
Copy link
Copy Markdown

Summary

This PR fixes out-of-bounds reads and writes in uberz::convertOffsetsToPointers by making archive pointer conversion size-aware.

Vulnerability

convertOffsetsToPointers rewrote attacker-controlled offsets from a decompressed uberz archive into live pointers without validating that the offsets remained inside the archive buffer. In release builds the existing assert_invariant checks compile away, so malformed values such as specsOffset, flagsOffset, packageOffset, or nameOffset could force the converter to write invalid pointers into the archive structure and then continue traversing those invalid addresses.

Real call sites include:

  • gltfio::ArchiveCache::load
  • the append path in tools/uberz

Any application or service that loads untrusted .uberz content could therefore crash or hit broader memory corruption.

Fix

The patch changes the conversion API to accept the decompressed archive size and validates all offset-derived regions before any pointer rewriting happens:

  • validate archive header size, magic, version, and alignment requirements;
  • validate the specs array range before converting specsOffset;
  • validate each flags array, package range, and NUL-terminated flag name string;
  • keep these checks active in release builds;
  • update both gltfio and tools/uberz to pass the decompressed archive size into the validator.

Tests

Added libs/uberz/tests/test_ReadableArchive.cpp with regression coverage for:

  • a top-level specsOffset that points outside the archive buffer;
  • a nested flag.nameOffset that points outside the archive buffer.

Why this PR is scoped separately

This change only addresses uberz archive validation and call-site propagation. It is intentionally separate from the two independent KTX deserialization fixes.

Make ReadableArchive pointer conversion size-aware so release builds validate the decompressed archive before rewriting any offsets into pointers. The previous implementation trusted attacker-controlled specsOffset, flagsOffset, packageOffset, and nameOffset fields and rewrote them without bounds checks, which allowed malformed uberz archives to drive out-of-bounds reads and writes. Add regression tests for top-level specs offsets and nested flag name offsets, and update gltfio plus the uberz tool to pass the decompressed archive size into the validator.
pixelflinger added a commit that referenced this pull request Apr 14, 2026
- Implement fixes inspired by PR #9853 to make convertOffsetsToPointers
  size-aware and prevent OOB reads and writes.
- Change function signature to return bool instead of void, allowing graceful
  error propagation instead of runtime aborts.
- Replace FILAMENT_CHECK_PRECONDITION with explicit checks that log errors
  and return false.
- Update ArchiveCache in gltfio and main in tools/uberz to handle failure.
- Add unit tests to verify rejection of invalid offsets.
@pixelflinger
Copy link
Copy Markdown
Collaborator

The fix was incomplete. See #9896 for a more complete fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants