enc: clamp max_base64_regions to avoid allocation-size overflow - #1520
Open
adilburaksen wants to merge 1 commit into
Open
enc: clamp max_base64_regions to avoid allocation-size overflow#1520adilburaksen wants to merge 1 commit into
adilburaksen wants to merge 1 commit into
Conversation
BROTLI_ALLOC computes `N * sizeof(T)` with no overflow check. When BROTLI_PARAM_MAX_BASE64_REGIONS is set close to SIZE_MAX / sizeof(Base64Region) (e.g. 1u << 29 on a 32-bit build, where sizeof(Base64Region) == 8), the multiplication in HasherSetup's base64_regions allocation wraps, producing a buffer much smaller than every subsequent `num_base64_regions < params->max_base64_regions` guard assumes. Clamp max_base64_regions to the largest value that cannot overflow the allocation before it is used, so the allocation size and every downstream guard stay consistent. Values above the clamp already have no realistic chance of a successful allocation, so this does not change behavior for any value that could previously succeed -- it only routes the previously-unreachable overflow case through the existing BROTLI_IS_OOM/IS_NULL failure handling instead. Not reachable through the bundled brotli CLI or any language binding in this repository today; found while auditing the new Base64 detection feature (BROTLI_PARAM_BASE64_MODE) added in 037b70e.
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
BROTLI_ALLOC(c/enc/memory.h) computesN * sizeof(T)with no overflowcheck.
BROTLI_PARAM_MAX_BASE64_REGIONS(added in 037b70e, part of the newBROTLI_PARAM_BASE64_MODEfeature) setsparams.max_base64_regionsfrom anunvalidated
uint32_twith no upper bound. When that value is close toSIZE_MAX / sizeof(Base64Region), the multiplication inHasherSetup'sbase64_regionsallocation (c/enc/hash.h) wraps, producing a buffer farsmaller than every subsequent
num_base64_regions < params->max_base64_regionsguard (
c/enc/backward_references_inc.h) assumes.Verified with a 32-bit ASan build (
sizeof(Base64Region) == 8there):max_base64_regions = 1u << 29makes the allocation wrap to 0, and the firstdetected Base64 region (a plain
;base64,-triggered match in the compressioninput -- ordinary public-API input, not internal misuse) writes past the
resulting allocation.
Fix
Clamp
max_base64_regionsto the largest value that cannot overflow theallocation, right before it's used in
HasherSetup. Since every downstreamread goes through the same
paramspointer, this keeps the allocation sizeand every write-guard consistent. Values above the clamp had no realistic
chance of a successful allocation anyway (multiple gigabytes), so this
doesn't change behavior for any value that could previously succeed -- it
routes the overflow case through the library's existing
BROTLI_IS_OOM/IS_NULLfailure handling instead of wrapping silently.Reachability
BROTLI_PARAM_BASE64_MODEdefaults to disabled(
BROTLI_DEFAULT_BASE64_MODE = BROTLI_BASE64_MODE_DISABLED). The bundledbrotliCLI and the Python/Java/Go bindings in this repository don't exposeeither new parameter. This is a defensive fix for the public C API contract
of a two-week-old experimental feature, not a demonstrated issue in any
current consumer.
Testing
c/common/*.c+c/enc/*.cwithgcc -m32 -fsanitize=address(32-bit, since the overflow needs a 32-bit
size_t).BrotliEncoderSetParameter(..., BROTLI_PARAM_BASE64_MODE, 1)BrotliEncoderSetParameter(..., BROTLI_PARAM_MAX_BASE64_REGIONS, 1u << 29)BrotliEncoderCompressStreamon input containing a;base64,regionreproducibly triggers an ASan heap-buffer-overflow.
max_base64_regionsafter clamping still permits legitimate use) or failscleanly via the existing OOM path for the deliberately-oversized case --
no overflow, verified under the same ASan build.
max_base64_regions(16) before and after thechange: identical, unaffected output.
Happy to share the full PoC/ASan trace via g.co/vulnz or here, whichever the
maintainers prefer.