]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
Revert "Merge patch series "zlib: Address CVE-2016-9841""
authorTom Rini <trini@konsulko.com>
Mon, 1 Jul 2024 01:03:14 +0000 (19:03 -0600)
committerTom Rini <trini@konsulko.com>
Mon, 1 Jul 2024 01:03:14 +0000 (19:03 -0600)
This series brings our zlib code more up to date. However, it drops an
important performance improvement that is required on some of our
supported platforms in order to boot Linux before the watchdog resets
the system. Furthermore, the "post increment" version of this
performance loop was not tested, so while we can fix it, it would then
require re-testing all platforms. At this point in time, we will revert
updating zlib (which has had a potential security issue since 2016) and
fix this in the v2024.10 release.

This reverts commit 4914263c9a14315390d3ccc4816cf3a94cfd156d, reversing
changes made to ef8ef5f77c9a998f76a48277a883af1645b54117.

Reported-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Tom Rini <trini@konsulko.com>
include/u-boot/zlib.h
lib/gzip.c
lib/zlib/deflate.c
lib/zlib/inffast.c
lib/zlib/inflate.c
lib/zlib/inflate.h
lib/zlib/zutil.c

index ee19f46095882c746c4c05e9017578bb955df17f..a33cc8780d336ec7728049b4cbca170db9fe6212 100644 (file)
@@ -49,6 +49,9 @@
 extern "C" {
 #endif
 
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
 /* #include "zconf.h" */        /* included directly here */
 /* zconf.h -- configuration of the zlib compression library
  * Copyright (C) 1995-2005 Jean-loup Gailly.
@@ -481,6 +484,7 @@ typedef gz_header FAR *gz_headerp;
 #define Z_DATA_ERROR   (-3)
 #define Z_MEM_ERROR    (-4)
 #define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
 /* Return codes for the compression/decompression functions. Negative
  * values are errors, positive values are used for special but normal events.
  */
@@ -519,11 +523,11 @@ typedef gz_header FAR *gz_headerp;
 
 ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
 ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
-                       int stream_size));
+                       const char *version, int stream_size));
 ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
 ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
                        int windowBits, int memLevel,
-                       int strategy,
+                       int strategy, const char *version,
                        int stream_size));
 ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
 ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
@@ -549,7 +553,7 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
 
 
 ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
-                       int stream_size));
+                       const char *version, int stream_size));
 ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
 /*
     inflate decompresses as much data as possible, and stops when the input
@@ -739,11 +743,11 @@ ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen,
 */
 
 ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
-                                      int stream_size));
+                                      const char *version, int stream_size));
 #define inflateInit(strm) \
-       inflateInit_((strm), sizeof(z_stream))
+       inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
 #define inflateInit2(strm, windowBits) \
-       inflateInit2_((strm), (windowBits), sizeof(z_stream))
+       inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
 
 #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
        struct internal_state {int dummy;}; /* hack for buggy compilers */
index a9a3df524de115e58cf41a8fd8b6bf00627fd5ea..5d9c19598d5e5bfd84973c20d38ee8d7485ec1e5 100644 (file)
@@ -67,7 +67,7 @@ int zzip(void *dst, unsigned long *lenp, unsigned char *src,
 
        r = deflateInit2_(&s, Z_BEST_SPEED, Z_DEFLATED, window,
                        DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
-                       sizeof(z_stream));
+                       ZLIB_VERSION, sizeof(z_stream));
        if (r != Z_OK) {
                printf ("Error: deflateInit2_() returned %d\n", r);
                return -1;
index 7e1ed4f9b20a46e2ed38d2afd1330b30209f0b4f..4549f4dc12a0030e74d99c77b3f6d9b885342ff0 100644 (file)
@@ -196,30 +196,37 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
     zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
 
 /* ========================================================================= */
-int ZEXPORT deflateInit_(strm, level, stream_size)
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
     z_streamp strm;
     int level;
+    const char *version;
     int stream_size;
 {
     return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
-                         Z_DEFAULT_STRATEGY, stream_size);
+                         Z_DEFAULT_STRATEGY, version, stream_size);
     /* To do: ignore strm->next_in if we use it as window */
 }
 
 /* ========================================================================= */
 int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
-                  stream_size)
+                  version, stream_size)
     z_streamp strm;
     int  level;
     int  method;
     int  windowBits;
     int  memLevel;
     int  strategy;
+    const char *version;
     int stream_size;
 {
     deflate_state *s;
     int wrap = 1;
+    static const char my_version[] = ZLIB_VERSION;
 
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+        return Z_VERSION_ERROR;
+    }
     if (strm == Z_NULL) return Z_STREAM_ERROR;
 
     strm->msg = Z_NULL;
index 5e2a65ad4d273b719aeb3634b455a0c8bde193f8..e3c7f3b892bbb8488c5d5e45f9a9bdd11d7b84a4 100644 (file)
@@ -1,5 +1,5 @@
 /* inffast.c -- fast decoding
- * Copyright (C) 1995-2008, 2010, 2013 Mark Adler
+ * Copyright (C) 1995-2004 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 
 #ifndef ASMINF
 
+/* Allow machine dependent optimization for post-increment or pre-increment.
+   Based on testing to date,
+   Pre-increment preferred for:
+   - PowerPC G3 (Adler)
+   - MIPS R5000 (Randers-Pehrson)
+   Post-increment preferred for:
+   - none
+   No measurable difference:
+   - Pentium III (Anderson)
+   - M68060 (Nikl)
+ */
+#ifdef POSTINC
+#  define OFF 0
+#  define PUP(a) *(a)++
+#else
+#  define OFF 1
+#  define PUP(a) *++(a)
+#endif
+
 /*
    Decode literal, length, and distance codes and write out the resulting
    literal and match bytes until either not enough input or output is
       requires strm->avail_out >= 258 for each loop to avoid checking for
       output space.
  */
-void ZLIB_INTERNAL inflate_fast(strm, start)
-z_streamp strm;
-unsigned start;         /* inflate()'s starting value for strm->avail_out */
+void inflate_fast(z_streamp strm, unsigned start)
+/* start: inflate()'s starting value for strm->avail_out */
 {
     struct inflate_state FAR *state;
-    z_const unsigned char FAR *in;      /* local strm->next_in */
-    z_const unsigned char FAR *last;    /* have enough input while in < last */
+    unsigned char FAR *in;      /* local strm->next_in */
+    unsigned char FAR *last;    /* while in < last, enough input available */
     unsigned char FAR *out;     /* local strm->next_out */
     unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
     unsigned char FAR *end;     /* while out < end, enough space available */
@@ -62,7 +80,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 #endif
     unsigned wsize;             /* window size or zero if not using window */
     unsigned whave;             /* valid bytes in the window */
-    unsigned wnext;             /* window write index */
+    unsigned write;             /* window write index */
     unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
     unsigned long hold;         /* local strm->hold */
     unsigned bits;              /* local strm->bits */
@@ -70,7 +88,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
     code const FAR *dcode;      /* local strm->distcode */
     unsigned lmask;             /* mask for first level of length codes */
     unsigned dmask;             /* mask for first level of distance codes */
-    code here;                  /* retrieved table entry */
+    code this;                  /* retrieved table entry */
     unsigned op;                /* code bits, operation, extra bits, or */
                                 /*  window position, window bytes to copy */
     unsigned len;               /* match length, unused bytes */
@@ -79,7 +97,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 
     /* copy state to local variables */
     state = (struct inflate_state FAR *)strm->state;
-    in = strm->next_in;
+    in = strm->next_in - OFF;
     last = in + (strm->avail_in - 5);
     if (in > last && strm->avail_in > 5) {
         /*
@@ -89,7 +107,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
        strm->avail_in = 0xffffffff - (uintptr_t)in;
         last = in + (strm->avail_in - 5);
     }
-    out = strm->next_out;
+    out = strm->next_out - OFF;
     beg = out - (start - strm->avail_out);
     end = out + (strm->avail_out - 257);
 #ifdef INFLATE_STRICT
@@ -97,7 +115,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 #endif
     wsize = state->wsize;
     whave = state->whave;
-    wnext = state->wnext;
+    write = state->write;
     window = state->window;
     hold = state->hold;
     bits = state->bits;
@@ -110,29 +128,29 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
        input data or output space */
     do {
         if (bits < 15) {
-            hold += (unsigned long)(*in++) << bits;
+            hold += (unsigned long)(PUP(in)) << bits;
             bits += 8;
-            hold += (unsigned long)(*in++) << bits;
+            hold += (unsigned long)(PUP(in)) << bits;
             bits += 8;
         }
-        here = lcode[hold & lmask];
+        this = lcode[hold & lmask];
       dolen:
-        op = (unsigned)(here.bits);
+        op = (unsigned)(this.bits);
         hold >>= op;
         bits -= op;
-        op = (unsigned)(here.op);
+        op = (unsigned)(this.op);
         if (op == 0) {                          /* literal */
-            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+            Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
                     "inflate:         literal '%c'\n" :
-                    "inflate:         literal 0x%02x\n", here.val));
-            *out++ = (unsigned char)(here.val);
+                    "inflate:         literal 0x%02x\n", this.val));
+            PUP(out) = (unsigned char)(this.val);
         }
         else if (op & 16) {                     /* length base */
-            len = (unsigned)(here.val);
+            len = (unsigned)(this.val);
             op &= 15;                           /* number of extra bits */
             if (op) {
                 if (bits < op) {
-                    hold += (unsigned long)(*in++) << bits;
+                    hold += (unsigned long)(PUP(in)) << bits;
                     bits += 8;
                 }
                 len += (unsigned)hold & ((1U << op) - 1);
@@ -141,25 +159,25 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
             }
             Tracevv((stderr, "inflate:         length %u\n", len));
             if (bits < 15) {
-                hold += (unsigned long)(*in++) << bits;
+                hold += (unsigned long)(PUP(in)) << bits;
                 bits += 8;
-                hold += (unsigned long)(*in++) << bits;
+                hold += (unsigned long)(PUP(in)) << bits;
                 bits += 8;
             }
-            here = dcode[hold & dmask];
+            this = dcode[hold & dmask];
           dodist:
-            op = (unsigned)(here.bits);
+            op = (unsigned)(this.bits);
             hold >>= op;
             bits -= op;
-            op = (unsigned)(here.op);
+            op = (unsigned)(this.op);
             if (op & 16) {                      /* distance base */
-                dist = (unsigned)(here.val);
+                dist = (unsigned)(this.val);
                 op &= 15;                       /* number of extra bits */
                 if (bits < op) {
-                    hold += (unsigned long)(*in++) << bits;
+                    hold += (unsigned long)(PUP(in)) << bits;
                     bits += 8;
                     if (bits < op) {
-                        hold += (unsigned long)(*in++) << bits;
+                        hold += (unsigned long)(PUP(in)) << bits;
                         bits += 8;
                     }
                 }
@@ -178,80 +196,108 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
                 if (dist > op) {                /* see if copy from window */
                     op = dist - op;             /* distance back in window */
                     if (op > whave) {
-                        strm->msg =
-                            (char *)"invalid distance too far back";
+                        strm->msg = (char *)"invalid distance too far back";
                         state->mode = BAD;
                         break;
                     }
-                    from = window;
-                    if (wnext == 0) {           /* very common case */
+                    from = window - OFF;
+                    if (write == 0) {           /* very common case */
                         from += wsize - op;
                         if (op < len) {         /* some from window */
                             len -= op;
                             do {
-                                *out++ = *from++;
+                                PUP(out) = PUP(from);
                             } while (--op);
                             from = out - dist;  /* rest from output */
                         }
                     }
-                    else if (wnext < op) {      /* wrap around window */
-                        from += wsize + wnext - op;
-                        op -= wnext;
+                    else if (write < op) {      /* wrap around window */
+                        from += wsize + write - op;
+                        op -= write;
                         if (op < len) {         /* some from end of window */
                             len -= op;
                             do {
-                                *out++ = *from++;
+                                PUP(out) = PUP(from);
                             } while (--op);
-                            from = window;
-                            if (wnext < len) {  /* some from start of window */
-                                op = wnext;
+                            from = window - OFF;
+                            if (write < len) {  /* some from start of window */
+                                op = write;
                                 len -= op;
                                 do {
-                                    *out++ = *from++;
+                                    PUP(out) = PUP(from);
                                 } while (--op);
                                 from = out - dist;      /* rest from output */
                             }
                         }
                     }
                     else {                      /* contiguous in window */
-                        from += wnext - op;
+                        from += write - op;
                         if (op < len) {         /* some from window */
                             len -= op;
                             do {
-                                *out++ = *from++;
+                                PUP(out) = PUP(from);
                             } while (--op);
                             from = out - dist;  /* rest from output */
                         }
                     }
                     while (len > 2) {
-                        *out++ = *from++;
-                        *out++ = *from++;
-                        *out++ = *from++;
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
                         len -= 3;
                     }
                     if (len) {
-                        *out++ = *from++;
+                        PUP(out) = PUP(from);
                         if (len > 1)
-                            *out++ = *from++;
+                            PUP(out) = PUP(from);
                     }
                 }
                 else {
+                   unsigned short *sout;
+                   unsigned long loops;
+
                     from = out - dist;          /* copy direct from output */
-                    do {                        /* minimum length is three */
-                        *out++ = *from++;
-                        *out++ = *from++;
-                        *out++ = *from++;
-                        len -= 3;
-                    } while (len > 2);
-                    if (len) {
-                        *out++ = *from++;
-                        if (len > 1)
-                            *out++ = *from++;
-                    }
+                    /* minimum length is three */
+                   /* Align out addr */
+                   if (!((long)(out - 1 + OFF) & 1)) {
+                       PUP(out) = PUP(from);
+                       len--;
+                   }
+                   sout = (unsigned short *)(out - OFF);
+                   if (dist > 2 ) {
+                       unsigned short *sfrom;
+
+                       sfrom = (unsigned short *)(from - OFF);
+                       loops = len >> 1;
+                       do
+                           PUP(sout) = get_unaligned(++sfrom);
+                       while (--loops);
+                       out = (unsigned char *)sout + OFF;
+                       from = (unsigned char *)sfrom + OFF;
+                   } else { /* dist == 1 or dist == 2 */
+                       unsigned short pat16;
+
+                       pat16 = *(sout-2+2*OFF);
+                       if (dist == 1)
+#if defined(__BIG_ENDIAN)
+                           pat16 = (pat16 & 0xff) | ((pat16 & 0xff ) << 8);
+#elif defined(__LITTLE_ENDIAN)
+                           pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00 ) >> 8);
+#else
+#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined
+#endif
+                       loops = len >> 1;
+                       do
+                           PUP(sout) = pat16;
+                       while (--loops);
+                       out = (unsigned char *)sout + OFF;
+                   }
+                   if (len & 1)
+                       PUP(out) = PUP(from);
                 }
             }
             else if ((op & 64) == 0) {          /* 2nd level distance code */
-                here = dcode[here.val + (hold & ((1U << op) - 1))];
+                this = dcode[this.val + (hold & ((1U << op) - 1))];
                 goto dodist;
             }
             else {
@@ -261,7 +307,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
             }
         }
         else if ((op & 64) == 0) {              /* 2nd level length code */
-            here = lcode[here.val + (hold & ((1U << op) - 1))];
+            this = lcode[this.val + (hold & ((1U << op) - 1))];
             goto dolen;
         }
         else if (op & 32) {                     /* end-of-block */
@@ -283,8 +329,8 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
     hold &= (1U << bits) - 1;
 
     /* update state and return */
-    strm->next_in = in;
-    strm->next_out = out;
+    strm->next_in = in + OFF;
+    strm->next_out = out + OFF;
     strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
     strm->avail_out = (unsigned)(out < end ?
                                  257 + (end - out) : 257 - (out - end));
@@ -297,7 +343,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
    inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
    - Using bit fields for code structure
    - Different op definition to avoid & for extra bits (do & for table bits)
-   - Three separate decoding do-loops for direct, window, and wnext == 0
+   - Three separate decoding do-loops for direct, window, and write == 0
    - Special case for distance > 1 copies to do overlapped load and store copy
    - Explicit branch predictions (based on measured branch probabilities)
    - Deferring match copy and interspersed it with decoding subsequent codes
index f7e81fc8b2a06575fd0795ddca7a5b20c72eccde..8f767b7b9d2d92bbca9d35337d054592922215ae 100644 (file)
@@ -21,7 +21,7 @@ int ZEXPORT inflateReset(z_streamp strm)
     state->head = Z_NULL;
     state->wsize = 0;
     state->whave = 0;
-    state->wnext = 0;
+    state->write = 0;
     state->hold = 0;
     state->bits = 0;
     state->lencode = state->distcode = state->next = state->codes;
@@ -30,11 +30,14 @@ int ZEXPORT inflateReset(z_streamp strm)
     return Z_OK;
 }
 
-int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
+int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version,
                          int stream_size)
 {
     struct inflate_state FAR *state;
 
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
     if (strm == Z_NULL) return Z_STREAM_ERROR;
     strm->msg = Z_NULL;                 /* in case we return an error */
     if (strm->zalloc == (alloc_func)0) {
@@ -67,9 +70,9 @@ int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
     return inflateReset(strm);
 }
 
-int ZEXPORT inflateInit_(z_streamp strm, int stream_size)
+int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size)
 {
-    return inflateInit2_(strm, DEF_WBITS, stream_size);
+    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
 }
 
 local void fixedtables(struct inflate_state FAR *state)
@@ -112,7 +115,7 @@ local int updatewindow(z_streamp strm, unsigned out)
     /* if window not in use yet, initialize */
     if (state->wsize == 0) {
         state->wsize = 1U << state->wbits;
-        state->wnext = 0;
+        state->write = 0;
         state->whave = 0;
     }
 
@@ -120,22 +123,22 @@ local int updatewindow(z_streamp strm, unsigned out)
     copy = out - strm->avail_out;
     if (copy >= state->wsize) {
         zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
-        state->wnext = 0;
+        state->write = 0;
         state->whave = state->wsize;
     }
     else {
-        dist = state->wsize - state->wnext;
+        dist = state->wsize - state->write;
         if (dist > copy) dist = copy;
-        zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
+        zmemcpy(state->window + state->write, strm->next_out - copy, dist);
         copy -= dist;
         if (copy) {
             zmemcpy(state->window, strm->next_out - copy, copy);
-            state->wnext = copy;
+            state->write = copy;
             state->whave = state->wsize;
         }
         else {
-            state->wnext += dist;
-            if (state->wnext == state->wsize) state->wnext = 0;
+            state->write += dist;
+            if (state->write == state->wsize) state->write = 0;
             if (state->whave < state->wsize) state->whave += dist;
         }
     }
@@ -820,12 +823,12 @@ int ZEXPORT inflate(z_streamp strm, int flush)
             copy = out - left;
             if (state->offset > copy) {         /* copy from window */
                 copy = state->offset - copy;
-                if (copy > state->wnext) {
-                    copy -= state->wnext;
+                if (copy > state->write) {
+                    copy -= state->write;
                     from = state->window + (state->wsize - copy);
                 }
                 else
-                    from = state->window + (state->wnext - copy);
+                    from = state->window + (state->write - copy);
                 if (copy > state->length) copy = state->length;
             }
             else {                              /* copy from output */
index 2657d611cda3b8a366294589fc45f56c04dce390..07bd3e78a7c7e763f2dbb939320b01a9897df019 100644 (file)
@@ -88,7 +88,7 @@ struct inflate_state {
     unsigned wbits;             /* log base 2 of requested window size */
     unsigned wsize;             /* window size or zero if not using window */
     unsigned whave;             /* valid bytes in the window */
-    unsigned wnext;             /* window write index */
+    unsigned write;             /* window write index */
     unsigned char FAR *window;  /* allocated sliding window, if needed */
         /* bit accumulator */
     unsigned long hold;         /* input bit accumulator */
index ec21b458fccef1885de0334809aa1f6e4a001b8b..609aac55ce11f015d79f805b29f3c7eec8d014cf 100644 (file)
@@ -21,6 +21,7 @@ const char * const z_errmsg[10] = {
 "data error",          /* Z_DATA_ERROR    (-3) */
 "insufficient memory", /* Z_MEM_ERROR     (-4) */
 "buffer error",        /* Z_BUF_ERROR     (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
 ""};
 
 #ifdef DEBUG