Repository navigation
fix(ipc): bound a compressed buffer's declared uncompressed size (FB-1380) - #50
Closed
moshap-firebolt wants to merge 1 commit into
Closed
moshap-firebolt wants to merge 1 commit into
moshap-firebolt wants to merge 1 commit into
Conversation
…1380) Each compressed IPC body buffer starts with its uncompressed size, and DecompressBuffer allocated that many bytes before decompressing, checking the size only afterwards. A 1 KB message could therefore make the reader allocate any amount of memory: PackDB's arrow_reader fuzzer found a 1,145-byte stream that allocated 973 MB. Reject the size before allocating when it is negative, or larger than the codec can decode from the compressed bytes: 255x for LZ4_FRAME (an LZ4 match spends at least one byte per 255 bytes of length) and 32768x for ZSTD (an RLE block expands one byte into at most a 128 KiB block behind a 3-byte header). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
|
Closing in favor of #51, which applies the same codec-ratio bound (255x LZ4_FRAME, 32768x ZSTD) and negative-size check, and additionally stream-decodes declared sizes over 64 MiB. The unit test here (TestWriteRecordBatch.ReadRejectsImpossibleUncompressedSize, with a ProxyMemoryPool asserting the declared size is never allocated) could be carried over to #51. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
FB-1380: PackDB's
arrow_readerfuzzer found a 1,145-byte Arrow IPC stream that makes the reader allocate 973 MB. Each compressed body buffer starts with its declared uncompressed size, andDecompressBufferallocates that many bytes before decompressing, checking the size only afterwards (Failed to fully decompress buffer). apache#84 (FIR-47668) bounded where a raw buffer may point in the file; the decompressed size was still unbounded. Upstreamapache/arrowmain has the same code.Summary
DecompressBufferrejects the declared uncompressed size before allocating when it is:-1, which marks an uncompressed buffer), orLZ4_FRAME(an LZ4 match spends at least one byte per 255 bytes of length) and 32768× forZSTD(an RLE block expands one byte into at most a 128 KiB block behind a 3-byte header). These are the only IPC body codecs.Real data, all-zero buffers included, stays within these ratios, so no valid stream is rejected.
Test Plan
TestWriteRecordBatch.ReadRejectsImpossibleUncompressedSize(arrow-ipc-read-write-test): forLZ4_FRAMEandZSTD, a compressed batch round-trips unchanged; with its values buffer's declared size set one byte past the codec's ratio the read fails withInvalid, and aProxyMemoryPoolshows the size was never allocated; a negative size fails withInvalid. Without the fix the test fails (the reader allocates the declared size, then reportsFailed to fully decompress buffer).arrow-ipc-read-write-testpasses in full (411 tests, withARROW_TEST_DATApointing attesting/data).arrow_readerregression seed.🤖 Generated with Claude Code
Note
High Risk
Changes IPC read-path memory allocation for compressed bodies; incorrect ratio bounds could reject valid streams or still allow abuse, but ratios are codec-specific and covered by new tests.
Overview
Hardens Arrow IPC decompression against malicious declared sizes (FB-1380): a fuzzer could trigger ~1 GB allocations from a tiny stream because
DecompressBuffertrusted the little-endian prefix and allocated before decompressing.DecompressBufferinreader.ccnow rejects invalid prefixes before allocation: any negative value other than-1(uncompressed sentinel), and any declared size above what the body codec can plausibly expand—255× compressed length forLZ4_FRAMEand 32768× forZSTD—via newMaxDecompressionRatio. Other codecs keep an unbounded ratio.Adds
ReadRejectsImpossibleUncompressedSizeinread_write_test.cc: round-trip for honest LZ4/ZSTD batches; patched impossible or negative declared sizes fail withInvalidand aProxyMemoryPoolproves the oversized buffer was never allocated.Reviewed by Cursor Bugbot for commit 5ae2a08. Bugbot is set up for automated code reviews on this repo. Configure here.