File Coverage

inffast.c
Criterion Covered Total %
statement 105 146 71.9
branch 42 70 60.0
condition n/a
subroutine n/a
pod n/a
total 147 216 68.0


line stmt bran cond sub pod time code
1             /* inffast.c -- fast decoding
2             * Copyright (C) 1995-2026 Mark Adler
3             * For conditions of distribution and use, see copyright notice in zlib.h
4             */
5              
6             #include "zutil.h"
7             #include "inftrees.h"
8             #include "inflate.h"
9             #include "inffast.h"
10              
11             #ifdef ASMINF
12             # pragma message("Assembler code may have bugs -- use at your own risk")
13             #else
14              
15             /*
16             Decode literal, length, and distance codes and write out the resulting
17             literal and match bytes until either not enough input or output is
18             available, an end-of-block is encountered, or a data error is encountered.
19             When large enough input and output buffers are supplied to inflate(), for
20             example, a 16K input buffer and a 64K output buffer, more than 95% of the
21             inflate execution time is spent in this routine.
22              
23             Entry assumptions:
24              
25             state->mode == LEN
26             strm->avail_in >= 6
27             strm->avail_out >= 258
28             start >= strm->avail_out
29             state->bits < 8
30              
31             On return, state->mode is one of:
32              
33             LEN -- ran out of enough output space or enough available input
34             TYPE -- reached end of block code, inflate() to interpret next block
35             BAD -- error in block data
36              
37             Notes:
38              
39             - The maximum input bits used by a length/distance pair is 15 bits for the
40             length code, 5 bits for the length extra, 15 bits for the distance code,
41             and 13 bits for the distance extra. This totals 48 bits, or six bytes.
42             Therefore if strm->avail_in >= 6, then there is enough input to avoid
43             checking for available input while decoding.
44              
45             - The maximum bytes that a single length/distance pair can output is 258
46             bytes, which is the maximum length that can be coded. inflate_fast()
47             requires strm->avail_out >= 258 for each loop to avoid checking for
48             output space.
49             */
50 125           void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
51             struct inflate_state FAR *state;
52             z_const unsigned char FAR *in; /* local strm->next_in */
53             z_const unsigned char FAR *last; /* have enough input while in < last */
54             unsigned char FAR *out; /* local strm->next_out */
55             unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
56             unsigned char FAR *end; /* while out < end, enough space available */
57             #ifdef INFLATE_STRICT
58             unsigned dmax; /* maximum distance from zlib header */
59             #endif
60             unsigned wsize; /* window size or zero if not using window */
61             unsigned whave; /* valid bytes in the window */
62             unsigned wnext; /* window write index */
63             unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
64             unsigned long hold; /* local strm->hold */
65             unsigned bits; /* local strm->bits */
66             code const FAR *lcode; /* local strm->lencode */
67             code const FAR *dcode; /* local strm->distcode */
68             unsigned lmask; /* mask for first level of length codes */
69             unsigned dmask; /* mask for first level of distance codes */
70             code const *here; /* retrieved table entry */
71             unsigned op; /* code bits, operation, extra bits, or */
72             /* window position, window bytes to copy */
73             unsigned len; /* match length, unused bytes */
74             unsigned dist; /* match distance */
75             unsigned char FAR *from; /* where to copy match from */
76              
77             /* copy state to local variables */
78 125           state = (struct inflate_state FAR *)strm->state;
79 125           in = strm->next_in;
80 125           last = in + (strm->avail_in - 5);
81 125           out = strm->next_out;
82 125           beg = out - (start - strm->avail_out);
83 125           end = out + (strm->avail_out - 257);
84             #ifdef INFLATE_STRICT
85             dmax = state->dmax;
86             #endif
87 125           wsize = state->wsize;
88 125           whave = state->whave;
89 125           wnext = state->wnext;
90 125           window = state->window;
91 125           hold = state->hold;
92 125           bits = state->bits;
93 125           lcode = state->lencode;
94 125           dcode = state->distcode;
95 125           lmask = (1U << state->lenbits) - 1;
96 125           dmask = (1U << state->distbits) - 1;
97              
98             /* decode literals and length/distances until end-of-block or not enough
99             input data or output space */
100             do {
101 1807 100         if (bits < 15) {
102 617           hold += (unsigned long)(*in++) << bits;
103 617           bits += 8;
104 617           hold += (unsigned long)(*in++) << bits;
105 617           bits += 8;
106             }
107 1807           here = lcode + (hold & lmask);
108 1807           dolen:
109 1807           op = (unsigned)(here->bits);
110 1807           hold >>= op;
111 1807           bits -= op;
112 1807           op = (unsigned)(here->op);
113 1807 100         if (op == 0) { /* literal */
114             Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
115             "inflate: literal '%c'\n" :
116             "inflate: literal 0x%02x\n", here->val));
117 280           *out++ = (unsigned char)(here->val);
118             }
119 1527 100         else if (op & 16) { /* length base */
120 1517           len = (unsigned)(here->val);
121 1517           op &= 15; /* number of extra bits */
122 1517 100         if (op) {
123 10 50         if (bits < op) {
124 0           hold += (unsigned long)(*in++) << bits;
125 0           bits += 8;
126             }
127 10           len += (unsigned)hold & ((1U << op) - 1);
128 10           hold >>= op;
129 10           bits -= op;
130             }
131             Tracevv((stderr, "inflate: length %u\n", len));
132 1517 100         if (bits < 15) {
133 83           hold += (unsigned long)(*in++) << bits;
134 83           bits += 8;
135 83           hold += (unsigned long)(*in++) << bits;
136 83           bits += 8;
137             }
138 1517           here = dcode + (hold & dmask);
139 1517           dodist:
140 1517           op = (unsigned)(here->bits);
141 1517           hold >>= op;
142 1517           bits -= op;
143 1517           op = (unsigned)(here->op);
144 1517 50         if (op & 16) { /* distance base */
145 1517           dist = (unsigned)(here->val);
146 1517           op &= 15; /* number of extra bits */
147 1517 50         if (bits < op) {
148 0           hold += (unsigned long)(*in++) << bits;
149 0           bits += 8;
150 0 0         if (bits < op) {
151 0           hold += (unsigned long)(*in++) << bits;
152 0           bits += 8;
153             }
154             }
155 1517           dist += (unsigned)hold & ((1U << op) - 1);
156             #ifdef INFLATE_STRICT
157             if (dist > dmax) {
158             strm->msg = (z_const char *)
159             "invalid distance too far back";
160             state->mode = BAD;
161             break;
162             }
163             #endif
164 1517           hold >>= op;
165 1517           bits -= op;
166             Tracevv((stderr, "inflate: distance %u\n", dist));
167 1517           op = (unsigned)(out - beg); /* max distance in output */
168 1517 100         if (dist > op) { /* see if copy from window */
169 16           op = dist - op; /* distance back in window */
170 16 50         if (op > whave) {
171 0 0         if (state->sane) {
172 0           strm->msg = (z_const char *)
173             "invalid distance too far back";
174 0           state->mode = BAD;
175 0           break;
176             }
177             #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
178             if (len <= op - whave) {
179             do {
180             *out++ = 0;
181             } while (--len);
182             continue;
183             }
184             len -= op - whave;
185             do {
186             *out++ = 0;
187             } while (--op > whave);
188             if (op == 0) {
189             from = out - dist;
190             do {
191             *out++ = *from++;
192             } while (--len);
193             continue;
194             }
195             #endif
196             }
197 16           from = window;
198 16 50         if (wnext == 0) { /* very common case */
199 0           from += wsize - op;
200 0 0         if (op < len) { /* some from window */
201 0           len -= op;
202             do {
203 0           *out++ = *from++;
204 0 0         } while (--op);
205 0           from = out - dist; /* rest from output */
206             }
207             }
208 16 50         else if (wnext < op) { /* wrap around window */
209 0           from += wsize + wnext - op;
210 0           op -= wnext;
211 0 0         if (op < len) { /* some from end of window */
212 0           len -= op;
213             do {
214 0           *out++ = *from++;
215 0 0         } while (--op);
216 0           from = window;
217 0 0         if (wnext < len) { /* some from start of window */
218 0           op = wnext;
219 0           len -= op;
220             do {
221 0           *out++ = *from++;
222 0 0         } while (--op);
223 0           from = out - dist; /* rest from output */
224             }
225             }
226             }
227             else { /* contiguous in window */
228 16           from += wnext - op;
229 16 50         if (op < len) { /* some from window */
230 16           len -= op;
231             do {
232 137           *out++ = *from++;
233 137 100         } while (--op);
234 16           from = out - dist; /* rest from output */
235             }
236             }
237 1085 100         while (len > 2) {
238 1069           *out++ = *from++;
239 1069           *out++ = *from++;
240 1069           *out++ = *from++;
241 1069           len -= 3;
242             }
243 16 50         if (len) {
244 16           *out++ = *from++;
245 16 100         if (len > 1)
246 3           *out++ = *from++;
247             }
248             }
249             else {
250 1501           from = out - dist; /* copy direct from output */
251             do { /* minimum length is three */
252 128270           *out++ = *from++;
253 128270           *out++ = *from++;
254 128270           *out++ = *from++;
255 128270           len -= 3;
256 128270 100         } while (len > 2);
257 1501 100         if (len) {
258 10           *out++ = *from++;
259 10 100         if (len > 1)
260 9           *out++ = *from++;
261             }
262             }
263             }
264 0 0         else if ((op & 64) == 0) { /* 2nd level distance code */
265 0           here = dcode + here->val + (hold & ((1U << op) - 1));
266 0           goto dodist;
267             }
268             else {
269 0           strm->msg = (z_const char *)"invalid distance code";
270 0           state->mode = BAD;
271 0           break;
272             }
273             }
274 10 50         else if ((op & 64) == 0) { /* 2nd level length code */
275 0           here = lcode + here->val + (hold & ((1U << op) - 1));
276 0           goto dolen;
277             }
278 10 50         else if (op & 32) { /* end-of-block */
279             Tracevv((stderr, "inflate: end of block\n"));
280 10           state->mode = TYPE;
281 10           break;
282             }
283             else {
284 0           strm->msg = (z_const char *)"invalid literal/length code";
285 0           state->mode = BAD;
286 0           break;
287             }
288 1797 100         } while (in < last && out < end);
    100          
289              
290             /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
291 125           len = bits >> 3;
292 125           in -= len;
293 125           bits -= len << 3;
294 125           hold &= (1U << bits) - 1;
295              
296             /* update state and return */
297 125           strm->next_in = in;
298 125           strm->next_out = out;
299 125 100         strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
300 125 100         strm->avail_out = (unsigned)(out < end ?
301 125           257 + (end - out) : 257 - (out - end));
302 125           state->hold = hold;
303 125           state->bits = bits;
304 125           return;
305             }
306              
307             /*
308             inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
309             - Using bit fields for code structure
310             - Different op definition to avoid & for extra bits (do & for table bits)
311             - Three separate decoding do-loops for direct, window, and wnext == 0
312             - Special case for distance > 1 copies to do overlapped load and store copy
313             - Explicit branch predictions (based on measured branch probabilities)
314             - Deferring match copy and interspersed it with decoding subsequent codes
315             - Swapping literal/length else
316             - Swapping window/direct else
317             - Larger unrolled copy loops (three is about right)
318             - Moving len -= 3 statement into middle of loop
319             */
320              
321             #endif /* !ASMINF */