]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Fix shift overflow in inflate and send_code.
authorMika Lindqvist <postmaster@raasu.org>
Sun, 26 Jan 2025 19:31:36 +0000 (21:31 +0200)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Sat, 8 Feb 2025 20:43:51 +0000 (21:43 +0100)
infback.c
inflate.c
inflate.h
trees_emit.h

index 0f5b51f78bca27fcbde9d3bc65f03cf0cc4d29c6..b6d98d4a3faba97a02a1d61caa44f45f4a2ca154 100644 (file)
--- 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 */
index d2ffdcb3c3027fe99986ed6c4396a8addd2881dc..8c373da69d42f18a8c63fa7d79fe3dd8d594d07e 100644 (file)
--- 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;
                 }
index f3bede2e414216b06576a668cedb42e21b4341d5..9d5c482707eff230df1903580c5f2dc5e5980301 100644 (file)
--- 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;
 
index 922daae509f520c8633829e3686ddb2fae688823..b5295ee4836accd423f4f7d322d9888a33cd8a37 100644 (file)
@@ -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;\