Skip to content

Use the buffer limit for the safe decompress(ByteBuffer, int, ByteBuffer, int) - #161

Merged
yawkat merged 2 commits into
mainfrom
fix/decompressor-with-length-bytebuffer-srclen
Oct 15, 2026
Merged

yawkat merged 2 commits into
mainfrom
fix/decompressor-with-length-bytebuffer-srclen

Conversation

@yawkat

@yawkat yawkat commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

With a safe decompressor, LZ4DecompressorWithLength.decompress(ByteBuffer src, int srcOff, ByteBuffer dest, int destOff) delegated with srcLen = src.remaining() - srcOff. That mixes the buffer's position with an absolute offset. The method uses absolute indexing and is documented to leave positions unchanged, so the result should not depend on src.position(), but it did. Valid data at srcOff = 3 decompressed with src.position() == 0. With src.position() == 3, it failed with LZ4Exception: Malformed input. With larger positions, the computed length could even be negative.

This change uses src.limit() - srcOff instead and corrects the javadoc from src[srcOff:src.remaining()] to src[srcOff:src.limit()]. I checked the sibling methods:

  • decompress(ByteBuffer, ByteBuffer) correctly uses src.position() together with src.remaining().
  • The array overloads use src.length - srcOff.
  • The other absolute-offset overloads take srcLen explicitly.

Found by fuzzing with micronaut-fuzzing.

Behaviour change: callers that set src.position() to something other than 0 get correct results now, where before they got a spurious failure. A call with position 0 behaves exactly as before.

Test: I added OutOfBoundsTest.byteBufferSourceOffsetIgnoresPosition. It decompresses data at srcOff = 3 with source positions 0, 1, 3 and limit, for fast and safe decompressors and for heap and direct buffers. It also checks that positions are unchanged. Without the fix, the safe case fails with Malformed input. With the fix, OutOfBoundsTest and LZ4Test pass.

This builds on #160 (short input, already merged) and merges cleanly with it.

🤖 Generated with Claude Code

yawkat and others added 2 commits October 15, 2026 15:15
…fer, int)

With a safe decompressor, decompress(ByteBuffer src, int srcOff,
ByteBuffer dest, int destOff) computed the compressed length as
src.remaining() - srcOff, mixing the buffer's position with the absolute
offset. Valid input failed to decompress whenever src.position() was not
0. Use src.limit() - srcOff, which matches the absolute indexing of the
other ByteBuffer arguments and the fast path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Place it after destinationBufferLimitsDecompressedLength so that it does
not conflict with the short input test from #160.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@yawkat
yawkat marked this pull request as ready for review October 15, 2026 13:22
@yawkat
yawkat enabled auto-merge (squash) October 15, 2026 13:22
@yawkat
yawkat merged commit f46a762 into main Oct 15, 2026
3 checks passed
@yawkat
yawkat deleted the fix/decompressor-with-length-bytebuffer-srclen branch October 15, 2026 13:29
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