Skip to content

Prevents out-of-bounds memory access#129

Merged
hellobertrand merged 6 commits intomainfrom
fix/usan-z
Mar 5, 2026
Merged

Prevents out-of-bounds memory access#129
hellobertrand merged 6 commits intomainfrom
fix/usan-z

Conversation

@hellobertrand
Copy link
Owner

Enhances memory safety within the compression and decompression routines by addressing several potential out-of-bounds read and write scenarios.

Specifically:

  • Introduces a padded scratch buffer for decompression to safely handle "wild copies," preventing direct out-of-bounds writes to the final output buffer.
  • Adds explicit bounds checks when copying literals during both compression and decompression to prevent reading past the end of source buffers.
  • Improves the bit reader's end-of-stream handling to avoid out-of-bounds reads when processing partial data.
  • Adjusts the destination safe margin calculation to correctly account for potential overshoots from 32-byte copy operations.

Adds bounds checks to ensure that optimized 16-byte and 32-byte copies do not read beyond the end of the input buffer. This resolves potential undefined behavior when processing literals near the buffer boundary, as identified by sanitizers.
@codecov
Copy link

codecov bot commented Mar 4, 2026

Codecov Report

❌ Patch coverage is 82.35294% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/lib/zxc_dispatch.c 83.33% 2 Missing ⚠️
src/lib/zxc_common.c 80.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Updates the safe threshold calculation in the decompression loop to include ZXC_PAD_SIZE. This ensures that optimized 32-byte copies do not write past the end of the destination buffer, resolving potential out-of-bounds access detected by sanitizers.

Prevents out-of-bounds writes using a padded scratch buffer

Optimized 32-byte wild copies used during decompression can overshoot the destination buffer by up to ZXC_PAD_SIZE bytes. This change introduces an intermediate padded scratch buffer to safely contain these overshoots before performing a precise copy to the final output buffer.
The bit reader's fast path uses `zxc_le64`, which always performs an 8-byte load. Previously, this path could be triggered when the buffer had enough data to satisfy the bit requirement but fewer than 8 bytes remaining, leading to a potential over-read. This change ensures the fast path is only used when a full 8-byte read is safe and correctly bounds partial reads to the number of bytes required.
The block decoding path previously validated the destination buffer's bounds but lacked corresponding checks for the source literal stream. This change adds bounds checks to ensure that both optimized wild copies and the fallback exact copy do not read past the end of the input buffer.
Reuses the padded scratch buffer across decompression calls by moving it into the context. This reduces allocation overhead and simplifies memory management in error paths.
Verifies the scratch buffer logic used to handle wild-copy overshoots during decompression. Includes test cases for exact-fit buffers, tiny data, and malformed input to ensure memory safety and prevent regressions.
@hellobertrand hellobertrand merged commit 56a5775 into main Mar 5, 2026
44 of 45 checks passed
@hellobertrand hellobertrand deleted the fix/usan-z branch March 5, 2026 07:26
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.

1 participant