Fix memory safety bugs in block reading and decompression#1320
Open
sharadboni wants to merge 1 commit intogoogle:mainfrom
Open
Fix memory safety bugs in block reading and decompression#1320sharadboni wants to merge 1 commit intogoogle:mainfrom
sharadboni wants to merge 1 commit intogoogle:mainfrom
Conversation
Fix three security-relevant bugs that can be triggered by crafted SST files: 1. ReadBlock integer overflow (table/format.cc): handle.size() is a uint64_t read from the SST file. On 32-bit platforms the static_cast<size_t> silently truncates, and on all platforms `n + kBlockTrailerSize` can wrap to a small value, causing an undersized heap allocation followed by an out-of-bounds write. Add an overflow check before the allocation. 2. ZSTD_getFrameContentSize sentinel mishandling (port/port_stdcxx.h): The function returns ZSTD_CONTENTSIZE_UNKNOWN (SIZE_MAX) or ZSTD_CONTENTSIZE_ERROR (SIZE_MAX-1) on failure, but only the value 0 was rejected. Passing SIZE_MAX as the output buffer size to ZSTD_decompressDCtx leads to a massive allocation or undefined behavior. Check both sentinels. 3. DecodeEntry uint32 overflow (table/block.cc): The bounds check `(limit - p) < (non_shared + value_length)` performs the addition in uint32_t, which can wrap to a small value and bypass the check, leading to out-of-bounds reads. Split into two sequential checks that cannot overflow.
Author
|
@pwnall Could you review this security fix? It addresses an integer overflow in ReadBlock, Zstd sentinel mishandling, and a uint32 overflow in DecodeEntry that can be triggered via crafted SST files. |
|
ارجMAHMOUD HASSANAL ASFAR بتاريخ ١٦/٠٤/٢٠٢٦ ١:٤٣ ص، كتب Sharad Boni ***@***.***>:Summary
Fix three security-relevant bugs that can be triggered by maliciously crafted SST files:
ReadBlock integer overflow (table/format.cc): handle.size() is a uint64_t read from the SST file. On 32-bit platforms the static_cast<size_t> silently truncates, and on all platforms n + kBlockTrailerSize can wrap to a small value, causing an undersized heap allocation followed by an out-of-bounds write. Added an overflow check before the allocation.
ZSTD_getFrameContentSize sentinel mishandling (port/port_stdcxx.h): ZSTD_getFrameContentSize returns ZSTD_CONTENTSIZE_UNKNOWN (SIZE_MAX) or ZSTD_CONTENTSIZE_ERROR (SIZE_MAX-1) on failure, but only the value 0 was rejected. Passing SIZE_MAX as the output buffer size to ZSTD_decompressDCtx leads to a massive allocation or undefined behavior. Now both sentinels are properly checked.
DecodeEntry uint32 overflow (table/block.cc): The bounds check (limit - p) < (non_shared + value_length) performs the addition in uint32_t, which can wrap to a small value and bypass the check, leading to out-of-bounds reads. Split into two sequential checks that cannot overflow.
Test plan
Verify existing unit tests still pass (make check / cmake --build . --target leveldb_tests) Confirm the ReadBlock overflow check rejects a BlockHandle with size() near SIZE_MAX Confirm Zstd_GetUncompressedLength returns false for frames that yield ZSTD_CONTENTSIZE_UNKNOWN or ZSTD_CONTENTSIZE_ERROR Confirm DecodeEntry returns nullptr when non_shared + value_length would overflow uint32
You can view, comment on, or merge this pull request online at:
#1320
Commit Summary
6eb1356 Fix memory safety bugs in block reading and decompression
File Changes (3 files)
M
port/port_stdcxx.h
(4)
M
table/block.cc
(3)
M
table/format.cc
(7)
Patch Links:
https://github.com/google/leveldb/pull/1320.patchhttps://github.com/google/leveldb/pull/1320.diff
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
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.
Summary
Fix three security-relevant bugs that can be triggered by maliciously crafted SST files:
ReadBlock integer overflow (
table/format.cc):handle.size()is auint64_tread from the SST file. On 32-bit platforms thestatic_cast<size_t>silently truncates, and on all platformsn + kBlockTrailerSizecan wrap to a small value, causing an undersized heap allocation followed by an out-of-bounds write. Added an overflow check before the allocation.ZSTD_getFrameContentSize sentinel mishandling (
port/port_stdcxx.h):ZSTD_getFrameContentSizereturnsZSTD_CONTENTSIZE_UNKNOWN(SIZE_MAX) orZSTD_CONTENTSIZE_ERROR(SIZE_MAX-1) on failure, but only the value0was rejected. PassingSIZE_MAXas the output buffer size toZSTD_decompressDCtxleads to a massive allocation or undefined behavior. Now both sentinels are properly checked.DecodeEntry uint32 overflow (
table/block.cc): The bounds check(limit - p) < (non_shared + value_length)performs the addition inuint32_t, which can wrap to a small value and bypass the check, leading to out-of-bounds reads. Split into two sequential checks that cannot overflow.Test plan
make check/cmake --build . --target leveldb_tests)BlockHandlewithsize()nearSIZE_MAXZstd_GetUncompressedLengthreturns false for frames that yieldZSTD_CONTENTSIZE_UNKNOWNorZSTD_CONTENTSIZE_ERRORDecodeEntryreturns nullptr whennon_shared + value_lengthwould overflow uint32