From: Mika Lindqvist Date: Sun, 26 Jan 2025 19:31:36 +0000 (+0200) Subject: Fix shift overflow in inflate and send_code. X-Git-Tag: 2.2.4~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43b27034358d657a2ef6926009d3b5553ad3799c;p=thirdparty%2Fzlib-ng.git Fix shift overflow in inflate and send_code. --- diff --git a/infback.c b/infback.c index 0f5b51f7..b6d98d4a 100644 --- a/infback.c +++ b/infback.c @@ -102,7 +102,7 @@ int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowB do { \ PULL(); \ have--; \ - hold += ((unsigned)(*next++) << bits); \ + hold += ((uint64_t)(*next++) << bits); \ bits += 8; \ } while (0) @@ -154,7 +154,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in z_const unsigned char *next; /* next input */ unsigned char *put; /* next output */ unsigned have, left; /* available input and output */ - uint32_t hold; /* bit buffer */ + uint64_t hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char *from; /* where to copy match bytes from */ diff --git a/inflate.c b/inflate.c index d2ffdcb3..8c373da6 100644 --- a/inflate.c +++ b/inflate.c @@ -291,7 +291,7 @@ int32_t Z_EXPORT PREFIX(inflatePrime)(PREFIX3(stream) *strm, int32_t bits, int32 if (bits > 16 || state->bits + (unsigned int)bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; - state->hold += (unsigned)value << state->bits; + state->hold += (uint64_t)value << state->bits; state->bits += (unsigned int)bits; return Z_OK; } @@ -387,7 +387,7 @@ static void updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t len do { \ if (have == 0) goto inf_leave; \ have--; \ - hold += ((unsigned)(*next++) << bits); \ + hold += ((uint64_t)(*next++) << bits); \ bits += 8; \ } while (0) @@ -479,7 +479,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { unsigned char *put; /* next output */ unsigned char *from; /* where to copy match bytes from */ unsigned have, left; /* available input and output */ - uint32_t hold; /* bit buffer */ + uint64_t hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ uint32_t in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ @@ -577,7 +577,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { case TIME: NEEDBITS(32); if (state->head != NULL) - state->head->time = hold; + state->head->time = (unsigned)(hold); if ((state->flags & 0x0200) && (state->wrap & 4)) CRC4(state->check, hold); INITBITS(); @@ -704,7 +704,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { #endif case DICTID: NEEDBITS(32); - strm->adler = state->check = ZSWAP32(hold); + strm->adler = state->check = ZSWAP32((unsigned)hold); INITBITS(); state->mode = DICT; Z_FALLTHROUGH; @@ -1128,7 +1128,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { #ifdef GUNZIP state->flags ? hold : #endif - ZSWAP32(hold)) != state->check) { + ZSWAP32((unsigned)hold)) != state->check) { SET_BAD("incorrect data check"); break; } diff --git a/inflate.h b/inflate.h index f3bede2e..9d5c4827 100644 --- a/inflate.h +++ b/inflate.h @@ -121,7 +121,7 @@ struct ALIGNED_(64) inflate_state { uint32_t chunksize; /* size of memory copying chunk */ /* bit accumulator */ - uint32_t hold; /* input bit accumulator */ + uint64_t hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ /* fixed and dynamic code tables */ unsigned lenbits; /* index bits for lencode */ @@ -141,7 +141,7 @@ struct ALIGNED_(64) inflate_state { code *next; /* next available space in codes[] */ #if defined(_M_IX86) || defined(_M_ARM) - uint32_t padding[2]; + uint32_t padding[1]; #endif struct crc32_fold_s ALIGNED_(16) crc_fold; diff --git a/trees_emit.h b/trees_emit.h index 922daae5..b5295ee4 100644 --- a/trees_emit.h +++ b/trees_emit.h @@ -38,6 +38,10 @@ extern Z_INTERNAL const int base_dist[D_CODES]; /* If not enough room in bi_buf, use (valid) bits from bi_buf and * (64 - bi_valid) bits from value, leaving (width - (64-bi_valid)) * unused bits in value. + * + * NOTE: Static analyzers can't evaluate value of total_bits, so we + * also need to make sure bi_valid is within acceptable range, + * otherwise the shifts will overflow. */ #define send_bits(s, t_val, t_len, bi_buf, bi_valid) {\ uint64_t val = (uint64_t)t_val;\ @@ -45,10 +49,10 @@ extern Z_INTERNAL const int base_dist[D_CODES]; uint32_t total_bits = bi_valid + len;\ send_bits_trace(s, val, len);\ sent_bits_add(s, len);\ - if (total_bits < BIT_BUF_SIZE) {\ + if (total_bits < BIT_BUF_SIZE && bi_valid < BIT_BUF_SIZE) {\ bi_buf |= val << bi_valid;\ bi_valid = total_bits;\ - } else if (bi_valid == BIT_BUF_SIZE) {\ + } else if (bi_valid >= BIT_BUF_SIZE) {\ put_uint64(s, bi_buf);\ bi_buf = val;\ bi_valid = len;\