Repository navigation
std.brotli: a decoder, capped, that refuses an unpatched libbrotlidec (CVE-2026-111497) - #3133
Merged
Merged
Conversation
Co-authored-by: paul-hammant <82182+paul-hammant@users.noreply.github.com>
…on, pin the CVE classes The decoder from the previous commit, reviewed against the brotli CVEs other implementations have shipped: - CVE-2026-111497 (broccoli2shell): libbrotlidec 1.0.3-1.2.0 writes out of bounds on a malformed block switch. Decoding now refuses to run on an unfixed library. brotli_decoder_patched() asks the library to name error code -17, which the fix added in the same commit, so distro backports that keep the old version number (Debian 1.0.9-2+deb12u1) pass. Checked against upstream v1.2.0 (refused) and v1.2.1 (decodes). decoder_available() exports it. - decompress_stream_finish accepted a truncated stream as success; it now returns "truncated stream". The one-shot path names truncation too. - The streaming decoder ignored bytes after the end of the stream; they are now an error, as on the one-shot path. - Errors name their cause (output limit, truncated, corrupt, refused). - BROTLI_LDFLAGS kept the FIRST of each repeated library, putting -lbrotlicommon before -lbrotlidec, which a static link cannot resolve; it keeps the last now. - The README called broccoli2shell a decompression bomb; it is a memory-safety bug the output cap cannot stop. The README now has a table of which CVE class each defence answers. Tests added: a thousandfold bomb (8 MiB in a few hundred bytes) on both paths, a 300 KB binary payload with NULs at and one under its exact limit, a stream fed one byte at a time, truncation and trailing bytes on the stream, an empty body, and a large-window stream (fixture from the brotli 1.2.1 CLI). The truncation and trailing-byte tests failed against the previous commit; the large-window test fails with large windows enabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
std.brotliwas encode-only. This adds a decoder over the system libbrotlidec: one-shot (decompress,decompress_max) and streaming (decompress_stream_new/_write/_finish/_free), shaped like the encoder.Two commits:
max_bytes, 0 = a 1 GiB ceiling), the link wiring (-lbrotlidecin codegen,ae, the Makefile and the optional-linking test) and a co-located spec.The CVE classes
brotlibrotli< 1.2.0, Scrapymax_byteson every decode. Tested with 8 MiB packed into a few hundred bytes, on both paths.Content-Encodingsstd.http's client doesn't auto-decode.int, and the fix check rules out pre-1.0.8 libraries.The fix check. The CVE-2026-111497 fix gave the reserved error code -17 a name (
BLOCK_SWITCH) in the same commit.brotli_decoder_patched()asks the linked library to name -17. A version comparison would refuse distro backports that keep the old number; the probe accepts them:INVALID_ERROR_FORMAT_BLOCK_SWITCH1.0.9-2+deb12u1(this box)BLOCK_SWITCHThe v1.2.0 and v1.2.1 rows come from a C harness linking
aether_brotli.cagainst static builds of those tags. On an unfixed system, every decode returns an error naming the CVE,decoder_available()returns 0, and encoding is unaffected. The spec has a branch for that case, so a CI runner with an unfixed library tests the refusal instead.Fixed in Jules's code
decompress_stream_finishreturned success on a truncated stream, so a cut connection read as a shorter body. It now returns"truncated stream".-lbrotlienc -lbrotlicommon -lbrotlidec. A static link (the MinGW case the comment is about) can't resolve that. It now keeps the last occurrence, giving-lbrotlienc -lbrotlidec -lbrotlicommon.Tests
std/brotli/test_brotli.ae, 20 specs. The new ones:Negative controls:
BROTLI_DECODER_PARAM_LARGE_WINDOWturned on;Valgrind is clean.
fmt,check-docs,check-changelogandcheck-testspass.brotli_streamingandoptional_library_linkingpass.Build requirement: building with brotli now needs libbrotlidec beside libbrotlienc. Both ship in the same distro package (
libbrotli-dev,brew brotli,mingw-w64-*-brotli).🤖 Generated with Claude Code