From: Aurelien DARRAGON Date: Tue, 11 Aug 2026 16:16:52 +0000 (+0200) Subject: IMPORT: slz/uslz: fix incorrect sign extension in shift when reading the adler32... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=08979193e50d69915848d4b24c8cfcfd7e90d535;p=thirdparty%2Fhaproxy.git IMPORT: slz/uslz: fix incorrect sign extension in shift when reading the adler32 trailer The zlib trailer is assembled byte by byte into the 64-bit bit accumulator: bit_accum |= in_ptr[0] << (24 - num_bits); in_ptr[0] is an unsigned char, that is unfortunately promoted to signed int when shifted left, thus introducing a sign bit in upper bits if bit 7 was set with num_bits=0, that gets sign-extended to 64-bit in the accumulator, resulting in a wrong checksum (and the stream is rejected with USLZ_DECODE_E_BAD_CRC). Let's just cast it to uint32_t before shifting to fix this. Note that other similar places already had the cast, this one was just overlooked. This is libslz upstream commit 98cf96c18d5b4636886ac66b9b6dbec323eaf11c --- diff --git a/src/uslz.c b/src/uslz.c index e879b0440..67944413b 100644 --- a/src/uslz.c +++ b/src/uslz.c @@ -875,7 +875,13 @@ static enum uslz_decode_ret uslz_decode_block(struct uslz_stream *state) while (num_bits < 32) { if (in_ptr >= in_top) goto out_of_data; - bit_accum |= in_ptr[0] << (24 - num_bits); + /* the cast matters: in_ptr[0] is promoted to a + * signed int, so for the first byte, whose + * shift is 24, any value >= 0x80 would become + * negative and be sign-extended over the upper + * half of the 64-bit accumulator. + */ + bit_accum |= (uint32_t)in_ptr[0] << (24 - num_bits); in_ptr++; num_bits += 8; }