diff options
Diffstat (limited to 'inffast.c')
-rw-r--r-- | inffast.c | 57 |
1 files changed, 39 insertions, 18 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* inffast.c -- fast decoding | 1 | /* inffast.c -- fast decoding |
2 | * Copyright (C) 1995-2004 Mark Adler | 2 | * Copyright (C) 1995-2006 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -87,7 +87,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ | |||
87 | code const FAR *dcode; /* local strm->distcode */ | 87 | code const FAR *dcode; /* local strm->distcode */ |
88 | unsigned lmask; /* mask for first level of length codes */ | 88 | unsigned lmask; /* mask for first level of length codes */ |
89 | unsigned dmask; /* mask for first level of distance codes */ | 89 | unsigned dmask; /* mask for first level of distance codes */ |
90 | code this; /* retrieved table entry */ | 90 | code here; /* retrieved table entry */ |
91 | unsigned op; /* code bits, operation, extra bits, or */ | 91 | unsigned op; /* code bits, operation, extra bits, or */ |
92 | /* window position, window bytes to copy */ | 92 | /* window position, window bytes to copy */ |
93 | unsigned len; /* match length, unused bytes */ | 93 | unsigned len; /* match length, unused bytes */ |
@@ -124,20 +124,20 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ | |||
124 | hold += (unsigned long)(PUP(in)) << bits; | 124 | hold += (unsigned long)(PUP(in)) << bits; |
125 | bits += 8; | 125 | bits += 8; |
126 | } | 126 | } |
127 | this = lcode[hold & lmask]; | 127 | here = lcode[hold & lmask]; |
128 | dolen: | 128 | dolen: |
129 | op = (unsigned)(this.bits); | 129 | op = (unsigned)(here.bits); |
130 | hold >>= op; | 130 | hold >>= op; |
131 | bits -= op; | 131 | bits -= op; |
132 | op = (unsigned)(this.op); | 132 | op = (unsigned)(here.op); |
133 | if (op == 0) { /* literal */ | 133 | if (op == 0) { /* literal */ |
134 | Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? | 134 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? |
135 | "inflate: literal '%c'\n" : | 135 | "inflate: literal '%c'\n" : |
136 | "inflate: literal 0x%02x\n", this.val)); | 136 | "inflate: literal 0x%02x\n", here.val)); |
137 | PUP(out) = (unsigned char)(this.val); | 137 | PUP(out) = (unsigned char)(here.val); |
138 | } | 138 | } |
139 | else if (op & 16) { /* length base */ | 139 | else if (op & 16) { /* length base */ |
140 | len = (unsigned)(this.val); | 140 | len = (unsigned)(here.val); |
141 | op &= 15; /* number of extra bits */ | 141 | op &= 15; /* number of extra bits */ |
142 | if (op) { | 142 | if (op) { |
143 | if (bits < op) { | 143 | if (bits < op) { |
@@ -155,14 +155,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ | |||
155 | hold += (unsigned long)(PUP(in)) << bits; | 155 | hold += (unsigned long)(PUP(in)) << bits; |
156 | bits += 8; | 156 | bits += 8; |
157 | } | 157 | } |
158 | this = dcode[hold & dmask]; | 158 | here = dcode[hold & dmask]; |
159 | dodist: | 159 | dodist: |
160 | op = (unsigned)(this.bits); | 160 | op = (unsigned)(here.bits); |
161 | hold >>= op; | 161 | hold >>= op; |
162 | bits -= op; | 162 | bits -= op; |
163 | op = (unsigned)(this.op); | 163 | op = (unsigned)(here.op); |
164 | if (op & 16) { /* distance base */ | 164 | if (op & 16) { /* distance base */ |
165 | dist = (unsigned)(this.val); | 165 | dist = (unsigned)(here.val); |
166 | op &= 15; /* number of extra bits */ | 166 | op &= 15; /* number of extra bits */ |
167 | if (bits < op) { | 167 | if (bits < op) { |
168 | hold += (unsigned long)(PUP(in)) << bits; | 168 | hold += (unsigned long)(PUP(in)) << bits; |
@@ -187,9 +187,30 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ | |||
187 | if (dist > op) { /* see if copy from window */ | 187 | if (dist > op) { /* see if copy from window */ |
188 | op = dist - op; /* distance back in window */ | 188 | op = dist - op; /* distance back in window */ |
189 | if (op > whave) { | 189 | if (op > whave) { |
190 | strm->msg = (char *)"invalid distance too far back"; | 190 | if (state->sane) { |
191 | state->mode = BAD; | 191 | strm->msg = (char *)"invalid distance too far back"; |
192 | break; | 192 | state->mode = BAD; |
193 | break; | ||
194 | } | ||
195 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR | ||
196 | if (len <= op - whave) { | ||
197 | do { | ||
198 | PUP(out) = 0; | ||
199 | } while (--len); | ||
200 | continue; | ||
201 | } | ||
202 | len -= op - whave; | ||
203 | do { | ||
204 | PUP(out) = 0; | ||
205 | } while (--op > whave); | ||
206 | if (op == 0) { | ||
207 | from = out - dist; | ||
208 | do { | ||
209 | PUP(out) = PUP(from); | ||
210 | } while (--len); | ||
211 | continue; | ||
212 | } | ||
213 | #endif | ||
193 | } | 214 | } |
194 | from = window - OFF; | 215 | from = window - OFF; |
195 | if (write == 0) { /* very common case */ | 216 | if (write == 0) { /* very common case */ |
@@ -259,7 +280,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ | |||
259 | } | 280 | } |
260 | } | 281 | } |
261 | else if ((op & 64) == 0) { /* 2nd level distance code */ | 282 | else if ((op & 64) == 0) { /* 2nd level distance code */ |
262 | this = dcode[this.val + (hold & ((1U << op) - 1))]; | 283 | here = dcode[here.val + (hold & ((1U << op) - 1))]; |
263 | goto dodist; | 284 | goto dodist; |
264 | } | 285 | } |
265 | else { | 286 | else { |
@@ -269,7 +290,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ | |||
269 | } | 290 | } |
270 | } | 291 | } |
271 | else if ((op & 64) == 0) { /* 2nd level length code */ | 292 | else if ((op & 64) == 0) { /* 2nd level length code */ |
272 | this = lcode[this.val + (hold & ((1U << op) - 1))]; | 293 | here = lcode[here.val + (hold & ((1U << op) - 1))]; |
273 | goto dolen; | 294 | goto dolen; |
274 | } | 295 | } |
275 | else if (op & 32) { /* end-of-block */ | 296 | else if (op & 32) { /* end-of-block */ |