blob: 3942176de54d53b9315f064df17cc9c2f0857160 [file] [log] [blame]
Brad Bishop96ff1982019-08-19 13:50:42 -04001From 9aaec95e82117c1cb0f9624264c3618fc380cecb Mon Sep 17 00:00:00 2001
2From: Mark Adler <madler@alumni.caltech.edu>
3Date: Wed, 21 Sep 2016 22:25:21 -0700
4Subject: [PATCH] Use post-increment only in inffast.c.
5
6An old inffast.c optimization turns out to not be optimal anymore
7with modern compilers, and furthermore was not compliant with the
8C standard, for which decrementing a pointer before its allocated
9memory is undefined. Per the recommendation of a security audit of
10the zlib code by Trail of Bits and TrustInSoft, in support of the
11Mozilla Foundation, this "optimization" was removed, in order to
12avoid the possibility of undefined behavior.
13
14CVE: CVE-2016-9841
15Upstream-Status: Backport
16Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
17---
18 zlib/inffast.c | 81 +++++++++++++++++++++----------------------------------
19 1 file changed, 31 insertions(+), 50 deletions(-)
20
21diff --git a/zlib/inffast.c b/zlib/inffast.c
22index bda59ceb..f0d163db 100644
23--- a/zlib/inffast.c
24+++ b/zlib/inffast.c
25@@ -10,25 +10,6 @@
26
27 #ifndef ASMINF
28
29-/* Allow machine dependent optimization for post-increment or pre-increment.
30- Based on testing to date,
31- Pre-increment preferred for:
32- - PowerPC G3 (Adler)
33- - MIPS R5000 (Randers-Pehrson)
34- Post-increment preferred for:
35- - none
36- No measurable difference:
37- - Pentium III (Anderson)
38- - M68060 (Nikl)
39- */
40-#ifdef POSTINC
41-# define OFF 0
42-# define PUP(a) *(a)++
43-#else
44-# define OFF 1
45-# define PUP(a) *++(a)
46-#endif
47-
48 /*
49 Decode literal, length, and distance codes and write out the resulting
50 literal and match bytes until either not enough input or output is
51@@ -96,9 +77,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
52
53 /* copy state to local variables */
54 state = (struct inflate_state FAR *)strm->state;
55- in = strm->next_in - OFF;
56+ in = strm->next_in;
57 last = in + (strm->avail_in - 5);
58- out = strm->next_out - OFF;
59+ out = strm->next_out;
60 beg = out - (start - strm->avail_out);
61 end = out + (strm->avail_out - 257);
62 #ifdef INFLATE_STRICT
63@@ -119,9 +100,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
64 input data or output space */
65 do {
66 if (bits < 15) {
67- hold += (unsigned long)(PUP(in)) << bits;
68+ hold += (unsigned long)(*in++) << bits;
69 bits += 8;
70- hold += (unsigned long)(PUP(in)) << bits;
71+ hold += (unsigned long)(*in++) << bits;
72 bits += 8;
73 }
74 here = lcode[hold & lmask];
75@@ -134,14 +115,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
76 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
77 "inflate: literal '%c'\n" :
78 "inflate: literal 0x%02x\n", here.val));
79- PUP(out) = (unsigned char)(here.val);
80+ *out++ = (unsigned char)(here.val);
81 }
82 else if (op & 16) { /* length base */
83 len = (unsigned)(here.val);
84 op &= 15; /* number of extra bits */
85 if (op) {
86 if (bits < op) {
87- hold += (unsigned long)(PUP(in)) << bits;
88+ hold += (unsigned long)(*in++) << bits;
89 bits += 8;
90 }
91 len += (unsigned)hold & ((1U << op) - 1);
92@@ -150,9 +131,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
93 }
94 Tracevv((stderr, "inflate: length %u\n", len));
95 if (bits < 15) {
96- hold += (unsigned long)(PUP(in)) << bits;
97+ hold += (unsigned long)(*in++) << bits;
98 bits += 8;
99- hold += (unsigned long)(PUP(in)) << bits;
100+ hold += (unsigned long)(*in++) << bits;
101 bits += 8;
102 }
103 here = dcode[hold & dmask];
104@@ -165,10 +146,10 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
105 dist = (unsigned)(here.val);
106 op &= 15; /* number of extra bits */
107 if (bits < op) {
108- hold += (unsigned long)(PUP(in)) << bits;
109+ hold += (unsigned long)(*in++) << bits;
110 bits += 8;
111 if (bits < op) {
112- hold += (unsigned long)(PUP(in)) << bits;
113+ hold += (unsigned long)(*in++) << bits;
114 bits += 8;
115 }
116 }
117@@ -196,30 +177,30 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
118 #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
119 if (len <= op - whave) {
120 do {
121- PUP(out) = 0;
122+ *out++ = 0;
123 } while (--len);
124 continue;
125 }
126 len -= op - whave;
127 do {
128- PUP(out) = 0;
129+ *out++ = 0;
130 } while (--op > whave);
131 if (op == 0) {
132 from = out - dist;
133 do {
134- PUP(out) = PUP(from);
135+ *out++ = *from++;
136 } while (--len);
137 continue;
138 }
139 #endif
140 }
141- from = window - OFF;
142+ from = window;
143 if (wnext == 0) { /* very common case */
144 from += wsize - op;
145 if (op < len) { /* some from window */
146 len -= op;
147 do {
148- PUP(out) = PUP(from);
149+ *out++ = *from++;
150 } while (--op);
151 from = out - dist; /* rest from output */
152 }
153@@ -230,14 +211,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
154 if (op < len) { /* some from end of window */
155 len -= op;
156 do {
157- PUP(out) = PUP(from);
158+ *out++ = *from++;
159 } while (--op);
160- from = window - OFF;
161+ from = window;
162 if (wnext < len) { /* some from start of window */
163 op = wnext;
164 len -= op;
165 do {
166- PUP(out) = PUP(from);
167+ *out++ = *from++;
168 } while (--op);
169 from = out - dist; /* rest from output */
170 }
171@@ -248,35 +229,35 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
172 if (op < len) { /* some from window */
173 len -= op;
174 do {
175- PUP(out) = PUP(from);
176+ *out++ = *from++;
177 } while (--op);
178 from = out - dist; /* rest from output */
179 }
180 }
181 while (len > 2) {
182- PUP(out) = PUP(from);
183- PUP(out) = PUP(from);
184- PUP(out) = PUP(from);
185+ *out++ = *from++;
186+ *out++ = *from++;
187+ *out++ = *from++;
188 len -= 3;
189 }
190 if (len) {
191- PUP(out) = PUP(from);
192+ *out++ = *from++;
193 if (len > 1)
194- PUP(out) = PUP(from);
195+ *out++ = *from++;
196 }
197 }
198 else {
199 from = out - dist; /* copy direct from output */
200 do { /* minimum length is three */
201- PUP(out) = PUP(from);
202- PUP(out) = PUP(from);
203- PUP(out) = PUP(from);
204+ *out++ = *from++;
205+ *out++ = *from++;
206+ *out++ = *from++;
207 len -= 3;
208 } while (len > 2);
209 if (len) {
210- PUP(out) = PUP(from);
211+ *out++ = *from++;
212 if (len > 1)
213- PUP(out) = PUP(from);
214+ *out++ = *from++;
215 }
216 }
217 }
218@@ -313,8 +294,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
219 hold &= (1U << bits) - 1;
220
221 /* update state and return */
222- strm->next_in = in + OFF;
223- strm->next_out = out + OFF;
224+ strm->next_in = in;
225+ strm->next_out = out;
226 strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
227 strm->avail_out = (unsigned)(out < end ?
228 257 + (end - out) : 257 - (out - end));