1
2
3
4
5
6#include <linux/zutil.h>
7#include "inftrees.h"
8#include "inflate.h"
9#include "inffast.h"
10
11#ifndef ASMINF
12
13union uu {
14 unsigned short us;
15 unsigned char b[2];
16};
17
18
19static inline unsigned short
20get_unaligned16(const unsigned short *p)
21{
22 union uu mm;
23 unsigned char *b = (unsigned char *)p;
24
25 mm.b[0] = b[0];
26 mm.b[1] = b[1];
27 return mm.us;
28}
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67void inflate_fast(z_streamp strm, unsigned start)
68{
69 struct inflate_state *state;
70 const unsigned char *in;
71 const unsigned char *last;
72 unsigned char *out;
73 unsigned char *beg;
74 unsigned char *end;
75#ifdef INFLATE_STRICT
76 unsigned dmax;
77#endif
78 unsigned wsize;
79 unsigned whave;
80 unsigned write;
81 unsigned char *window;
82 unsigned long hold;
83 unsigned bits;
84 code const *lcode;
85 code const *dcode;
86 unsigned lmask;
87 unsigned dmask;
88 code this;
89 unsigned op;
90
91 unsigned len;
92 unsigned dist;
93 unsigned char *from;
94
95
96 state = (struct inflate_state *)strm->state;
97 in = strm->next_in;
98 last = in + (strm->avail_in - 5);
99 out = strm->next_out;
100 beg = out - (start - strm->avail_out);
101 end = out + (strm->avail_out - 257);
102#ifdef INFLATE_STRICT
103 dmax = state->dmax;
104#endif
105 wsize = state->wsize;
106 whave = state->whave;
107 write = state->write;
108 window = state->window;
109 hold = state->hold;
110 bits = state->bits;
111 lcode = state->lencode;
112 dcode = state->distcode;
113 lmask = (1U << state->lenbits) - 1;
114 dmask = (1U << state->distbits) - 1;
115
116
117
118 do {
119 if (bits < 15) {
120 hold += (unsigned long)(*in++) << bits;
121 bits += 8;
122 hold += (unsigned long)(*in++) << bits;
123 bits += 8;
124 }
125 this = lcode[hold & lmask];
126 dolen:
127 op = (unsigned)(this.bits);
128 hold >>= op;
129 bits -= op;
130 op = (unsigned)(this.op);
131 if (op == 0) {
132 *out++ = (unsigned char)(this.val);
133 }
134 else if (op & 16) {
135 len = (unsigned)(this.val);
136 op &= 15;
137 if (op) {
138 if (bits < op) {
139 hold += (unsigned long)(*in++) << bits;
140 bits += 8;
141 }
142 len += (unsigned)hold & ((1U << op) - 1);
143 hold >>= op;
144 bits -= op;
145 }
146 if (bits < 15) {
147 hold += (unsigned long)(*in++) << bits;
148 bits += 8;
149 hold += (unsigned long)(*in++) << bits;
150 bits += 8;
151 }
152 this = dcode[hold & dmask];
153 dodist:
154 op = (unsigned)(this.bits);
155 hold >>= op;
156 bits -= op;
157 op = (unsigned)(this.op);
158 if (op & 16) {
159 dist = (unsigned)(this.val);
160 op &= 15;
161 if (bits < op) {
162 hold += (unsigned long)(*in++) << bits;
163 bits += 8;
164 if (bits < op) {
165 hold += (unsigned long)(*in++) << bits;
166 bits += 8;
167 }
168 }
169 dist += (unsigned)hold & ((1U << op) - 1);
170#ifdef INFLATE_STRICT
171 if (dist > dmax) {
172 strm->msg = (char *)"invalid distance too far back";
173 state->mode = BAD;
174 break;
175 }
176#endif
177 hold >>= op;
178 bits -= op;
179 op = (unsigned)(out - beg);
180 if (dist > op) {
181 op = dist - op;
182 if (op > whave) {
183 strm->msg = (char *)"invalid distance too far back";
184 state->mode = BAD;
185 break;
186 }
187 from = window;
188 if (write == 0) {
189 from += wsize - op;
190 if (op < len) {
191 len -= op;
192 do {
193 *out++ = *from++;
194 } while (--op);
195 from = out - dist;
196 }
197 }
198 else if (write < op) {
199 from += wsize + write - op;
200 op -= write;
201 if (op < len) {
202 len -= op;
203 do {
204 *out++ = *from++;
205 } while (--op);
206 from = window;
207 if (write < len) {
208 op = write;
209 len -= op;
210 do {
211 *out++ = *from++;
212 } while (--op);
213 from = out - dist;
214 }
215 }
216 }
217 else {
218 from += write - op;
219 if (op < len) {
220 len -= op;
221 do {
222 *out++ = *from++;
223 } while (--op);
224 from = out - dist;
225 }
226 }
227 while (len > 2) {
228 *out++ = *from++;
229 *out++ = *from++;
230 *out++ = *from++;
231 len -= 3;
232 }
233 if (len) {
234 *out++ = *from++;
235 if (len > 1)
236 *out++ = *from++;
237 }
238 }
239 else {
240 unsigned short *sout;
241 unsigned long loops;
242
243 from = out - dist;
244
245
246 if (!((long)(out - 1) & 1)) {
247 *out++ = *from++;
248 len--;
249 }
250 sout = (unsigned short *)(out);
251 if (dist > 2) {
252 unsigned short *sfrom;
253
254 sfrom = (unsigned short *)(from);
255 loops = len >> 1;
256 do {
257 if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
258 *sout++ = *sfrom++;
259 else
260 *sout++ = get_unaligned16(sfrom++);
261 } while (--loops);
262 out = (unsigned char *)sout;
263 from = (unsigned char *)sfrom;
264 } else {
265 unsigned short pat16;
266
267 pat16 = *(sout-1);
268 if (dist == 1) {
269 union uu mm;
270
271 mm.us = pat16;
272 mm.b[0] = mm.b[1];
273 pat16 = mm.us;
274 }
275 loops = len >> 1;
276 do
277 *sout++ = pat16;
278 while (--loops);
279 out = (unsigned char *)sout;
280 }
281 if (len & 1)
282 *out++ = *from++;
283 }
284 }
285 else if ((op & 64) == 0) {
286 this = dcode[this.val + (hold & ((1U << op) - 1))];
287 goto dodist;
288 }
289 else {
290 strm->msg = (char *)"invalid distance code";
291 state->mode = BAD;
292 break;
293 }
294 }
295 else if ((op & 64) == 0) {
296 this = lcode[this.val + (hold & ((1U << op) - 1))];
297 goto dolen;
298 }
299 else if (op & 32) {
300 state->mode = TYPE;
301 break;
302 }
303 else {
304 strm->msg = (char *)"invalid literal/length code";
305 state->mode = BAD;
306 break;
307 }
308 } while (in < last && out < end);
309
310
311 len = bits >> 3;
312 in -= len;
313 bits -= len << 3;
314 hold &= (1U << bits) - 1;
315
316
317 strm->next_in = in;
318 strm->next_out = out;
319 strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
320 strm->avail_out = (unsigned)(out < end ?
321 257 + (end - out) : 257 - (out - end));
322 state->hold = hold;
323 state->bits = bits;
324 return;
325}
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341#endif
342