guix_mirror_bot pushed a commit to branch master
in repository guix.
commit 2d53eb46cefc81495b5ce14897044e200b290723
Author: Jelle Licht <[email protected]>
AuthorDate: Wed Oct 21 13:20:44 2026 +0200
gnu: brotli: Fix CVE-2026-111497.
* gnu/packages/patches/brotli-CVE-2026-111497.patch: New file.
* gnu/local.mk (dist_patch_DATA): Register it.
* gnu/packages/compression.scm (brotli)[replacement]: New field.
(brotli/fixed): New variable.
---
gnu/local.mk | 1 +
gnu/packages/compression.scm | 13 ++
gnu/packages/patches/brotli-CVE-2026-111497.patch | 229 ++++++++++++++++++++++
3 files changed, 243 insertions(+)
diff --git a/gnu/local.mk b/gnu/local.mk
index e357460013c..d1821055c77 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1068,6 +1068,7 @@ dist_patch_DATA =
\
%D%/packages/patches/brasero-fix-gcc-14-build-failure.patch \
%D%/packages/patches/brightnessctl-elogind-support.patch \
%D%/packages/patches/bristol-c99.patch \
+ %D%/packages/patches/brotli-CVE-2026-111497.patch \
%D%/packages/patches/bsd-games-2.17-64bit.patch \
%D%/packages/patches/bsd-games-add-configure-config.patch \
%D%/packages/patches/bsd-games-add-wrapper.patch \
diff --git a/gnu/packages/compression.scm b/gnu/packages/compression.scm
index 367a293646c..d08b363cc0f 100644
--- a/gnu/packages/compression.scm
+++ b/gnu/packages/compression.scm
@@ -2598,6 +2598,7 @@ targeting storage applications. ISA-L includes:
(package
(name "brotli")
(version "1.2.0")
+ (replacement brotli/fixed)
(source
(origin
(method git-fetch)
@@ -2620,6 +2621,18 @@ with @code{deflate} but offers more dense compression.
The specification of the Brotli Compressed Data Format is defined in RFC
7932.")
(license license:expat)))
+(define-public brotli/fixed
+ (hidden-package
+ (package
+ (inherit brotli)
+ (source
+ (let ((s (package-source brotli)))
+ (origin
+ (inherit s)
+ (patches
+ (append (search-patches "brotli-CVE-2026-111497.patch")
+ (origin-patches s)))))))))
+
(define-public java-brotli
(package
(inherit brotli)
diff --git a/gnu/packages/patches/brotli-CVE-2026-111497.patch
b/gnu/packages/patches/brotli-CVE-2026-111497.patch
new file mode 100644
index 00000000000..d55f2dbe477
--- /dev/null
+++ b/gnu/packages/patches/brotli-CVE-2026-111497.patch
@@ -0,0 +1,229 @@
+From 0ed4268a4401abcb4472096340477cf4af7d1a2b Mon Sep 17 00:00:00 2001
+From: Evgenii Kliuchnikov <[email protected]>
+Date: Fri, 27 Feb 2026 05:10:32 -0800
+Subject: [PATCH] Detect and report invalid stream earlier.
+
+PiperOrigin-RevId: 876198329
+---
+ c/dec/decode.c | 87 ++++++++++++++++++++++++++-------------
+ c/include/brotli/decode.h | 4 +-
+ 2 files changed, 59 insertions(+), 32 deletions(-)
+
+diff --git a/c/dec/decode.c b/c/dec/decode.c
+index e87e7f5ea..19c7e0283 100644
+--- a/c/dec/decode.c
++++ b/c/dec/decode.c
+@@ -1176,7 +1176,7 @@ static BrotliDecoderErrorCode
DecodeContextMap(brotli_reg_t context_map_size,
+
+ /* Decodes a command or literal and updates block type ring-buffer.
+ Reads 3..54 bits. */
+-static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
++static BROTLI_INLINE BrotliDecoderErrorCode DecodeBlockTypeAndLength(
+ int safe, BrotliDecoderState* s, int tree_type) {
+ brotli_reg_t max_block_type = s->num_block_types[tree_type];
+ const HuffmanCode* type_tree = &s->block_type_trees[
+@@ -1187,7 +1187,7 @@ static BROTLI_INLINE BROTLI_BOOL
DecodeBlockTypeAndLength(
+ brotli_reg_t* ringbuffer = &s->block_type_rb[tree_type * 2];
+ brotli_reg_t block_type;
+ if (max_block_type <= 1) {
+- return BROTLI_FALSE;
++ return BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH;
+ }
+
+ /* Read 0..15 + 3..39 bits. */
+@@ -1197,11 +1197,13 @@ static BROTLI_INLINE BROTLI_BOOL
DecodeBlockTypeAndLength(
+ } else {
+ BrotliBitReaderState memento;
+ BrotliBitReaderSaveState(br, &memento);
+- if (!SafeReadSymbol(type_tree, br, &block_type)) return BROTLI_FALSE;
++ if (!SafeReadSymbol(type_tree, br, &block_type)) {
++ return BROTLI_DECODER_NEEDS_MORE_INPUT;
++ }
+ if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) {
+ s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
+ BrotliBitReaderRestoreState(br, &memento);
+- return BROTLI_FALSE;
++ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ }
+
+@@ -1217,7 +1219,7 @@ static BROTLI_INLINE BROTLI_BOOL
DecodeBlockTypeAndLength(
+ }
+ ringbuffer[0] = ringbuffer[1];
+ ringbuffer[1] = block_type;
+- return BROTLI_TRUE;
++ return BROTLI_DECODER_SUCCESS;
+ }
+
+ static BROTLI_INLINE void DetectTrivialLiteralBlockTypes(
+@@ -1254,59 +1256,65 @@ static BROTLI_INLINE void
PrepareLiteralDecoding(BrotliDecoderState* s) {
+
+ /* Decodes the block type and updates the state for literal context.
+ Reads 3..54 bits. */
+-static BROTLI_INLINE BROTLI_BOOL DecodeLiteralBlockSwitchInternal(
++static BROTLI_INLINE BrotliDecoderErrorCode DecodeLiteralBlockSwitchInternal(
+ int safe, BrotliDecoderState* s) {
+- if (!DecodeBlockTypeAndLength(safe, s, 0)) {
+- return BROTLI_FALSE;
++ BrotliDecoderErrorCode result = DecodeBlockTypeAndLength(safe, s, 0);
++ if (result != BROTLI_DECODER_SUCCESS) {
++ return result;
+ }
+ PrepareLiteralDecoding(s);
+- return BROTLI_TRUE;
++ return BROTLI_DECODER_SUCCESS;
+ }
+
+-static void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliDecoderState* s) {
+- DecodeLiteralBlockSwitchInternal(0, s);
++static BROTLI_NOINLINE BrotliDecoderErrorCode
++DecodeLiteralBlockSwitch(BrotliDecoderState* s) {
++ return DecodeLiteralBlockSwitchInternal(0, s);
+ }
+
+-static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(
++static BROTLI_NOINLINE BrotliDecoderErrorCode SafeDecodeLiteralBlockSwitch(
+ BrotliDecoderState* s) {
+ return DecodeLiteralBlockSwitchInternal(1, s);
+ }
+
+ /* Block switch for insert/copy length.
+ Reads 3..54 bits. */
+-static BROTLI_INLINE BROTLI_BOOL DecodeCommandBlockSwitchInternal(
++static BROTLI_INLINE BrotliDecoderErrorCode DecodeCommandBlockSwitchInternal(
+ int safe, BrotliDecoderState* s) {
+- if (!DecodeBlockTypeAndLength(safe, s, 1)) {
+- return BROTLI_FALSE;
++ BrotliDecoderErrorCode result = DecodeBlockTypeAndLength(safe, s, 1);
++ if (result != BROTLI_DECODER_SUCCESS) {
++ return result;
+ }
+ s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]];
+- return BROTLI_TRUE;
++ return BROTLI_DECODER_SUCCESS;
+ }
+
+-static void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliDecoderState* s) {
+- DecodeCommandBlockSwitchInternal(0, s);
++static BROTLI_NOINLINE BrotliDecoderErrorCode
++DecodeCommandBlockSwitch(BrotliDecoderState* s) {
++ return DecodeCommandBlockSwitchInternal(0, s);
+ }
+
+-static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(
+- BrotliDecoderState* s) {
++static BROTLI_NOINLINE BrotliDecoderErrorCode
++SafeDecodeCommandBlockSwitch(BrotliDecoderState* s) {
+ return DecodeCommandBlockSwitchInternal(1, s);
+ }
+
+ /* Block switch for distance codes.
+ Reads 3..54 bits. */
+-static BROTLI_INLINE BROTLI_BOOL DecodeDistanceBlockSwitchInternal(
++static BROTLI_INLINE BrotliDecoderErrorCode DecodeDistanceBlockSwitchInternal(
+ int safe, BrotliDecoderState* s) {
+- if (!DecodeBlockTypeAndLength(safe, s, 2)) {
+- return BROTLI_FALSE;
++ BrotliDecoderErrorCode result = DecodeBlockTypeAndLength(safe, s, 2);
++ if (result != BROTLI_DECODER_SUCCESS) {
++ return result;
+ }
+ s->dist_context_map_slice = s->dist_context_map +
+ (s->block_type_rb[5] << BROTLI_DISTANCE_CONTEXT_BITS);
+ s->dist_htree_index = s->dist_context_map_slice[s->distance_context];
+- return BROTLI_TRUE;
++ return BROTLI_DECODER_SUCCESS;
+ }
+
+-static void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliDecoderState* s) {
+- DecodeDistanceBlockSwitchInternal(0, s);
++static BROTLI_NOINLINE BrotliDecoderErrorCode
++DecodeDistanceBlockSwitch(BrotliDecoderState* s) {
++ return DecodeDistanceBlockSwitchInternal(0, s);
+ }
+
+ static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(
+@@ -1940,6 +1948,9 @@ static BROTLI_INLINE BROTLI_BOOL CheckInputAmount(
+ return BrotliCheckInputAmount(br);
+ }
+
++/* NB: METHOD should return BROTLI_FALSE only in case there is not enough
input;
++ in case of "unsafe" execution, when input is guaranteed to be
sufficient,
++ result is ignored. */
+ #define BROTLI_SAFE(METHOD) \
+ { \
+ if (safe) { \
+@@ -1952,6 +1963,22 @@ static BROTLI_INLINE BROTLI_BOOL CheckInputAmount(
+ } \
+ }
+
++/* NB: METHOD should return BROTLI_DECODER_SUCCESS, BROTLI_DECODER_ERROR_*, or
++ BROTLI_DECODER_NEEDS_MORE_INPUT; the later two break the processing. */
++#define BROTLI_SAFE_WITH_STATUS(METHOD) \
++ { \
++ BrotliDecoderErrorCode status; \
++ if (safe) { \
++ status = Safe##METHOD; \
++ } else { \
++ status = METHOD; \
++ } \
++ if (status != BROTLI_DECODER_SUCCESS) { \
++ result = status; \
++ goto saveStateAndReturn; \
++ } \
++ }
++
+ static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(
+ int safe, BrotliDecoderState* s) {
+ int pos = s->pos;
+@@ -1991,7 +2018,7 @@ static BROTLI_INLINE BrotliDecoderErrorCode
ProcessCommandsInternal(
+ goto saveStateAndReturn;
+ }
+ if (BROTLI_PREDICT_FALSE(s->block_length[1] == 0)) {
+- BROTLI_SAFE(DecodeCommandBlockSwitch(s));
++ BROTLI_SAFE_WITH_STATUS(DecodeCommandBlockSwitch(s));
+ goto CommandBegin;
+ }
+ /* Read the insert/copy length in the command. */
+@@ -2136,7 +2163,7 @@ static BROTLI_INLINE BrotliDecoderErrorCode
ProcessCommandsInternal(
+ } else {
+ /* Read distance code in the command, unless it was implicitly zero. */
+ if (BROTLI_PREDICT_FALSE(s->block_length[2] == 0)) {
+- BROTLI_SAFE(DecodeDistanceBlockSwitch(s));
++ BROTLI_SAFE_WITH_STATUS(DecodeDistanceBlockSwitch(s));
+ }
+ BROTLI_SAFE(ReadDistance(s, br));
+ }
+@@ -2330,7 +2357,7 @@ static BROTLI_INLINE BrotliDecoderErrorCode
ProcessCommandsInternal(
+ }
+
+ NextLiteralBlock:
+- BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
++ BROTLI_SAFE_WITH_STATUS(DecodeLiteralBlockSwitch(s));
+ goto CommandInner;
+
+ saveStateAndReturn:
+@@ -2552,6 +2579,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
++ BROTLI_DCHECK(s->meta_block_remaining_len <=
++ (int)BROTLI_BLOCK_SIZE_CAP);
+ BROTLI_LOG_UINT(s->is_last_metablock);
+ BROTLI_LOG_UINT(s->meta_block_remaining_len);
+ BROTLI_LOG_UINT(s->is_metadata);
+diff --git a/c/include/brotli/decode.h b/c/include/brotli/decode.h
+index 8d436db73..10d01e365 100644
+--- a/c/include/brotli/decode.h
++++ b/c/include/brotli/decode.h
+@@ -85,9 +85,7 @@ typedef enum {
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR \
+- \
+- /* -17 code is reserved */ \
+- \
++ BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_SWITCH, -17) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_, DICTIONARY_NOT_SET, -19) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_, INVALID_ARGUMENTS, -20) SEPARATOR \