Bounds-check XtcBasedEncoder and Lossless_bypass against corrupted input#135
Open
alexey-milovidov wants to merge 1 commit into
Open
Bounds-check XtcBasedEncoder and Lossless_bypass against corrupted input#135alexey-milovidov wants to merge 1 commit into
alexey-milovidov wants to merge 1 commit into
Conversation
XtcBasedEncoder::decode and Lossless_bypass::decompress read sizes and indices from the compressed data without validation, so corrupted input could write or read out of bounds and leak memory: - XtcBasedEncoder::decode allocated buffer.data twice (the first allocation was overwritten and leaked); the index smallIdx, read from the data, indexed the fixed-size magicInts table out of bounds; and buffer.index, an attacker- controlled byte count, was memcpy'd into buffer.data without checking it against the buffer capacity (a heap buffer overflow). Allocations were not null-checked. - Lossless_bypass::decompress did not null-check its malloc. Adds the missing bounds and null checks; valid data is unaffected. Found while integrating SZ3 into ClickHouse and fuzzing the decompressor: ClickHouse/ClickHouse#108788
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.
Problem
XtcBasedEncoder::decodeandLossless_bypass::decompressread sizes and indices from the compressed data without validating them. On corrupted or adversarial input (e.g. when fuzzing the decompressor) this leads to out-of-bounds writes/reads and a memory leak:XtcBasedEncoder::decodeallocatesbuffer.datatwice — the first allocation is immediately overwritten and leaked.smallIdx, read from the compressed data, indexes the fixed-sizemagicIntstable (magicInts[smallIdx],magicInts[smallIdx - 1]) with no range check — an out-of-bounds read of a static array.buffer.index, an attacker-controlled byte count read from the data, ismemcpy'd intobuffer.datawithout checking it against the buffer capacity — a heap buffer overflow.buffer.data/ index-buffer allocations are not null-checked.Lossless_bypass::decompressdoes not null-check itsmallocbeforememcpy.Changes
Bounds checks and null checks only; valid data is unaffected:
buffer.dataallocation;smallIdxoutside[0, LASTIDX)before indexingmagicInts;buffer.index) larger than thebuffer.datacapacity before the copy loop;buffer.dataand index-buffer allocations;Lossless_bypassallocation.Notes
XtcBasedEncoder::decodedoes not receive a length for its input buffer, so the reads from the input pointer itself can not be fully bounded without threading a length through theEncoderInterface::decodesignature; this change bounds the out-of-bounds writes and the static-array index, which are the memory-corruption issues.Context
Found while integrating SZ3 as an experimental compression codec in ClickHouse and fuzzing the decompressor: ClickHouse/ClickHouse#108788