1 >From 9aaec95e82117c1cb0f9624264c3618fc380cecb Mon Sep 17 00:00:00 2001
2 From: Mark Adler <madler@alumni.caltech.edu>
3 Date: Wed, 21 Sep 2016 22:25:21 -0700
4 Subject: [PATCH] Use post-increment only in inffast.c.
6 An old inffast.c optimization turns out to not be optimal anymore
7 with modern compilers, and furthermore was not compliant with the
8 C standard, for which decrementing a pointer before its allocated
9 memory is undefined. Per the recommendation of a security audit of
10 the zlib code by Trail of Bits and TrustInSoft, in support of the
11 Mozilla Foundation, this "optimization" was removed, in order to
12 avoid the possibility of undefined behavior.
14 inffast.c | 81 +++++++++++++++++++++----------------------------------
15 1 file changed, 31 insertions(+), 50 deletions(-)
17 diff --git a/zlib/inffast.c b/zlib/inffast.c
18 index bda59ceb..f0d163db 100644
25 -/* Allow machine dependent optimization for post-increment or pre-increment.
26 - Based on testing to date,
27 - Pre-increment preferred for:
28 - - PowerPC G3 (Adler)
29 - - MIPS R5000 (Randers-Pehrson)
30 - Post-increment preferred for:
32 - No measurable difference:
33 - - Pentium III (Anderson)
38 -# define PUP(a) *(a)++
41 -# define PUP(a) *++(a)
45 Decode literal, length, and distance codes and write out the resulting
46 literal and match bytes until either not enough input or output is
47 @@ -96,9 +77,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
49 /* copy state to local variables */
50 state = (struct inflate_state FAR *)strm->state;
51 - in = strm->next_in - OFF;
53 last = in + (strm->avail_in - 5);
54 - out = strm->next_out - OFF;
55 + out = strm->next_out;
56 beg = out - (start - strm->avail_out);
57 end = out + (strm->avail_out - 257);
59 @@ -119,9 +100,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
60 input data or output space */
63 - hold += (unsigned long)(PUP(in)) << bits;
64 + hold += (unsigned long)(*in++) << bits;
66 - hold += (unsigned long)(PUP(in)) << bits;
67 + hold += (unsigned long)(*in++) << bits;
70 here = lcode[hold & lmask];
71 @@ -134,14 +115,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
72 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
73 "inflate: literal '%c'\n" :
74 "inflate: literal 0x%02x\n", here.val));
75 - PUP(out) = (unsigned char)(here.val);
76 + *out++ = (unsigned char)(here.val);
78 else if (op & 16) { /* length base */
79 len = (unsigned)(here.val);
80 op &= 15; /* number of extra bits */
83 - hold += (unsigned long)(PUP(in)) << bits;
84 + hold += (unsigned long)(*in++) << bits;
87 len += (unsigned)hold & ((1U << op) - 1);
88 @@ -150,9 +131,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
90 Tracevv((stderr, "inflate: length %u\n", len));
92 - hold += (unsigned long)(PUP(in)) << bits;
93 + hold += (unsigned long)(*in++) << bits;
95 - hold += (unsigned long)(PUP(in)) << bits;
96 + hold += (unsigned long)(*in++) << bits;
99 here = dcode[hold & dmask];
100 @@ -165,10 +146,10 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
101 dist = (unsigned)(here.val);
102 op &= 15; /* number of extra bits */
104 - hold += (unsigned long)(PUP(in)) << bits;
105 + hold += (unsigned long)(*in++) << bits;
108 - hold += (unsigned long)(PUP(in)) << bits;
109 + hold += (unsigned long)(*in++) << bits;
113 @@ -196,30 +177,30 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
114 #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
115 if (len <= op - whave) {
126 } while (--op > whave);
130 - PUP(out) = PUP(from);
137 - from = window - OFF;
139 if (wnext == 0) { /* very common case */
141 if (op < len) { /* some from window */
144 - PUP(out) = PUP(from);
147 from = out - dist; /* rest from output */
149 @@ -230,14 +211,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
150 if (op < len) { /* some from end of window */
153 - PUP(out) = PUP(from);
156 - from = window - OFF;
158 if (wnext < len) { /* some from start of window */
162 - PUP(out) = PUP(from);
165 from = out - dist; /* rest from output */
167 @@ -248,35 +229,35 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
168 if (op < len) { /* some from window */
171 - PUP(out) = PUP(from);
174 from = out - dist; /* rest from output */
178 - PUP(out) = PUP(from);
179 - PUP(out) = PUP(from);
180 - PUP(out) = PUP(from);
187 - PUP(out) = PUP(from);
190 - PUP(out) = PUP(from);
195 from = out - dist; /* copy direct from output */
196 do { /* minimum length is three */
197 - PUP(out) = PUP(from);
198 - PUP(out) = PUP(from);
199 - PUP(out) = PUP(from);
206 - PUP(out) = PUP(from);
209 - PUP(out) = PUP(from);
214 @@ -313,8 +294,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
215 hold &= (1U << bits) - 1;
217 /* update state and return */
218 - strm->next_in = in + OFF;
219 - strm->next_out = out + OFF;
220 + strm->next_in = in;
221 + strm->next_out = out;
222 strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
223 strm->avail_out = (unsigned)(out < end ?
224 257 + (end - out) : 257 - (out - end));