1a79de952Smillert /* inffast.c -- fast decoding
236f395ceStb * Copyright (C) 1995-2017 Mark Adler
335534e26Sdownsj * For conditions of distribution and use, see copyright notice in zlib.h
435534e26Sdownsj */
535534e26Sdownsj
635534e26Sdownsj #include "zutil.h"
735534e26Sdownsj #include "inftrees.h"
8a79de952Smillert #include "inflate.h"
935534e26Sdownsj #include "inffast.h"
1035534e26Sdownsj
1136f395ceStb #ifdef ASMINF
1236f395ceStb # pragma message("Assembler code may have bugs -- use at your own risk")
1386c6ced8Sderaadt #else
1435534e26Sdownsj
15a79de952Smillert /*
16a79de952Smillert Decode literal, length, and distance codes and write out the resulting
17a79de952Smillert literal and match bytes until either not enough input or output is
18a79de952Smillert available, an end-of-block is encountered, or a data error is encountered.
19a79de952Smillert When large enough input and output buffers are supplied to inflate(), for
20a79de952Smillert example, a 16K input buffer and a 64K output buffer, more than 95% of the
21a79de952Smillert inflate execution time is spent in this routine.
22a79de952Smillert
23a79de952Smillert Entry assumptions:
24a79de952Smillert
25a79de952Smillert state->mode == LEN
26a79de952Smillert strm->avail_in >= 6
27a79de952Smillert strm->avail_out >= 258
28a79de952Smillert start >= strm->avail_out
29a79de952Smillert state->bits < 8
30a79de952Smillert
31a79de952Smillert On return, state->mode is one of:
32a79de952Smillert
33a79de952Smillert LEN -- ran out of enough output space or enough available input
34a79de952Smillert TYPE -- reached end of block code, inflate() to interpret next block
35a79de952Smillert BAD -- error in block data
36a79de952Smillert
37a79de952Smillert Notes:
38a79de952Smillert
39a79de952Smillert - The maximum input bits used by a length/distance pair is 15 bits for the
40a79de952Smillert length code, 5 bits for the length extra, 15 bits for the distance code,
41a79de952Smillert and 13 bits for the distance extra. This totals 48 bits, or six bytes.
42a79de952Smillert Therefore if strm->avail_in >= 6, then there is enough input to avoid
43a79de952Smillert checking for available input while decoding.
44a79de952Smillert
45a79de952Smillert - The maximum bytes that a single length/distance pair can output is 258
46a79de952Smillert bytes, which is the maximum length that can be coded. inflate_fast()
47a79de952Smillert requires strm->avail_out >= 258 for each loop to avoid checking for
48a79de952Smillert output space.
49a79de952Smillert */
inflate_fast(z_streamp strm,unsigned start)50cfac609cStb void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
51a79de952Smillert struct inflate_state FAR *state;
52efa1b761Sjca z_const unsigned char FAR *in; /* local strm->next_in */
5336f395ceStb z_const unsigned char FAR *last; /* have enough input while in < last */
54a79de952Smillert unsigned char FAR *out; /* local strm->next_out */
55a79de952Smillert unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
56a79de952Smillert unsigned char FAR *end; /* while out < end, enough space available */
57d76b9bfaSmillert #ifdef INFLATE_STRICT
58d76b9bfaSmillert unsigned dmax; /* maximum distance from zlib header */
59d76b9bfaSmillert #endif
60a79de952Smillert unsigned wsize; /* window size or zero if not using window */
61a79de952Smillert unsigned whave; /* valid bytes in the window */
6236f395ceStb unsigned wnext; /* window write index */
63a79de952Smillert unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
64a79de952Smillert unsigned long hold; /* local strm->hold */
65a79de952Smillert unsigned bits; /* local strm->bits */
66a79de952Smillert code const FAR *lcode; /* local strm->lencode */
67a79de952Smillert code const FAR *dcode; /* local strm->distcode */
68a79de952Smillert unsigned lmask; /* mask for first level of length codes */
69a79de952Smillert unsigned dmask; /* mask for first level of distance codes */
70a6530658Stb code const *here; /* retrieved table entry */
71a79de952Smillert unsigned op; /* code bits, operation, extra bits, or */
72a79de952Smillert /* window position, window bytes to copy */
73a79de952Smillert unsigned len; /* match length, unused bytes */
74a79de952Smillert unsigned dist; /* match distance */
75a79de952Smillert unsigned char FAR *from; /* where to copy match from */
76a79de952Smillert
77a79de952Smillert /* copy state to local variables */
78a79de952Smillert state = (struct inflate_state FAR *)strm->state;
7936f395ceStb in = strm->next_in;
80a79de952Smillert last = in + (strm->avail_in - 5);
8136f395ceStb out = strm->next_out;
82a79de952Smillert beg = out - (start - strm->avail_out);
83a79de952Smillert end = out + (strm->avail_out - 257);
84d76b9bfaSmillert #ifdef INFLATE_STRICT
85d76b9bfaSmillert dmax = state->dmax;
86d76b9bfaSmillert #endif
87a79de952Smillert wsize = state->wsize;
88a79de952Smillert whave = state->whave;
8936f395ceStb wnext = state->wnext;
90a79de952Smillert window = state->window;
91a79de952Smillert hold = state->hold;
92a79de952Smillert bits = state->bits;
93a79de952Smillert lcode = state->lencode;
94a79de952Smillert dcode = state->distcode;
95a79de952Smillert lmask = (1U << state->lenbits) - 1;
96a79de952Smillert dmask = (1U << state->distbits) - 1;
97a79de952Smillert
98a79de952Smillert /* decode literals and length/distances until end-of-block or not enough
99a79de952Smillert input data or output space */
100a79de952Smillert do {
101a79de952Smillert if (bits < 15) {
10236f395ceStb hold += (unsigned long)(*in++) << bits;
103a79de952Smillert bits += 8;
10436f395ceStb hold += (unsigned long)(*in++) << bits;
105a79de952Smillert bits += 8;
10635534e26Sdownsj }
107a6530658Stb here = lcode + (hold & lmask);
108a79de952Smillert dolen:
109a6530658Stb op = (unsigned)(here->bits);
110a79de952Smillert hold >>= op;
111a79de952Smillert bits -= op;
112a6530658Stb op = (unsigned)(here->op);
113a79de952Smillert if (op == 0) { /* literal */
114a6530658Stb Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
115a79de952Smillert "inflate: literal '%c'\n" :
116a6530658Stb "inflate: literal 0x%02x\n", here->val));
117a6530658Stb *out++ = (unsigned char)(here->val);
118a79de952Smillert }
119a79de952Smillert else if (op & 16) { /* length base */
120a6530658Stb len = (unsigned)(here->val);
121a79de952Smillert op &= 15; /* number of extra bits */
122a79de952Smillert if (op) {
123a79de952Smillert if (bits < op) {
12436f395ceStb hold += (unsigned long)(*in++) << bits;
125a79de952Smillert bits += 8;
126a79de952Smillert }
127a79de952Smillert len += (unsigned)hold & ((1U << op) - 1);
128a79de952Smillert hold >>= op;
129a79de952Smillert bits -= op;
130a79de952Smillert }
131a79de952Smillert Tracevv((stderr, "inflate: length %u\n", len));
132a79de952Smillert if (bits < 15) {
13336f395ceStb hold += (unsigned long)(*in++) << bits;
134a79de952Smillert bits += 8;
13536f395ceStb hold += (unsigned long)(*in++) << bits;
136a79de952Smillert bits += 8;
137a79de952Smillert }
138a6530658Stb here = dcode + (hold & dmask);
139a79de952Smillert dodist:
140a6530658Stb op = (unsigned)(here->bits);
141a79de952Smillert hold >>= op;
142a79de952Smillert bits -= op;
143a6530658Stb op = (unsigned)(here->op);
144a79de952Smillert if (op & 16) { /* distance base */
145a6530658Stb dist = (unsigned)(here->val);
146a79de952Smillert op &= 15; /* number of extra bits */
147a79de952Smillert if (bits < op) {
14836f395ceStb hold += (unsigned long)(*in++) << bits;
149a79de952Smillert bits += 8;
150a79de952Smillert if (bits < op) {
15136f395ceStb hold += (unsigned long)(*in++) << bits;
152a79de952Smillert bits += 8;
153a79de952Smillert }
154a79de952Smillert }
155a79de952Smillert dist += (unsigned)hold & ((1U << op) - 1);
156d76b9bfaSmillert #ifdef INFLATE_STRICT
157d76b9bfaSmillert if (dist > dmax) {
158*fb9b0152Stb strm->msg = (z_const char *)"invalid distance too far back";
159d76b9bfaSmillert state->mode = BAD;
160d76b9bfaSmillert break;
161d76b9bfaSmillert }
162d76b9bfaSmillert #endif
163a79de952Smillert hold >>= op;
164a79de952Smillert bits -= op;
165a79de952Smillert Tracevv((stderr, "inflate: distance %u\n", dist));
166a79de952Smillert op = (unsigned)(out - beg); /* max distance in output */
167a79de952Smillert if (dist > op) { /* see if copy from window */
168a79de952Smillert op = dist - op; /* distance back in window */
169a79de952Smillert if (op > whave) {
17036f395ceStb if (state->sane) {
1710ede0c43Smillert #ifdef SMALL
172*fb9b0152Stb strm->msg = (z_const char *)"error";
1730ede0c43Smillert #else
17436f395ceStb strm->msg =
175*fb9b0152Stb (z_const char *)"invalid distance too far back";
1760ede0c43Smillert #endif
177a79de952Smillert state->mode = BAD;
178a79de952Smillert break;
179a79de952Smillert }
18036f395ceStb #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
18136f395ceStb if (len <= op - whave) {
18236f395ceStb do {
18336f395ceStb *out++ = 0;
18436f395ceStb } while (--len);
18536f395ceStb continue;
18636f395ceStb }
18736f395ceStb len -= op - whave;
18836f395ceStb do {
18936f395ceStb *out++ = 0;
19036f395ceStb } while (--op > whave);
19136f395ceStb if (op == 0) {
19236f395ceStb from = out - dist;
19336f395ceStb do {
19436f395ceStb *out++ = *from++;
19536f395ceStb } while (--len);
19636f395ceStb continue;
19736f395ceStb }
19836f395ceStb #endif
19936f395ceStb }
20036f395ceStb from = window;
20136f395ceStb if (wnext == 0) { /* very common case */
202a79de952Smillert from += wsize - op;
203a79de952Smillert if (op < len) { /* some from window */
204a79de952Smillert len -= op;
205a79de952Smillert do {
20636f395ceStb *out++ = *from++;
207a79de952Smillert } while (--op);
208a79de952Smillert from = out - dist; /* rest from output */
209a79de952Smillert }
210a79de952Smillert }
21136f395ceStb else if (wnext < op) { /* wrap around window */
21236f395ceStb from += wsize + wnext - op;
21336f395ceStb op -= wnext;
214a79de952Smillert if (op < len) { /* some from end of window */
215a79de952Smillert len -= op;
216a79de952Smillert do {
21736f395ceStb *out++ = *from++;
218a79de952Smillert } while (--op);
21936f395ceStb from = window;
22036f395ceStb if (wnext < len) { /* some from start of window */
22136f395ceStb op = wnext;
222a79de952Smillert len -= op;
223a79de952Smillert do {
22436f395ceStb *out++ = *from++;
225a79de952Smillert } while (--op);
226a79de952Smillert from = out - dist; /* rest from output */
227a79de952Smillert }
228a79de952Smillert }
229a79de952Smillert }
230a79de952Smillert else { /* contiguous in window */
23136f395ceStb from += wnext - op;
232a79de952Smillert if (op < len) { /* some from window */
233a79de952Smillert len -= op;
234a79de952Smillert do {
23536f395ceStb *out++ = *from++;
236a79de952Smillert } while (--op);
237a79de952Smillert from = out - dist; /* rest from output */
238a79de952Smillert }
239a79de952Smillert }
240a79de952Smillert while (len > 2) {
24136f395ceStb *out++ = *from++;
24236f395ceStb *out++ = *from++;
24336f395ceStb *out++ = *from++;
244a79de952Smillert len -= 3;
245a79de952Smillert }
246a79de952Smillert if (len) {
24736f395ceStb *out++ = *from++;
248a79de952Smillert if (len > 1)
24936f395ceStb *out++ = *from++;
250a79de952Smillert }
251a79de952Smillert }
252a79de952Smillert else {
253a79de952Smillert from = out - dist; /* copy direct from output */
254a79de952Smillert do { /* minimum length is three */
25536f395ceStb *out++ = *from++;
25636f395ceStb *out++ = *from++;
25736f395ceStb *out++ = *from++;
258a79de952Smillert len -= 3;
259a79de952Smillert } while (len > 2);
260a79de952Smillert if (len) {
26136f395ceStb *out++ = *from++;
262a79de952Smillert if (len > 1)
26336f395ceStb *out++ = *from++;
264a79de952Smillert }
265a79de952Smillert }
266a79de952Smillert }
267a79de952Smillert else if ((op & 64) == 0) { /* 2nd level distance code */
268a6530658Stb here = dcode + here->val + (hold & ((1U << op) - 1));
269a79de952Smillert goto dodist;
270a79de952Smillert }
271a79de952Smillert else {
2720ede0c43Smillert #ifdef SMALL
273*fb9b0152Stb strm->msg = (z_const char *)"error";
2740ede0c43Smillert #else
275*fb9b0152Stb strm->msg = (z_const char *)"invalid distance code";
2760ede0c43Smillert #endif
277a79de952Smillert state->mode = BAD;
278a79de952Smillert break;
279a79de952Smillert }
280a79de952Smillert }
281a79de952Smillert else if ((op & 64) == 0) { /* 2nd level length code */
282a6530658Stb here = lcode + here->val + (hold & ((1U << op) - 1));
283a79de952Smillert goto dolen;
284a79de952Smillert }
285a79de952Smillert else if (op & 32) { /* end-of-block */
286a79de952Smillert Tracevv((stderr, "inflate: end of block\n"));
287a79de952Smillert state->mode = TYPE;
288a79de952Smillert break;
289a79de952Smillert }
290a79de952Smillert else {
2910ede0c43Smillert #ifdef SMALL
292*fb9b0152Stb strm->msg = (z_const char *)"error";
2930ede0c43Smillert #else
294*fb9b0152Stb strm->msg = (z_const char *)"invalid literal/length code";
2950ede0c43Smillert #endif
296a79de952Smillert state->mode = BAD;
297a79de952Smillert break;
298a79de952Smillert }
299a79de952Smillert } while (in < last && out < end);
300a79de952Smillert
301a79de952Smillert /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
302a79de952Smillert len = bits >> 3;
303a79de952Smillert in -= len;
304a79de952Smillert bits -= len << 3;
305a79de952Smillert hold &= (1U << bits) - 1;
306a79de952Smillert
307a79de952Smillert /* update state and return */
30836f395ceStb strm->next_in = in;
30936f395ceStb strm->next_out = out;
310a79de952Smillert strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
311a79de952Smillert strm->avail_out = (unsigned)(out < end ?
312a79de952Smillert 257 + (end - out) : 257 - (out - end));
313a79de952Smillert state->hold = hold;
314a79de952Smillert state->bits = bits;
315a79de952Smillert return;
316a79de952Smillert }
317a79de952Smillert
318a79de952Smillert /*
319a79de952Smillert inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
320a79de952Smillert - Using bit fields for code structure
321a79de952Smillert - Different op definition to avoid & for extra bits (do & for table bits)
32236f395ceStb - Three separate decoding do-loops for direct, window, and wnext == 0
323a79de952Smillert - Special case for distance > 1 copies to do overlapped load and store copy
324a79de952Smillert - Explicit branch predictions (based on measured branch probabilities)
325a79de952Smillert - Deferring match copy and interspersed it with decoding subsequent codes
326a79de952Smillert - Swapping literal/length else
327a79de952Smillert - Swapping window/direct else
328a79de952Smillert - Larger unrolled copy loops (three is about right)
329a79de952Smillert - Moving len -= 3 statement into middle of loop
330a79de952Smillert */
331a79de952Smillert
332a79de952Smillert #endif /* !ASMINF */
333