53{
55 z_const unsigned char FAR *in;
56 z_const
unsigned char FAR *
last;
57 unsigned char FAR *out;
58 unsigned char FAR *beg;
59 unsigned char FAR *end;
60#ifdef INFLATE_STRICT
62#endif
69 code const FAR *lcode;
70 code const FAR *dcode;
71 unsigned lmask;
72 unsigned dmask;
74 unsigned op;
75
76 unsigned len;
77 unsigned dist;
78 unsigned char FAR *from;
79
80
85 beg = out - (start -
strm->avail_out);
86 end = out + (
strm->avail_out - 257);
87#ifdef INFLATE_STRICT
89#endif
96 lcode = state->lencode;
97 dcode = state->distcode;
98 lmask = (1U << state->lenbits) - 1;
99 dmask = (1U << state->distbits) - 1;
100
101
102
103 do {
105 hold += (
unsigned long)(*in++) <<
bits;
107 hold += (
unsigned long)(*in++) <<
bits;
109 }
110 here = lcode + (
hold & lmask);
111 dolen:
112 op = (unsigned)(here->bits);
115 op = (unsigned)(here->op);
116 if (op == 0) {
117 Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
118 "inflate: literal '%c'\n" :
119 "inflate: literal 0x%02x\n", here->val));
120 *out++ = (unsigned char)(here->val);
121 }
122 else if (op & 16) {
123 len = (unsigned)(here->val);
124 op &= 15;
125 if (op) {
127 hold += (
unsigned long)(*in++) <<
bits;
129 }
130 len += (unsigned)
hold & ((1U << op) - 1);
133 }
134 Tracevv((stderr,
"inflate: length %u\n", len));
136 hold += (
unsigned long)(*in++) <<
bits;
138 hold += (
unsigned long)(*in++) <<
bits;
140 }
141 here = dcode + (
hold & dmask);
142 dodist:
143 op = (unsigned)(here->bits);
146 op = (unsigned)(here->op);
147 if (op & 16) {
148 dist = (unsigned)(here->val);
149 op &= 15;
151 hold += (
unsigned long)(*in++) <<
bits;
154 hold += (
unsigned long)(*in++) <<
bits;
156 }
157 }
158 dist += (unsigned)
hold & ((1U << op) - 1);
159#ifdef INFLATE_STRICT
161 strm->msg = (
char *)
"invalid distance too far back";
163 break;
164 }
165#endif
168 Tracevv((stderr,
"inflate: distance %u\n", dist));
169 op = (unsigned)(out - beg);
170 if (dist > op) {
171 op = dist - op;
173 if (state->sane) {
175 (char *)"invalid distance too far back";
177 break;
178 }
179#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
180 if (len <= op -
whave) {
181 do {
182 *out++ = 0;
183 } while (--len);
184 continue;
185 }
187 do {
188 *out++ = 0;
189 }
while (--op >
whave);
190 if (op == 0) {
191 from = out - dist;
192 do {
193 *out++ = *from++;
194 } while (--len);
195 continue;
196 }
197#endif
198 }
202 if (op < len) {
203 len -= op;
204 do {
205 *out++ = *from++;
206 } while (--op);
207 from = out - dist;
208 }
209 }
210 else if (
wnext < op) {
213 if (op < len) {
214 len -= op;
215 do {
216 *out++ = *from++;
217 } while (--op);
221 len -= op;
222 do {
223 *out++ = *from++;
224 } while (--op);
225 from = out - dist;
226 }
227 }
228 }
229 else {
231 if (op < len) {
232 len -= op;
233 do {
234 *out++ = *from++;
235 } while (--op);
236 from = out - dist;
237 }
238 }
239 while (len > 2) {
240 *out++ = *from++;
241 *out++ = *from++;
242 *out++ = *from++;
243 len -= 3;
244 }
245 if (len) {
246 *out++ = *from++;
247 if (len > 1)
248 *out++ = *from++;
249 }
250 }
251 else {
252 from = out - dist;
253 do {
254 *out++ = *from++;
255 *out++ = *from++;
256 *out++ = *from++;
257 len -= 3;
258 } while (len > 2);
259 if (len) {
260 *out++ = *from++;
261 if (len > 1)
262 *out++ = *from++;
263 }
264 }
265 }
266 else if ((op & 64) == 0) {
267 here = dcode + here->val + (
hold & ((1U << op) - 1));
268 goto dodist;
269 }
270 else {
271 strm->msg = (
char *)
"invalid distance code";
273 break;
274 }
275 }
276 else if ((op & 64) == 0) {
277 here = lcode + here->val + (
hold & ((1U << op) - 1));
278 goto dolen;
279 }
280 else if (op & 32) {
281 Tracevv((stderr,
"inflate: end of block\n"));
283 break;
284 }
285 else {
286 strm->msg = (
char *)
"invalid literal/length code";
288 break;
289 }
290 }
while (in <
last && out < end);
291
292
294 in -= len;
297
298
300 strm->next_out = out;
302 strm->avail_out = (unsigned)(out < end ?
303 257 + (end - out) : 257 - (out - end));
306 return;
307}
unsigned char FAR * window