Control: forwarded -1 https://github.com/google/snappy/issues/266
On Sun, 20 Sep 2026 at 07:52:35 +0200, Sebastian Ramacher wrote:
snappy FTBFS on 32 bit architectures:
[ RUN ] Snappy.LiteralLengthU32Overflow
./snappy_unittest.cc:1011: Failure
Value of: snappy::Uncompress(compressed.data(), compressed.size(),
&uncompressed)
Actual: true
Expected: false
./snappy_unittest.cc:1013: Failure
Value of: snappy::IsValidCompressedBuffer(compressed.data(), compressed.size())
Actual: true
Expected: false
[ FAILED ] Snappy.LiteralLengthU32Overflow (0 ms)
I think the attached might fix it? (Untested, so no patch tag yet.)
smcv
From: Simon McVittie <[email protected]>
Date: Tue, 22 Sep 2026 00:06:11 +0100
Subject: Calculate literal_length as 64-bit, even on 32-bit platforms
The test added in 7406111ac "Reject streams with literal spans of
2^32 bytes" fails on 32-bit architectures such as i386, because size_t
on such platforms is still only 32 bits, so the addition of 1 byte
to the result of ExtractLowBytes still overflows and wraps around to 0.
If we do the calculation in 64-bit space even on 32-bit platforms,
this works as intended.
An i386 version of libsnappy is used by ffmpeg, and indirectly
by 32-bit Wine, which is one of the few remaining use-cases for i386.
Bug-Debian: https://bugs.debian.org/1148501
Signed-off-by: Simon McVittie <[email protected]>
---
snappy.cc | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/snappy.cc b/snappy.cc
index add72f8..f4f5137 100644
--- a/snappy.cc
+++ b/snappy.cc
@@ -1691,7 +1691,8 @@ class SnappyDecompressor {
// pb 24% 76%
// bin 24% 76%
if (SNAPPY_PREDICT_FALSE((c & 0x3) == LITERAL)) {
- size_t literal_length = (c >> 2) + 1u;
+ // This needs to be larger than 32 bits, even if size_t is 32-bit.
+ uint64_t literal_length = (c >> 2) + 1u;
if (writer->TryFastAppend(ip, ip_limit_ - ip, literal_length, &op)) {
assert(literal_length < 61);
ip += literal_length;
@@ -1708,9 +1709,10 @@ class SnappyDecompressor {
// returns 0xFFFFFFFF); this is implicitly invalid stream (since
// uncompressed length is capped with 0xFFFFFFFF); for performance we
// do not check for this case here.
+ // Because literal_length is 64-bit, the addition here can't overflow.
literal_length =
ExtractLowBytes(LittleEndian::Load32(ip), literal_length_length) +
- size_t{1};
+ uint64_t{1};
ip += literal_length_length;
}