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