|
@@ -0,0 +1,228 @@
|
|
|
+From 9aaec95e82117c1cb0f9624264c3618fc380cecb Mon Sep 17 00:00:00 2001
|
|
|
+From: Mark Adler <madler@alumni.caltech.edu>
|
|
|
+Date: Wed, 21 Sep 2016 22:25:21 -0700
|
|
|
+Subject: [PATCH] Use post-increment only in inffast.c.
|
|
|
+
|
|
|
+An old inffast.c optimization turns out to not be optimal anymore
|
|
|
+with modern compilers, and furthermore was not compliant with the
|
|
|
+C standard, for which decrementing a pointer before its allocated
|
|
|
+memory is undefined. Per the recommendation of a security audit of
|
|
|
+the zlib code by Trail of Bits and TrustInSoft, in support of the
|
|
|
+Mozilla Foundation, this "optimization" was removed, in order to
|
|
|
+avoid the possibility of undefined behavior.
|
|
|
+
|
|
|
+CVE: CVE-2016-9841
|
|
|
+Upstream-Status: Backport
|
|
|
+Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
|
|
|
+---
|
|
|
+ zlib/inffast.c | 81 +++++++++++++++++++++----------------------------------
|
|
|
+ 1 file changed, 31 insertions(+), 50 deletions(-)
|
|
|
+
|
|
|
+diff --git a/zlib/inffast.c b/zlib/inffast.c
|
|
|
+index bda59ceb..f0d163db 100644
|
|
|
+--- a/zlib/inffast.c
|
|
|
++++ b/zlib/inffast.c
|
|
|
+@@ -10,25 +10,6 @@
|
|
|
+
|
|
|
+ #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
|
|
|
+@@ -96,9 +77,9 @@ 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 - OFF;
|
|
|
++ in = strm->next_in;
|
|
|
+ last = in + (strm->avail_in - 5);
|
|
|
+- out = strm->next_out - OFF;
|
|
|
++ out = strm->next_out;
|
|
|
+ beg = out - (start - strm->avail_out);
|
|
|
+ end = out + (strm->avail_out - 257);
|
|
|
+ #ifdef INFLATE_STRICT
|
|
|
+@@ -119,9 +100,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|
|
+ input data or output space */
|
|
|
+ do {
|
|
|
+ if (bits < 15) {
|
|
|
+- hold += (unsigned long)(PUP(in)) << bits;
|
|
|
++ hold += (unsigned long)(*in++) << bits;
|
|
|
+ bits += 8;
|
|
|
+- hold += (unsigned long)(PUP(in)) << bits;
|
|
|
++ hold += (unsigned long)(*in++) << bits;
|
|
|
+ bits += 8;
|
|
|
+ }
|
|
|
+ here = lcode[hold & lmask];
|
|
|
+@@ -134,14 +115,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|
|
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
|
|
+ "inflate: literal '%c'\n" :
|
|
|
+ "inflate: literal 0x%02x\n", here.val));
|
|
|
+- PUP(out) = (unsigned char)(here.val);
|
|
|
++ *out++ = (unsigned char)(here.val);
|
|
|
+ }
|
|
|
+ else if (op & 16) { /* length base */
|
|
|
+ len = (unsigned)(here.val);
|
|
|
+ op &= 15; /* number of extra bits */
|
|
|
+ if (op) {
|
|
|
+ if (bits < op) {
|
|
|
+- hold += (unsigned long)(PUP(in)) << bits;
|
|
|
++ hold += (unsigned long)(*in++) << bits;
|
|
|
+ bits += 8;
|
|
|
+ }
|
|
|
+ len += (unsigned)hold & ((1U << op) - 1);
|
|
|
+@@ -150,9 +131,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|
|
+ }
|
|
|
+ Tracevv((stderr, "inflate: length %u\n", len));
|
|
|
+ if (bits < 15) {
|
|
|
+- hold += (unsigned long)(PUP(in)) << bits;
|
|
|
++ hold += (unsigned long)(*in++) << bits;
|
|
|
+ bits += 8;
|
|
|
+- hold += (unsigned long)(PUP(in)) << bits;
|
|
|
++ hold += (unsigned long)(*in++) << bits;
|
|
|
+ bits += 8;
|
|
|
+ }
|
|
|
+ here = dcode[hold & dmask];
|
|
|
+@@ -165,10 +146,10 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|
|
+ dist = (unsigned)(here.val);
|
|
|
+ op &= 15; /* number of extra bits */
|
|
|
+ if (bits < op) {
|
|
|
+- hold += (unsigned long)(PUP(in)) << bits;
|
|
|
++ hold += (unsigned long)(*in++) << bits;
|
|
|
+ bits += 8;
|
|
|
+ if (bits < op) {
|
|
|
+- hold += (unsigned long)(PUP(in)) << bits;
|
|
|
++ hold += (unsigned long)(*in++) << bits;
|
|
|
+ bits += 8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+@@ -196,30 +177,30 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|
|
+ #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
|
|
+ if (len <= op - whave) {
|
|
|
+ do {
|
|
|
+- PUP(out) = 0;
|
|
|
++ *out++ = 0;
|
|
|
+ } while (--len);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ len -= op - whave;
|
|
|
+ do {
|
|
|
+- PUP(out) = 0;
|
|
|
++ *out++ = 0;
|
|
|
+ } while (--op > whave);
|
|
|
+ if (op == 0) {
|
|
|
+ from = out - dist;
|
|
|
+ do {
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
+ } while (--len);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+- from = window - OFF;
|
|
|
++ from = window;
|
|
|
+ if (wnext == 0) { /* very common case */
|
|
|
+ from += wsize - op;
|
|
|
+ if (op < len) { /* some from window */
|
|
|
+ len -= op;
|
|
|
+ do {
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
+ } while (--op);
|
|
|
+ from = out - dist; /* rest from output */
|
|
|
+ }
|
|
|
+@@ -230,14 +211,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|
|
+ if (op < len) { /* some from end of window */
|
|
|
+ len -= op;
|
|
|
+ do {
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
+ } while (--op);
|
|
|
+- from = window - OFF;
|
|
|
++ from = window;
|
|
|
+ if (wnext < len) { /* some from start of window */
|
|
|
+ op = wnext;
|
|
|
+ len -= op;
|
|
|
+ do {
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
+ } while (--op);
|
|
|
+ from = out - dist; /* rest from output */
|
|
|
+ }
|
|
|
+@@ -248,35 +229,35 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|
|
+ if (op < len) { /* some from window */
|
|
|
+ len -= op;
|
|
|
+ do {
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
+ } while (--op);
|
|
|
+ from = out - dist; /* rest from output */
|
|
|
+ }
|
|
|
+ }
|
|
|
+ while (len > 2) {
|
|
|
+- PUP(out) = PUP(from);
|
|
|
+- PUP(out) = PUP(from);
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
++ *out++ = *from++;
|
|
|
++ *out++ = *from++;
|
|
|
+ len -= 3;
|
|
|
+ }
|
|
|
+ if (len) {
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
+ if (len > 1)
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ from = out - dist; /* copy direct from output */
|
|
|
+ do { /* minimum length is three */
|
|
|
+- PUP(out) = PUP(from);
|
|
|
+- PUP(out) = PUP(from);
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
++ *out++ = *from++;
|
|
|
++ *out++ = *from++;
|
|
|
+ len -= 3;
|
|
|
+ } while (len > 2);
|
|
|
+ if (len) {
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
+ if (len > 1)
|
|
|
+- PUP(out) = PUP(from);
|
|
|
++ *out++ = *from++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+@@ -313,8 +294,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|
|
+ hold &= (1U << bits) - 1;
|
|
|
+
|
|
|
+ /* update state and return */
|
|
|
+- strm->next_in = in + OFF;
|
|
|
+- strm->next_out = out + OFF;
|
|
|
++ strm->next_in = in;
|
|
|
++ strm->next_out = out;
|
|
|
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
|
|
|
+ strm->avail_out = (unsigned)(out < end ?
|
|
|
+ 257 + (end - out) : 257 - (out - end));
|