1221b1638SMasahiro Yamada /* inffast.c -- fast decoding
2221b1638SMasahiro Yamada * Copyright (C) 1995-2017 Mark Adler
3221b1638SMasahiro Yamada * For conditions of distribution and use, see copyright notice in zlib.h
4221b1638SMasahiro Yamada */
5221b1638SMasahiro Yamada
6221b1638SMasahiro Yamada #include "zutil.h"
7221b1638SMasahiro Yamada #include "inftrees.h"
8221b1638SMasahiro Yamada #include "inflate.h"
9221b1638SMasahiro Yamada #include "inffast.h"
10221b1638SMasahiro Yamada
11221b1638SMasahiro Yamada #ifdef ASMINF
12221b1638SMasahiro Yamada # pragma message("Assembler code may have bugs -- use at your own risk")
13221b1638SMasahiro Yamada #else
14221b1638SMasahiro Yamada
15221b1638SMasahiro Yamada /*
16221b1638SMasahiro Yamada Decode literal, length, and distance codes and write out the resulting
17221b1638SMasahiro Yamada literal and match bytes until either not enough input or output is
18221b1638SMasahiro Yamada available, an end-of-block is encountered, or a data error is encountered.
19221b1638SMasahiro Yamada When large enough input and output buffers are supplied to inflate(), for
20221b1638SMasahiro Yamada example, a 16K input buffer and a 64K output buffer, more than 95% of the
21221b1638SMasahiro Yamada inflate execution time is spent in this routine.
22221b1638SMasahiro Yamada
23221b1638SMasahiro Yamada Entry assumptions:
24221b1638SMasahiro Yamada
25221b1638SMasahiro Yamada state->mode == LEN
26221b1638SMasahiro Yamada strm->avail_in >= 6
27221b1638SMasahiro Yamada strm->avail_out >= 258
28221b1638SMasahiro Yamada start >= strm->avail_out
29221b1638SMasahiro Yamada state->bits < 8
30221b1638SMasahiro Yamada
31221b1638SMasahiro Yamada On return, state->mode is one of:
32221b1638SMasahiro Yamada
33221b1638SMasahiro Yamada LEN -- ran out of enough output space or enough available input
34221b1638SMasahiro Yamada TYPE -- reached end of block code, inflate() to interpret next block
35221b1638SMasahiro Yamada BAD -- error in block data
36221b1638SMasahiro Yamada
37221b1638SMasahiro Yamada Notes:
38221b1638SMasahiro Yamada
39221b1638SMasahiro Yamada - The maximum input bits used by a length/distance pair is 15 bits for the
40221b1638SMasahiro Yamada length code, 5 bits for the length extra, 15 bits for the distance code,
41221b1638SMasahiro Yamada and 13 bits for the distance extra. This totals 48 bits, or six bytes.
42221b1638SMasahiro Yamada Therefore if strm->avail_in >= 6, then there is enough input to avoid
43221b1638SMasahiro Yamada checking for available input while decoding.
44221b1638SMasahiro Yamada
45221b1638SMasahiro Yamada - The maximum bytes that a single length/distance pair can output is 258
46221b1638SMasahiro Yamada bytes, which is the maximum length that can be coded. inflate_fast()
47221b1638SMasahiro Yamada requires strm->avail_out >= 258 for each loop to avoid checking for
48221b1638SMasahiro Yamada output space.
49221b1638SMasahiro Yamada */
inflate_fast(z_streamp strm,unsigned start)50fd39217aSManish Pandey void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
51221b1638SMasahiro Yamada struct inflate_state FAR *state;
52221b1638SMasahiro Yamada z_const unsigned char FAR *in; /* local strm->next_in */
53221b1638SMasahiro Yamada z_const unsigned char FAR *last; /* have enough input while in < last */
54221b1638SMasahiro Yamada unsigned char FAR *out; /* local strm->next_out */
55221b1638SMasahiro Yamada unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
56221b1638SMasahiro Yamada unsigned char FAR *end; /* while out < end, enough space available */
57221b1638SMasahiro Yamada #ifdef INFLATE_STRICT
58221b1638SMasahiro Yamada unsigned dmax; /* maximum distance from zlib header */
59221b1638SMasahiro Yamada #endif
60221b1638SMasahiro Yamada unsigned wsize; /* window size or zero if not using window */
61221b1638SMasahiro Yamada unsigned whave; /* valid bytes in the window */
62221b1638SMasahiro Yamada unsigned wnext; /* window write index */
63221b1638SMasahiro Yamada unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
64221b1638SMasahiro Yamada unsigned long hold; /* local strm->hold */
65221b1638SMasahiro Yamada unsigned bits; /* local strm->bits */
66221b1638SMasahiro Yamada code const FAR *lcode; /* local strm->lencode */
67221b1638SMasahiro Yamada code const FAR *dcode; /* local strm->distcode */
68221b1638SMasahiro Yamada unsigned lmask; /* mask for first level of length codes */
69221b1638SMasahiro Yamada unsigned dmask; /* mask for first level of distance codes */
70a194255dSDaniel Boulby code const *here; /* retrieved table entry */
71221b1638SMasahiro Yamada unsigned op; /* code bits, operation, extra bits, or */
72221b1638SMasahiro Yamada /* window position, window bytes to copy */
73221b1638SMasahiro Yamada unsigned len; /* match length, unused bytes */
74221b1638SMasahiro Yamada unsigned dist; /* match distance */
75221b1638SMasahiro Yamada unsigned char FAR *from; /* where to copy match from */
76221b1638SMasahiro Yamada
77221b1638SMasahiro Yamada /* copy state to local variables */
78221b1638SMasahiro Yamada state = (struct inflate_state FAR *)strm->state;
79221b1638SMasahiro Yamada in = strm->next_in;
80221b1638SMasahiro Yamada last = in + (strm->avail_in - 5);
81221b1638SMasahiro Yamada out = strm->next_out;
82221b1638SMasahiro Yamada beg = out - (start - strm->avail_out);
83221b1638SMasahiro Yamada end = out + (strm->avail_out - 257);
84221b1638SMasahiro Yamada #ifdef INFLATE_STRICT
85221b1638SMasahiro Yamada dmax = state->dmax;
86221b1638SMasahiro Yamada #endif
87221b1638SMasahiro Yamada wsize = state->wsize;
88221b1638SMasahiro Yamada whave = state->whave;
89221b1638SMasahiro Yamada wnext = state->wnext;
90221b1638SMasahiro Yamada window = state->window;
91221b1638SMasahiro Yamada hold = state->hold;
92221b1638SMasahiro Yamada bits = state->bits;
93221b1638SMasahiro Yamada lcode = state->lencode;
94221b1638SMasahiro Yamada dcode = state->distcode;
95221b1638SMasahiro Yamada lmask = (1U << state->lenbits) - 1;
96221b1638SMasahiro Yamada dmask = (1U << state->distbits) - 1;
97221b1638SMasahiro Yamada
98221b1638SMasahiro Yamada /* decode literals and length/distances until end-of-block or not enough
99221b1638SMasahiro Yamada input data or output space */
100221b1638SMasahiro Yamada do {
101221b1638SMasahiro Yamada if (bits < 15) {
102221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits;
103221b1638SMasahiro Yamada bits += 8;
104221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits;
105221b1638SMasahiro Yamada bits += 8;
106221b1638SMasahiro Yamada }
107a194255dSDaniel Boulby here = lcode + (hold & lmask);
108221b1638SMasahiro Yamada dolen:
109a194255dSDaniel Boulby op = (unsigned)(here->bits);
110221b1638SMasahiro Yamada hold >>= op;
111221b1638SMasahiro Yamada bits -= op;
112a194255dSDaniel Boulby op = (unsigned)(here->op);
113221b1638SMasahiro Yamada if (op == 0) { /* literal */
114a194255dSDaniel Boulby Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
115221b1638SMasahiro Yamada "inflate: literal '%c'\n" :
116a194255dSDaniel Boulby "inflate: literal 0x%02x\n", here->val));
117a194255dSDaniel Boulby *out++ = (unsigned char)(here->val);
118221b1638SMasahiro Yamada }
119221b1638SMasahiro Yamada else if (op & 16) { /* length base */
120a194255dSDaniel Boulby len = (unsigned)(here->val);
121221b1638SMasahiro Yamada op &= 15; /* number of extra bits */
122221b1638SMasahiro Yamada if (op) {
123221b1638SMasahiro Yamada if (bits < op) {
124221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits;
125221b1638SMasahiro Yamada bits += 8;
126221b1638SMasahiro Yamada }
127221b1638SMasahiro Yamada len += (unsigned)hold & ((1U << op) - 1);
128221b1638SMasahiro Yamada hold >>= op;
129221b1638SMasahiro Yamada bits -= op;
130221b1638SMasahiro Yamada }
131221b1638SMasahiro Yamada Tracevv((stderr, "inflate: length %u\n", len));
132221b1638SMasahiro Yamada if (bits < 15) {
133221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits;
134221b1638SMasahiro Yamada bits += 8;
135221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits;
136221b1638SMasahiro Yamada bits += 8;
137221b1638SMasahiro Yamada }
138a194255dSDaniel Boulby here = dcode + (hold & dmask);
139221b1638SMasahiro Yamada dodist:
140a194255dSDaniel Boulby op = (unsigned)(here->bits);
141221b1638SMasahiro Yamada hold >>= op;
142221b1638SMasahiro Yamada bits -= op;
143a194255dSDaniel Boulby op = (unsigned)(here->op);
144221b1638SMasahiro Yamada if (op & 16) { /* distance base */
145a194255dSDaniel Boulby dist = (unsigned)(here->val);
146221b1638SMasahiro Yamada op &= 15; /* number of extra bits */
147221b1638SMasahiro Yamada if (bits < op) {
148221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits;
149221b1638SMasahiro Yamada bits += 8;
150221b1638SMasahiro Yamada if (bits < op) {
151221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits;
152221b1638SMasahiro Yamada bits += 8;
153221b1638SMasahiro Yamada }
154221b1638SMasahiro Yamada }
155221b1638SMasahiro Yamada dist += (unsigned)hold & ((1U << op) - 1);
156221b1638SMasahiro Yamada #ifdef INFLATE_STRICT
157221b1638SMasahiro Yamada if (dist > dmax) {
158*a8c877cbSChris Kay strm->msg = (z_const char *)"invalid distance too far back";
159221b1638SMasahiro Yamada state->mode = BAD;
160221b1638SMasahiro Yamada break;
161221b1638SMasahiro Yamada }
162221b1638SMasahiro Yamada #endif
163221b1638SMasahiro Yamada hold >>= op;
164221b1638SMasahiro Yamada bits -= op;
165221b1638SMasahiro Yamada Tracevv((stderr, "inflate: distance %u\n", dist));
166221b1638SMasahiro Yamada op = (unsigned)(out - beg); /* max distance in output */
167221b1638SMasahiro Yamada if (dist > op) { /* see if copy from window */
168221b1638SMasahiro Yamada op = dist - op; /* distance back in window */
169221b1638SMasahiro Yamada if (op > whave) {
170221b1638SMasahiro Yamada if (state->sane) {
171221b1638SMasahiro Yamada strm->msg =
172*a8c877cbSChris Kay (z_const char *)"invalid distance too far back";
173221b1638SMasahiro Yamada state->mode = BAD;
174221b1638SMasahiro Yamada break;
175221b1638SMasahiro Yamada }
176221b1638SMasahiro Yamada #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
177221b1638SMasahiro Yamada if (len <= op - whave) {
178221b1638SMasahiro Yamada do {
179221b1638SMasahiro Yamada *out++ = 0;
180221b1638SMasahiro Yamada } while (--len);
181221b1638SMasahiro Yamada continue;
182221b1638SMasahiro Yamada }
183221b1638SMasahiro Yamada len -= op - whave;
184221b1638SMasahiro Yamada do {
185221b1638SMasahiro Yamada *out++ = 0;
186221b1638SMasahiro Yamada } while (--op > whave);
187221b1638SMasahiro Yamada if (op == 0) {
188221b1638SMasahiro Yamada from = out - dist;
189221b1638SMasahiro Yamada do {
190221b1638SMasahiro Yamada *out++ = *from++;
191221b1638SMasahiro Yamada } while (--len);
192221b1638SMasahiro Yamada continue;
193221b1638SMasahiro Yamada }
194221b1638SMasahiro Yamada #endif
195221b1638SMasahiro Yamada }
196221b1638SMasahiro Yamada from = window;
197221b1638SMasahiro Yamada if (wnext == 0) { /* very common case */
198221b1638SMasahiro Yamada from += wsize - op;
199221b1638SMasahiro Yamada if (op < len) { /* some from window */
200221b1638SMasahiro Yamada len -= op;
201221b1638SMasahiro Yamada do {
202221b1638SMasahiro Yamada *out++ = *from++;
203221b1638SMasahiro Yamada } while (--op);
204221b1638SMasahiro Yamada from = out - dist; /* rest from output */
205221b1638SMasahiro Yamada }
206221b1638SMasahiro Yamada }
207221b1638SMasahiro Yamada else if (wnext < op) { /* wrap around window */
208221b1638SMasahiro Yamada from += wsize + wnext - op;
209221b1638SMasahiro Yamada op -= wnext;
210221b1638SMasahiro Yamada if (op < len) { /* some from end of window */
211221b1638SMasahiro Yamada len -= op;
212221b1638SMasahiro Yamada do {
213221b1638SMasahiro Yamada *out++ = *from++;
214221b1638SMasahiro Yamada } while (--op);
215221b1638SMasahiro Yamada from = window;
216221b1638SMasahiro Yamada if (wnext < len) { /* some from start of window */
217221b1638SMasahiro Yamada op = wnext;
218221b1638SMasahiro Yamada len -= op;
219221b1638SMasahiro Yamada do {
220221b1638SMasahiro Yamada *out++ = *from++;
221221b1638SMasahiro Yamada } while (--op);
222221b1638SMasahiro Yamada from = out - dist; /* rest from output */
223221b1638SMasahiro Yamada }
224221b1638SMasahiro Yamada }
225221b1638SMasahiro Yamada }
226221b1638SMasahiro Yamada else { /* contiguous in window */
227221b1638SMasahiro Yamada from += wnext - op;
228221b1638SMasahiro Yamada if (op < len) { /* some from window */
229221b1638SMasahiro Yamada len -= op;
230221b1638SMasahiro Yamada do {
231221b1638SMasahiro Yamada *out++ = *from++;
232221b1638SMasahiro Yamada } while (--op);
233221b1638SMasahiro Yamada from = out - dist; /* rest from output */
234221b1638SMasahiro Yamada }
235221b1638SMasahiro Yamada }
236221b1638SMasahiro Yamada while (len > 2) {
237221b1638SMasahiro Yamada *out++ = *from++;
238221b1638SMasahiro Yamada *out++ = *from++;
239221b1638SMasahiro Yamada *out++ = *from++;
240221b1638SMasahiro Yamada len -= 3;
241221b1638SMasahiro Yamada }
242221b1638SMasahiro Yamada if (len) {
243221b1638SMasahiro Yamada *out++ = *from++;
244221b1638SMasahiro Yamada if (len > 1)
245221b1638SMasahiro Yamada *out++ = *from++;
246221b1638SMasahiro Yamada }
247221b1638SMasahiro Yamada }
248221b1638SMasahiro Yamada else {
249221b1638SMasahiro Yamada from = out - dist; /* copy direct from output */
250221b1638SMasahiro Yamada do { /* minimum length is three */
251221b1638SMasahiro Yamada *out++ = *from++;
252221b1638SMasahiro Yamada *out++ = *from++;
253221b1638SMasahiro Yamada *out++ = *from++;
254221b1638SMasahiro Yamada len -= 3;
255221b1638SMasahiro Yamada } while (len > 2);
256221b1638SMasahiro Yamada if (len) {
257221b1638SMasahiro Yamada *out++ = *from++;
258221b1638SMasahiro Yamada if (len > 1)
259221b1638SMasahiro Yamada *out++ = *from++;
260221b1638SMasahiro Yamada }
261221b1638SMasahiro Yamada }
262221b1638SMasahiro Yamada }
263221b1638SMasahiro Yamada else if ((op & 64) == 0) { /* 2nd level distance code */
264a194255dSDaniel Boulby here = dcode + here->val + (hold & ((1U << op) - 1));
265221b1638SMasahiro Yamada goto dodist;
266221b1638SMasahiro Yamada }
267221b1638SMasahiro Yamada else {
268*a8c877cbSChris Kay strm->msg = (z_const char *)"invalid distance code";
269221b1638SMasahiro Yamada state->mode = BAD;
270221b1638SMasahiro Yamada break;
271221b1638SMasahiro Yamada }
272221b1638SMasahiro Yamada }
273221b1638SMasahiro Yamada else if ((op & 64) == 0) { /* 2nd level length code */
274a194255dSDaniel Boulby here = lcode + here->val + (hold & ((1U << op) - 1));
275221b1638SMasahiro Yamada goto dolen;
276221b1638SMasahiro Yamada }
277221b1638SMasahiro Yamada else if (op & 32) { /* end-of-block */
278221b1638SMasahiro Yamada Tracevv((stderr, "inflate: end of block\n"));
279221b1638SMasahiro Yamada state->mode = TYPE;
280221b1638SMasahiro Yamada break;
281221b1638SMasahiro Yamada }
282221b1638SMasahiro Yamada else {
283*a8c877cbSChris Kay strm->msg = (z_const char *)"invalid literal/length code";
284221b1638SMasahiro Yamada state->mode = BAD;
285221b1638SMasahiro Yamada break;
286221b1638SMasahiro Yamada }
287221b1638SMasahiro Yamada } while (in < last && out < end);
288221b1638SMasahiro Yamada
289221b1638SMasahiro Yamada /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
290221b1638SMasahiro Yamada len = bits >> 3;
291221b1638SMasahiro Yamada in -= len;
292221b1638SMasahiro Yamada bits -= len << 3;
293221b1638SMasahiro Yamada hold &= (1U << bits) - 1;
294221b1638SMasahiro Yamada
295221b1638SMasahiro Yamada /* update state and return */
296221b1638SMasahiro Yamada strm->next_in = in;
297221b1638SMasahiro Yamada strm->next_out = out;
298221b1638SMasahiro Yamada strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
299221b1638SMasahiro Yamada strm->avail_out = (unsigned)(out < end ?
300221b1638SMasahiro Yamada 257 + (end - out) : 257 - (out - end));
301221b1638SMasahiro Yamada state->hold = hold;
302221b1638SMasahiro Yamada state->bits = bits;
303221b1638SMasahiro Yamada return;
304221b1638SMasahiro Yamada }
305221b1638SMasahiro Yamada
306221b1638SMasahiro Yamada /*
307221b1638SMasahiro Yamada inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
308221b1638SMasahiro Yamada - Using bit fields for code structure
309221b1638SMasahiro Yamada - Different op definition to avoid & for extra bits (do & for table bits)
310221b1638SMasahiro Yamada - Three separate decoding do-loops for direct, window, and wnext == 0
311221b1638SMasahiro Yamada - Special case for distance > 1 copies to do overlapped load and store copy
312221b1638SMasahiro Yamada - Explicit branch predictions (based on measured branch probabilities)
313221b1638SMasahiro Yamada - Deferring match copy and interspersed it with decoding subsequent codes
314221b1638SMasahiro Yamada - Swapping literal/length else
315221b1638SMasahiro Yamada - Swapping window/direct else
316221b1638SMasahiro Yamada - Larger unrolled copy loops (three is about right)
317221b1638SMasahiro Yamada - Moving len -= 3 statement into middle of loop
318221b1638SMasahiro Yamada */
319221b1638SMasahiro Yamada
320221b1638SMasahiro Yamada #endif /* !ASMINF */
321