1b39c5158Smillert /* inffast.c -- fast decoding 25759b3d2Safresh1 * Copyright (C) 1995-2017 Mark Adler 3b39c5158Smillert * For conditions of distribution and use, see copyright notice in zlib.h 4b39c5158Smillert */ 5b39c5158Smillert 6b39c5158Smillert #include "zutil.h" 7b39c5158Smillert #include "inftrees.h" 8b39c5158Smillert #include "inflate.h" 9b39c5158Smillert #include "inffast.h" 10b39c5158Smillert 115759b3d2Safresh1 #ifdef ASMINF 125759b3d2Safresh1 # pragma message("Assembler code may have bugs -- use at your own risk") 13b39c5158Smillert #else 14b39c5158Smillert 15b39c5158Smillert /* 16b39c5158Smillert Decode literal, length, and distance codes and write out the resulting 17b39c5158Smillert literal and match bytes until either not enough input or output is 18b39c5158Smillert available, an end-of-block is encountered, or a data error is encountered. 19b39c5158Smillert When large enough input and output buffers are supplied to inflate(), for 20b39c5158Smillert example, a 16K input buffer and a 64K output buffer, more than 95% of the 21b39c5158Smillert inflate execution time is spent in this routine. 22b39c5158Smillert 23b39c5158Smillert Entry assumptions: 24b39c5158Smillert 25b39c5158Smillert state->mode == LEN 26b39c5158Smillert strm->avail_in >= 6 27b39c5158Smillert strm->avail_out >= 258 28b39c5158Smillert start >= strm->avail_out 29b39c5158Smillert state->bits < 8 30b39c5158Smillert 31b39c5158Smillert On return, state->mode is one of: 32b39c5158Smillert 33b39c5158Smillert LEN -- ran out of enough output space or enough available input 34b39c5158Smillert TYPE -- reached end of block code, inflate() to interpret next block 35b39c5158Smillert BAD -- error in block data 36b39c5158Smillert 37b39c5158Smillert Notes: 38b39c5158Smillert 39b39c5158Smillert - The maximum input bits used by a length/distance pair is 15 bits for the 40b39c5158Smillert length code, 5 bits for the length extra, 15 bits for the distance code, 41b39c5158Smillert and 13 bits for the distance extra. This totals 48 bits, or six bytes. 42b39c5158Smillert Therefore if strm->avail_in >= 6, then there is enough input to avoid 43b39c5158Smillert checking for available input while decoding. 44b39c5158Smillert 45b39c5158Smillert - The maximum bytes that a single length/distance pair can output is 258 46b39c5158Smillert bytes, which is the maximum length that can be coded. inflate_fast() 47b39c5158Smillert requires strm->avail_out >= 258 for each loop to avoid checking for 48b39c5158Smillert output space. 49b39c5158Smillert */ 50*5486feefSafresh1 void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) { 51b39c5158Smillert struct inflate_state FAR *state; 526fb12b70Safresh1 z_const unsigned char FAR *in; /* local strm->next_in */ 536fb12b70Safresh1 z_const unsigned char FAR *last; /* have enough input while in < last */ 54b39c5158Smillert unsigned char FAR *out; /* local strm->next_out */ 55b39c5158Smillert unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ 56b39c5158Smillert unsigned char FAR *end; /* while out < end, enough space available */ 57b39c5158Smillert #ifdef INFLATE_STRICT 58b39c5158Smillert unsigned dmax; /* maximum distance from zlib header */ 59b39c5158Smillert #endif 60b39c5158Smillert unsigned wsize; /* window size or zero if not using window */ 61b39c5158Smillert unsigned whave; /* valid bytes in the window */ 62898184e3Ssthen unsigned wnext; /* window write index */ 63b39c5158Smillert unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ 64b39c5158Smillert unsigned long hold; /* local strm->hold */ 65b39c5158Smillert unsigned bits; /* local strm->bits */ 66b39c5158Smillert code const FAR *lcode; /* local strm->lencode */ 67b39c5158Smillert code const FAR *dcode; /* local strm->distcode */ 68b39c5158Smillert unsigned lmask; /* mask for first level of length codes */ 69b39c5158Smillert unsigned dmask; /* mask for first level of distance codes */ 70256a93a4Safresh1 code const *here; /* retrieved table entry */ 71b39c5158Smillert unsigned op; /* code bits, operation, extra bits, or */ 72b39c5158Smillert /* window position, window bytes to copy */ 73b39c5158Smillert unsigned len; /* match length, unused bytes */ 74b39c5158Smillert unsigned dist; /* match distance */ 75b39c5158Smillert unsigned char FAR *from; /* where to copy match from */ 76b39c5158Smillert 77b39c5158Smillert /* copy state to local variables */ 78b39c5158Smillert state = (struct inflate_state FAR *)strm->state; 795759b3d2Safresh1 in = strm->next_in; 80b39c5158Smillert last = in + (strm->avail_in - 5); 815759b3d2Safresh1 out = strm->next_out; 82b39c5158Smillert beg = out - (start - strm->avail_out); 83b39c5158Smillert end = out + (strm->avail_out - 257); 84b39c5158Smillert #ifdef INFLATE_STRICT 85b39c5158Smillert dmax = state->dmax; 86b39c5158Smillert #endif 87b39c5158Smillert wsize = state->wsize; 88b39c5158Smillert whave = state->whave; 89898184e3Ssthen wnext = state->wnext; 90b39c5158Smillert window = state->window; 91b39c5158Smillert hold = state->hold; 92b39c5158Smillert bits = state->bits; 93b39c5158Smillert lcode = state->lencode; 94b39c5158Smillert dcode = state->distcode; 95b39c5158Smillert lmask = (1U << state->lenbits) - 1; 96b39c5158Smillert dmask = (1U << state->distbits) - 1; 97b39c5158Smillert 98b39c5158Smillert /* decode literals and length/distances until end-of-block or not enough 99b39c5158Smillert input data or output space */ 100b39c5158Smillert do { 101b39c5158Smillert if (bits < 15) { 1025759b3d2Safresh1 hold += (unsigned long)(*in++) << bits; 103b39c5158Smillert bits += 8; 1045759b3d2Safresh1 hold += (unsigned long)(*in++) << bits; 105b39c5158Smillert bits += 8; 106b39c5158Smillert } 107256a93a4Safresh1 here = lcode + (hold & lmask); 108b39c5158Smillert dolen: 109256a93a4Safresh1 op = (unsigned)(here->bits); 110b39c5158Smillert hold >>= op; 111b39c5158Smillert bits -= op; 112256a93a4Safresh1 op = (unsigned)(here->op); 113b39c5158Smillert if (op == 0) { /* literal */ 114256a93a4Safresh1 Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? 115b39c5158Smillert "inflate: literal '%c'\n" : 116256a93a4Safresh1 "inflate: literal 0x%02x\n", here->val)); 117256a93a4Safresh1 *out++ = (unsigned char)(here->val); 118b39c5158Smillert } 119b39c5158Smillert else if (op & 16) { /* length base */ 120256a93a4Safresh1 len = (unsigned)(here->val); 121b39c5158Smillert op &= 15; /* number of extra bits */ 122b39c5158Smillert if (op) { 123b39c5158Smillert if (bits < op) { 1245759b3d2Safresh1 hold += (unsigned long)(*in++) << bits; 125b39c5158Smillert bits += 8; 126b39c5158Smillert } 127b39c5158Smillert len += (unsigned)hold & ((1U << op) - 1); 128b39c5158Smillert hold >>= op; 129b39c5158Smillert bits -= op; 130b39c5158Smillert } 131b39c5158Smillert Tracevv((stderr, "inflate: length %u\n", len)); 132b39c5158Smillert if (bits < 15) { 1335759b3d2Safresh1 hold += (unsigned long)(*in++) << bits; 134b39c5158Smillert bits += 8; 1355759b3d2Safresh1 hold += (unsigned long)(*in++) << bits; 136b39c5158Smillert bits += 8; 137b39c5158Smillert } 138256a93a4Safresh1 here = dcode + (hold & dmask); 139b39c5158Smillert dodist: 140256a93a4Safresh1 op = (unsigned)(here->bits); 141b39c5158Smillert hold >>= op; 142b39c5158Smillert bits -= op; 143256a93a4Safresh1 op = (unsigned)(here->op); 144b39c5158Smillert if (op & 16) { /* distance base */ 145256a93a4Safresh1 dist = (unsigned)(here->val); 146b39c5158Smillert op &= 15; /* number of extra bits */ 147b39c5158Smillert if (bits < op) { 1485759b3d2Safresh1 hold += (unsigned long)(*in++) << bits; 149b39c5158Smillert bits += 8; 150b39c5158Smillert if (bits < op) { 1515759b3d2Safresh1 hold += (unsigned long)(*in++) << bits; 152b39c5158Smillert bits += 8; 153b39c5158Smillert } 154b39c5158Smillert } 155b39c5158Smillert dist += (unsigned)hold & ((1U << op) - 1); 156b39c5158Smillert #ifdef INFLATE_STRICT 157b39c5158Smillert if (dist > dmax) { 158b39c5158Smillert strm->msg = (char *)"invalid distance too far back"; 159b39c5158Smillert state->mode = BAD; 160b39c5158Smillert break; 161b39c5158Smillert } 162b39c5158Smillert #endif 163b39c5158Smillert hold >>= op; 164b39c5158Smillert bits -= op; 165b39c5158Smillert Tracevv((stderr, "inflate: distance %u\n", dist)); 166b39c5158Smillert op = (unsigned)(out - beg); /* max distance in output */ 167b39c5158Smillert if (dist > op) { /* see if copy from window */ 168b39c5158Smillert op = dist - op; /* distance back in window */ 169b39c5158Smillert if (op > whave) { 170898184e3Ssthen if (state->sane) { 171898184e3Ssthen strm->msg = 172898184e3Ssthen (char *)"invalid distance too far back"; 173b39c5158Smillert state->mode = BAD; 174b39c5158Smillert break; 175b39c5158Smillert } 176898184e3Ssthen #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR 177898184e3Ssthen if (len <= op - whave) { 178898184e3Ssthen do { 1795759b3d2Safresh1 *out++ = 0; 180898184e3Ssthen } while (--len); 181898184e3Ssthen continue; 182898184e3Ssthen } 183898184e3Ssthen len -= op - whave; 184898184e3Ssthen do { 1855759b3d2Safresh1 *out++ = 0; 186898184e3Ssthen } while (--op > whave); 187898184e3Ssthen if (op == 0) { 188898184e3Ssthen from = out - dist; 189898184e3Ssthen do { 1905759b3d2Safresh1 *out++ = *from++; 191898184e3Ssthen } while (--len); 192898184e3Ssthen continue; 193898184e3Ssthen } 194898184e3Ssthen #endif 195898184e3Ssthen } 1965759b3d2Safresh1 from = window; 197898184e3Ssthen if (wnext == 0) { /* very common case */ 198b39c5158Smillert from += wsize - op; 199b39c5158Smillert if (op < len) { /* some from window */ 200b39c5158Smillert len -= op; 201b39c5158Smillert do { 2025759b3d2Safresh1 *out++ = *from++; 203b39c5158Smillert } while (--op); 204b39c5158Smillert from = out - dist; /* rest from output */ 205b39c5158Smillert } 206b39c5158Smillert } 207898184e3Ssthen else if (wnext < op) { /* wrap around window */ 208898184e3Ssthen from += wsize + wnext - op; 209898184e3Ssthen op -= wnext; 210b39c5158Smillert if (op < len) { /* some from end of window */ 211b39c5158Smillert len -= op; 212b39c5158Smillert do { 2135759b3d2Safresh1 *out++ = *from++; 214b39c5158Smillert } while (--op); 2155759b3d2Safresh1 from = window; 216898184e3Ssthen if (wnext < len) { /* some from start of window */ 217898184e3Ssthen op = wnext; 218b39c5158Smillert len -= op; 219b39c5158Smillert do { 2205759b3d2Safresh1 *out++ = *from++; 221b39c5158Smillert } while (--op); 222b39c5158Smillert from = out - dist; /* rest from output */ 223b39c5158Smillert } 224b39c5158Smillert } 225b39c5158Smillert } 226b39c5158Smillert else { /* contiguous in window */ 227898184e3Ssthen from += wnext - op; 228b39c5158Smillert if (op < len) { /* some from window */ 229b39c5158Smillert len -= op; 230b39c5158Smillert do { 2315759b3d2Safresh1 *out++ = *from++; 232b39c5158Smillert } while (--op); 233b39c5158Smillert from = out - dist; /* rest from output */ 234b39c5158Smillert } 235b39c5158Smillert } 236b39c5158Smillert while (len > 2) { 2375759b3d2Safresh1 *out++ = *from++; 2385759b3d2Safresh1 *out++ = *from++; 2395759b3d2Safresh1 *out++ = *from++; 240b39c5158Smillert len -= 3; 241b39c5158Smillert } 242b39c5158Smillert if (len) { 2435759b3d2Safresh1 *out++ = *from++; 244b39c5158Smillert if (len > 1) 2455759b3d2Safresh1 *out++ = *from++; 246b39c5158Smillert } 247b39c5158Smillert } 248b39c5158Smillert else { 249b39c5158Smillert from = out - dist; /* copy direct from output */ 250b39c5158Smillert do { /* minimum length is three */ 2515759b3d2Safresh1 *out++ = *from++; 2525759b3d2Safresh1 *out++ = *from++; 2535759b3d2Safresh1 *out++ = *from++; 254b39c5158Smillert len -= 3; 255b39c5158Smillert } while (len > 2); 256b39c5158Smillert if (len) { 2575759b3d2Safresh1 *out++ = *from++; 258b39c5158Smillert if (len > 1) 2595759b3d2Safresh1 *out++ = *from++; 260b39c5158Smillert } 261b39c5158Smillert } 262b39c5158Smillert } 263b39c5158Smillert else if ((op & 64) == 0) { /* 2nd level distance code */ 264256a93a4Safresh1 here = dcode + here->val + (hold & ((1U << op) - 1)); 265b39c5158Smillert goto dodist; 266b39c5158Smillert } 267b39c5158Smillert else { 268b39c5158Smillert strm->msg = (char *)"invalid distance code"; 269b39c5158Smillert state->mode = BAD; 270b39c5158Smillert break; 271b39c5158Smillert } 272b39c5158Smillert } 273b39c5158Smillert else if ((op & 64) == 0) { /* 2nd level length code */ 274256a93a4Safresh1 here = lcode + here->val + (hold & ((1U << op) - 1)); 275b39c5158Smillert goto dolen; 276b39c5158Smillert } 277b39c5158Smillert else if (op & 32) { /* end-of-block */ 278b39c5158Smillert Tracevv((stderr, "inflate: end of block\n")); 279b39c5158Smillert state->mode = TYPE; 280b39c5158Smillert break; 281b39c5158Smillert } 282b39c5158Smillert else { 283b39c5158Smillert strm->msg = (char *)"invalid literal/length code"; 284b39c5158Smillert state->mode = BAD; 285b39c5158Smillert break; 286b39c5158Smillert } 287b39c5158Smillert } while (in < last && out < end); 288b39c5158Smillert 289b39c5158Smillert /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ 290b39c5158Smillert len = bits >> 3; 291b39c5158Smillert in -= len; 292b39c5158Smillert bits -= len << 3; 293b39c5158Smillert hold &= (1U << bits) - 1; 294b39c5158Smillert 295b39c5158Smillert /* update state and return */ 2965759b3d2Safresh1 strm->next_in = in; 2975759b3d2Safresh1 strm->next_out = out; 298b39c5158Smillert strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); 299b39c5158Smillert strm->avail_out = (unsigned)(out < end ? 300b39c5158Smillert 257 + (end - out) : 257 - (out - end)); 301b39c5158Smillert state->hold = hold; 302b39c5158Smillert state->bits = bits; 303b39c5158Smillert return; 304b39c5158Smillert } 305b39c5158Smillert 306b39c5158Smillert /* 307b39c5158Smillert inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): 308b39c5158Smillert - Using bit fields for code structure 309b39c5158Smillert - Different op definition to avoid & for extra bits (do & for table bits) 310898184e3Ssthen - Three separate decoding do-loops for direct, window, and wnext == 0 311b39c5158Smillert - Special case for distance > 1 copies to do overlapped load and store copy 312b39c5158Smillert - Explicit branch predictions (based on measured branch probabilities) 313b39c5158Smillert - Deferring match copy and interspersed it with decoding subsequent codes 314b39c5158Smillert - Swapping literal/length else 315b39c5158Smillert - Swapping window/direct else 316b39c5158Smillert - Larger unrolled copy loops (three is about right) 317b39c5158Smillert - Moving len -= 3 statement into middle of loop 318b39c5158Smillert */ 319b39c5158Smillert 320b39c5158Smillert #endif /* !ASMINF */ 321