[PATCH] lib: decompress_bunzip2: fix integer overflow in run-length decoding

From: Aamir Ahmed

Date: Wed Sep 16 2026 - 05:00:46 EST


The RUNA/RUNB decoder in get_next_block() accumulates a run length into
the signed int t with no bound. runPos doubles per symbol, so t grows as
at least 2^n-1 and reaches INT_MAX after 31 RUNA symbols. The guard that
follows, dbufCount+t >= dbufSize, is itself a signed addition, and as the
kernel builds with -fno-strict-overflow it wraps negative once dbufCount
is nonzero, so the guard is skipped. while (t--) dbuf[dbufCount++] = uc
then writes INT_MAX entries into a buffer holding at most 900000. One
literal symbol ahead of the run is enough to make dbufCount nonzero.

Bound t to the block size as it is accumulated. t only grows within a
run, so the value tested never exceeds the final run length; any stream
that decodes today satisfies dbufCount+t < dbufSize at the flush, hence
t < dbufSize throughout, and no such stream is rejected. Because t grows
as at least 2^n-1 the bound trips by the 20th symbol, leaving runPos at
most 2^19, so the following runPos <<= 1 cannot overflow either.

Fixes: bc22c17e12c1 ("bzip2/lzma: library support for gzip, bzip2 and lzma decompression")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Signed-off-by: Aamir Ahmed <elb12345@xxxxxxxxxxxxx>
---
Triggering this requires control of the initramfs or the compressed
kernel image, so it is not reachable remotely or by an unprivileged
local user.

Tested in userspace under ASan with -fno-strict-overflow: a crafted
31-RUNA stream reports a heap-buffer-overflow at the dbuf[] write
without the patch and returns RETVAL_DATA_ERROR with it. Valid bzip2
streams still decompress byte-identically.

lib/decompress_bunzip2.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/lib/decompress_bunzip2.c b/lib/decompress_bunzip2.c
index 1288f146661f..c4e84dd55770 100644
--- a/lib/decompress_bunzip2.c
+++ b/lib/decompress_bunzip2.c
@@ -428,6 +428,10 @@ static int INIT get_next_block(struct bunzip_data *bd)
t += (runPos << nextSym);
/* +runPos if RUNA; +2*runPos if RUNB */

+ /* Bound the run so t and runPos cannot overflow. */
+ if (t >= dbufSize)
+ return RETVAL_DATA_ERROR;
+
runPos <<= 1;
continue;
}

base-commit: 9b87fdc9af2fbfcdb5c24a64139685ef80f6573f
--
2.43.0