50 {
52 z_const unsigned char FAR *in;
53 z_const
unsigned char FAR *
last;
54 unsigned char FAR *out;
55 unsigned char FAR *beg;
56 unsigned char FAR *end;
57#ifdef INFLATE_STRICT
59#endif
66 code const FAR *lcode;
67 code const FAR *dcode;
68 unsigned lmask;
69 unsigned dmask;
71 unsigned op;
72
73 unsigned len;
74 unsigned dist;
75 unsigned char FAR *from;
76
77
82 beg = out - (start -
strm->avail_out);
83 end = out + (
strm->avail_out - 257);
84#ifdef INFLATE_STRICT
86#endif
93 lcode = state->lencode;
94 dcode = state->distcode;
95 lmask = (1U << state->lenbits) - 1;
96 dmask = (1U << state->distbits) - 1;
97
98
99
100 do {
102 hold += (
unsigned long)(*in++) <<
bits;
104 hold += (
unsigned long)(*in++) <<
bits;
106 }
107 here = lcode + (
hold & lmask);
108 dolen:
109 op = (unsigned)(here->bits);
112 op = (unsigned)(here->op);
113 if (op == 0) {
114 Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
115 "inflate: literal '%c'\n" :
116 "inflate: literal 0x%02x\n", here->val));
117 *out++ = (unsigned char)(here->val);
118 }
119 else if (op & 16) {
120 len = (unsigned)(here->val);
121 op &= 15;
122 if (op) {
124 hold += (
unsigned long)(*in++) <<
bits;
126 }
127 len += (unsigned)
hold & ((1U << op) - 1);
130 }
131 Tracevv((stderr,
"inflate: length %u\n", len));
133 hold += (
unsigned long)(*in++) <<
bits;
135 hold += (
unsigned long)(*in++) <<
bits;
137 }
138 here = dcode + (
hold & dmask);
139 dodist:
140 op = (unsigned)(here->bits);
143 op = (unsigned)(here->op);
144 if (op & 16) {
145 dist = (unsigned)(here->val);
146 op &= 15;
148 hold += (
unsigned long)(*in++) <<
bits;
151 hold += (
unsigned long)(*in++) <<
bits;
153 }
154 }
155 dist += (unsigned)
hold & ((1U << op) - 1);
156#ifdef INFLATE_STRICT
158 strm->msg = (
char *)
"invalid distance too far back";
160 break;
161 }
162#endif
165 Tracevv((stderr,
"inflate: distance %u\n", dist));
166 op = (unsigned)(out - beg);
167 if (dist > op) {
168 op = dist - op;
170 if (state->sane) {
172 (char *)"invalid distance too far back";
174 break;
175 }
176#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
177 if (len <= op -
whave) {
178 do {
179 *out++ = 0;
180 } while (--len);
181 continue;
182 }
184 do {
185 *out++ = 0;
186 }
while (--op >
whave);
187 if (op == 0) {
188 from = out - dist;
189 do {
190 *out++ = *from++;
191 } while (--len);
192 continue;
193 }
194#endif
195 }
199 if (op < len) {
200 len -= op;
201 do {
202 *out++ = *from++;
203 } while (--op);
204 from = out - dist;
205 }
206 }
207 else if (
wnext < op) {
210 if (op < len) {
211 len -= op;
212 do {
213 *out++ = *from++;
214 } while (--op);
218 len -= op;
219 do {
220 *out++ = *from++;
221 } while (--op);
222 from = out - dist;
223 }
224 }
225 }
226 else {
228 if (op < len) {
229 len -= op;
230 do {
231 *out++ = *from++;
232 } while (--op);
233 from = out - dist;
234 }
235 }
236 while (len > 2) {
237 *out++ = *from++;
238 *out++ = *from++;
239 *out++ = *from++;
240 len -= 3;
241 }
242 if (len) {
243 *out++ = *from++;
244 if (len > 1)
245 *out++ = *from++;
246 }
247 }
248 else {
249 from = out - dist;
250 do {
251 *out++ = *from++;
252 *out++ = *from++;
253 *out++ = *from++;
254 len -= 3;
255 } while (len > 2);
256 if (len) {
257 *out++ = *from++;
258 if (len > 1)
259 *out++ = *from++;
260 }
261 }
262 }
263 else if ((op & 64) == 0) {
264 here = dcode + here->val + (
hold & ((1U << op) - 1));
265 goto dodist;
266 }
267 else {
268 strm->msg = (
char *)
"invalid distance code";
270 break;
271 }
272 }
273 else if ((op & 64) == 0) {
274 here = lcode + here->val + (
hold & ((1U << op) - 1));
275 goto dolen;
276 }
277 else if (op & 32) {
278 Tracevv((stderr,
"inflate: end of block\n"));
280 break;
281 }
282 else {
283 strm->msg = (
char *)
"invalid literal/length code";
285 break;
286 }
287 }
while (in <
last && out < end);
288
289
291 in -= len;
294
295
297 strm->next_out = out;
299 strm->avail_out = (unsigned)(out < end ?
300 257 + (end - out) : 257 - (out - end));
303 return;
304}
unsigned char FAR * window