]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
IMPORT: slz/uslz: fix incorrect sign extension in shift when reading the adler32...
authorAurelien DARRAGON <adarragon@haproxy.com>
Tue, 11 Aug 2026 16:16:52 +0000 (18:16 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Wed, 12 Aug 2026 07:14:07 +0000 (09:14 +0200)
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

src/uslz.c

index e879b0440e3bfc4c7be20a853a63fb593cdf4fc2..67944413bcb5dc300d123978112bc7f272c7652d 100644 (file)
@@ -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;
                        }