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 */ 50221b1638SMasahiro Yamada void ZLIB_INTERNAL inflate_fast(strm, start) 51221b1638SMasahiro Yamada z_streamp strm; 52221b1638SMasahiro Yamada unsigned start; /* inflate()'s starting value for strm->avail_out */ 53221b1638SMasahiro Yamada { 54221b1638SMasahiro Yamada struct inflate_state FAR *state; 55221b1638SMasahiro Yamada z_const unsigned char FAR *in; /* local strm->next_in */ 56221b1638SMasahiro Yamada z_const unsigned char FAR *last; /* have enough input while in < last */ 57221b1638SMasahiro Yamada unsigned char FAR *out; /* local strm->next_out */ 58221b1638SMasahiro Yamada unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ 59221b1638SMasahiro Yamada unsigned char FAR *end; /* while out < end, enough space available */ 60221b1638SMasahiro Yamada #ifdef INFLATE_STRICT 61221b1638SMasahiro Yamada unsigned dmax; /* maximum distance from zlib header */ 62221b1638SMasahiro Yamada #endif 63221b1638SMasahiro Yamada unsigned wsize; /* window size or zero if not using window */ 64221b1638SMasahiro Yamada unsigned whave; /* valid bytes in the window */ 65221b1638SMasahiro Yamada unsigned wnext; /* window write index */ 66221b1638SMasahiro Yamada unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ 67221b1638SMasahiro Yamada unsigned long hold; /* local strm->hold */ 68221b1638SMasahiro Yamada unsigned bits; /* local strm->bits */ 69221b1638SMasahiro Yamada code const FAR *lcode; /* local strm->lencode */ 70221b1638SMasahiro Yamada code const FAR *dcode; /* local strm->distcode */ 71221b1638SMasahiro Yamada unsigned lmask; /* mask for first level of length codes */ 72221b1638SMasahiro Yamada unsigned dmask; /* mask for first level of distance codes */ 73*a194255dSDaniel Boulby code const *here; /* retrieved table entry */ 74221b1638SMasahiro Yamada unsigned op; /* code bits, operation, extra bits, or */ 75221b1638SMasahiro Yamada /* window position, window bytes to copy */ 76221b1638SMasahiro Yamada unsigned len; /* match length, unused bytes */ 77221b1638SMasahiro Yamada unsigned dist; /* match distance */ 78221b1638SMasahiro Yamada unsigned char FAR *from; /* where to copy match from */ 79221b1638SMasahiro Yamada 80221b1638SMasahiro Yamada /* copy state to local variables */ 81221b1638SMasahiro Yamada state = (struct inflate_state FAR *)strm->state; 82221b1638SMasahiro Yamada in = strm->next_in; 83221b1638SMasahiro Yamada last = in + (strm->avail_in - 5); 84221b1638SMasahiro Yamada out = strm->next_out; 85221b1638SMasahiro Yamada beg = out - (start - strm->avail_out); 86221b1638SMasahiro Yamada end = out + (strm->avail_out - 257); 87221b1638SMasahiro Yamada #ifdef INFLATE_STRICT 88221b1638SMasahiro Yamada dmax = state->dmax; 89221b1638SMasahiro Yamada #endif 90221b1638SMasahiro Yamada wsize = state->wsize; 91221b1638SMasahiro Yamada whave = state->whave; 92221b1638SMasahiro Yamada wnext = state->wnext; 93221b1638SMasahiro Yamada window = state->window; 94221b1638SMasahiro Yamada hold = state->hold; 95221b1638SMasahiro Yamada bits = state->bits; 96221b1638SMasahiro Yamada lcode = state->lencode; 97221b1638SMasahiro Yamada dcode = state->distcode; 98221b1638SMasahiro Yamada lmask = (1U << state->lenbits) - 1; 99221b1638SMasahiro Yamada dmask = (1U << state->distbits) - 1; 100221b1638SMasahiro Yamada 101221b1638SMasahiro Yamada /* decode literals and length/distances until end-of-block or not enough 102221b1638SMasahiro Yamada input data or output space */ 103221b1638SMasahiro Yamada do { 104221b1638SMasahiro Yamada if (bits < 15) { 105221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits; 106221b1638SMasahiro Yamada bits += 8; 107221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits; 108221b1638SMasahiro Yamada bits += 8; 109221b1638SMasahiro Yamada } 110*a194255dSDaniel Boulby here = lcode + (hold & lmask); 111221b1638SMasahiro Yamada dolen: 112*a194255dSDaniel Boulby op = (unsigned)(here->bits); 113221b1638SMasahiro Yamada hold >>= op; 114221b1638SMasahiro Yamada bits -= op; 115*a194255dSDaniel Boulby op = (unsigned)(here->op); 116221b1638SMasahiro Yamada if (op == 0) { /* literal */ 117*a194255dSDaniel Boulby Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? 118221b1638SMasahiro Yamada "inflate: literal '%c'\n" : 119*a194255dSDaniel Boulby "inflate: literal 0x%02x\n", here->val)); 120*a194255dSDaniel Boulby *out++ = (unsigned char)(here->val); 121221b1638SMasahiro Yamada } 122221b1638SMasahiro Yamada else if (op & 16) { /* length base */ 123*a194255dSDaniel Boulby len = (unsigned)(here->val); 124221b1638SMasahiro Yamada op &= 15; /* number of extra bits */ 125221b1638SMasahiro Yamada if (op) { 126221b1638SMasahiro Yamada if (bits < op) { 127221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits; 128221b1638SMasahiro Yamada bits += 8; 129221b1638SMasahiro Yamada } 130221b1638SMasahiro Yamada len += (unsigned)hold & ((1U << op) - 1); 131221b1638SMasahiro Yamada hold >>= op; 132221b1638SMasahiro Yamada bits -= op; 133221b1638SMasahiro Yamada } 134221b1638SMasahiro Yamada Tracevv((stderr, "inflate: length %u\n", len)); 135221b1638SMasahiro Yamada if (bits < 15) { 136221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits; 137221b1638SMasahiro Yamada bits += 8; 138221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits; 139221b1638SMasahiro Yamada bits += 8; 140221b1638SMasahiro Yamada } 141*a194255dSDaniel Boulby here = dcode + (hold & dmask); 142221b1638SMasahiro Yamada dodist: 143*a194255dSDaniel Boulby op = (unsigned)(here->bits); 144221b1638SMasahiro Yamada hold >>= op; 145221b1638SMasahiro Yamada bits -= op; 146*a194255dSDaniel Boulby op = (unsigned)(here->op); 147221b1638SMasahiro Yamada if (op & 16) { /* distance base */ 148*a194255dSDaniel Boulby dist = (unsigned)(here->val); 149221b1638SMasahiro Yamada op &= 15; /* number of extra bits */ 150221b1638SMasahiro Yamada if (bits < op) { 151221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits; 152221b1638SMasahiro Yamada bits += 8; 153221b1638SMasahiro Yamada if (bits < op) { 154221b1638SMasahiro Yamada hold += (unsigned long)(*in++) << bits; 155221b1638SMasahiro Yamada bits += 8; 156221b1638SMasahiro Yamada } 157221b1638SMasahiro Yamada } 158221b1638SMasahiro Yamada dist += (unsigned)hold & ((1U << op) - 1); 159221b1638SMasahiro Yamada #ifdef INFLATE_STRICT 160221b1638SMasahiro Yamada if (dist > dmax) { 161221b1638SMasahiro Yamada strm->msg = (char *)"invalid distance too far back"; 162221b1638SMasahiro Yamada state->mode = BAD; 163221b1638SMasahiro Yamada break; 164221b1638SMasahiro Yamada } 165221b1638SMasahiro Yamada #endif 166221b1638SMasahiro Yamada hold >>= op; 167221b1638SMasahiro Yamada bits -= op; 168221b1638SMasahiro Yamada Tracevv((stderr, "inflate: distance %u\n", dist)); 169221b1638SMasahiro Yamada op = (unsigned)(out - beg); /* max distance in output */ 170221b1638SMasahiro Yamada if (dist > op) { /* see if copy from window */ 171221b1638SMasahiro Yamada op = dist - op; /* distance back in window */ 172221b1638SMasahiro Yamada if (op > whave) { 173221b1638SMasahiro Yamada if (state->sane) { 174221b1638SMasahiro Yamada strm->msg = 175221b1638SMasahiro Yamada (char *)"invalid distance too far back"; 176221b1638SMasahiro Yamada state->mode = BAD; 177221b1638SMasahiro Yamada break; 178221b1638SMasahiro Yamada } 179221b1638SMasahiro Yamada #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR 180221b1638SMasahiro Yamada if (len <= op - whave) { 181221b1638SMasahiro Yamada do { 182221b1638SMasahiro Yamada *out++ = 0; 183221b1638SMasahiro Yamada } while (--len); 184221b1638SMasahiro Yamada continue; 185221b1638SMasahiro Yamada } 186221b1638SMasahiro Yamada len -= op - whave; 187221b1638SMasahiro Yamada do { 188221b1638SMasahiro Yamada *out++ = 0; 189221b1638SMasahiro Yamada } while (--op > whave); 190221b1638SMasahiro Yamada if (op == 0) { 191221b1638SMasahiro Yamada from = out - dist; 192221b1638SMasahiro Yamada do { 193221b1638SMasahiro Yamada *out++ = *from++; 194221b1638SMasahiro Yamada } while (--len); 195221b1638SMasahiro Yamada continue; 196221b1638SMasahiro Yamada } 197221b1638SMasahiro Yamada #endif 198221b1638SMasahiro Yamada } 199221b1638SMasahiro Yamada from = window; 200221b1638SMasahiro Yamada if (wnext == 0) { /* very common case */ 201221b1638SMasahiro Yamada from += wsize - op; 202221b1638SMasahiro Yamada if (op < len) { /* some from window */ 203221b1638SMasahiro Yamada len -= op; 204221b1638SMasahiro Yamada do { 205221b1638SMasahiro Yamada *out++ = *from++; 206221b1638SMasahiro Yamada } while (--op); 207221b1638SMasahiro Yamada from = out - dist; /* rest from output */ 208221b1638SMasahiro Yamada } 209221b1638SMasahiro Yamada } 210221b1638SMasahiro Yamada else if (wnext < op) { /* wrap around window */ 211221b1638SMasahiro Yamada from += wsize + wnext - op; 212221b1638SMasahiro Yamada op -= wnext; 213221b1638SMasahiro Yamada if (op < len) { /* some from end of window */ 214221b1638SMasahiro Yamada len -= op; 215221b1638SMasahiro Yamada do { 216221b1638SMasahiro Yamada *out++ = *from++; 217221b1638SMasahiro Yamada } while (--op); 218221b1638SMasahiro Yamada from = window; 219221b1638SMasahiro Yamada if (wnext < len) { /* some from start of window */ 220221b1638SMasahiro Yamada op = wnext; 221221b1638SMasahiro Yamada len -= op; 222221b1638SMasahiro Yamada do { 223221b1638SMasahiro Yamada *out++ = *from++; 224221b1638SMasahiro Yamada } while (--op); 225221b1638SMasahiro Yamada from = out - dist; /* rest from output */ 226221b1638SMasahiro Yamada } 227221b1638SMasahiro Yamada } 228221b1638SMasahiro Yamada } 229221b1638SMasahiro Yamada else { /* contiguous in window */ 230221b1638SMasahiro Yamada from += wnext - op; 231221b1638SMasahiro Yamada if (op < len) { /* some from window */ 232221b1638SMasahiro Yamada len -= op; 233221b1638SMasahiro Yamada do { 234221b1638SMasahiro Yamada *out++ = *from++; 235221b1638SMasahiro Yamada } while (--op); 236221b1638SMasahiro Yamada from = out - dist; /* rest from output */ 237221b1638SMasahiro Yamada } 238221b1638SMasahiro Yamada } 239221b1638SMasahiro Yamada while (len > 2) { 240221b1638SMasahiro Yamada *out++ = *from++; 241221b1638SMasahiro Yamada *out++ = *from++; 242221b1638SMasahiro Yamada *out++ = *from++; 243221b1638SMasahiro Yamada len -= 3; 244221b1638SMasahiro Yamada } 245221b1638SMasahiro Yamada if (len) { 246221b1638SMasahiro Yamada *out++ = *from++; 247221b1638SMasahiro Yamada if (len > 1) 248221b1638SMasahiro Yamada *out++ = *from++; 249221b1638SMasahiro Yamada } 250221b1638SMasahiro Yamada } 251221b1638SMasahiro Yamada else { 252221b1638SMasahiro Yamada from = out - dist; /* copy direct from output */ 253221b1638SMasahiro Yamada do { /* minimum length is three */ 254221b1638SMasahiro Yamada *out++ = *from++; 255221b1638SMasahiro Yamada *out++ = *from++; 256221b1638SMasahiro Yamada *out++ = *from++; 257221b1638SMasahiro Yamada len -= 3; 258221b1638SMasahiro Yamada } while (len > 2); 259221b1638SMasahiro Yamada if (len) { 260221b1638SMasahiro Yamada *out++ = *from++; 261221b1638SMasahiro Yamada if (len > 1) 262221b1638SMasahiro Yamada *out++ = *from++; 263221b1638SMasahiro Yamada } 264221b1638SMasahiro Yamada } 265221b1638SMasahiro Yamada } 266221b1638SMasahiro Yamada else if ((op & 64) == 0) { /* 2nd level distance code */ 267*a194255dSDaniel Boulby here = dcode + here->val + (hold & ((1U << op) - 1)); 268221b1638SMasahiro Yamada goto dodist; 269221b1638SMasahiro Yamada } 270221b1638SMasahiro Yamada else { 271221b1638SMasahiro Yamada strm->msg = (char *)"invalid distance code"; 272221b1638SMasahiro Yamada state->mode = BAD; 273221b1638SMasahiro Yamada break; 274221b1638SMasahiro Yamada } 275221b1638SMasahiro Yamada } 276221b1638SMasahiro Yamada else if ((op & 64) == 0) { /* 2nd level length code */ 277*a194255dSDaniel Boulby here = lcode + here->val + (hold & ((1U << op) - 1)); 278221b1638SMasahiro Yamada goto dolen; 279221b1638SMasahiro Yamada } 280221b1638SMasahiro Yamada else if (op & 32) { /* end-of-block */ 281221b1638SMasahiro Yamada Tracevv((stderr, "inflate: end of block\n")); 282221b1638SMasahiro Yamada state->mode = TYPE; 283221b1638SMasahiro Yamada break; 284221b1638SMasahiro Yamada } 285221b1638SMasahiro Yamada else { 286221b1638SMasahiro Yamada strm->msg = (char *)"invalid literal/length code"; 287221b1638SMasahiro Yamada state->mode = BAD; 288221b1638SMasahiro Yamada break; 289221b1638SMasahiro Yamada } 290221b1638SMasahiro Yamada } while (in < last && out < end); 291221b1638SMasahiro Yamada 292221b1638SMasahiro Yamada /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ 293221b1638SMasahiro Yamada len = bits >> 3; 294221b1638SMasahiro Yamada in -= len; 295221b1638SMasahiro Yamada bits -= len << 3; 296221b1638SMasahiro Yamada hold &= (1U << bits) - 1; 297221b1638SMasahiro Yamada 298221b1638SMasahiro Yamada /* update state and return */ 299221b1638SMasahiro Yamada strm->next_in = in; 300221b1638SMasahiro Yamada strm->next_out = out; 301221b1638SMasahiro Yamada strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); 302221b1638SMasahiro Yamada strm->avail_out = (unsigned)(out < end ? 303221b1638SMasahiro Yamada 257 + (end - out) : 257 - (out - end)); 304221b1638SMasahiro Yamada state->hold = hold; 305221b1638SMasahiro Yamada state->bits = bits; 306221b1638SMasahiro Yamada return; 307221b1638SMasahiro Yamada } 308221b1638SMasahiro Yamada 309221b1638SMasahiro Yamada /* 310221b1638SMasahiro Yamada inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): 311221b1638SMasahiro Yamada - Using bit fields for code structure 312221b1638SMasahiro Yamada - Different op definition to avoid & for extra bits (do & for table bits) 313221b1638SMasahiro Yamada - Three separate decoding do-loops for direct, window, and wnext == 0 314221b1638SMasahiro Yamada - Special case for distance > 1 copies to do overlapped load and store copy 315221b1638SMasahiro Yamada - Explicit branch predictions (based on measured branch probabilities) 316221b1638SMasahiro Yamada - Deferring match copy and interspersed it with decoding subsequent codes 317221b1638SMasahiro Yamada - Swapping literal/length else 318221b1638SMasahiro Yamada - Swapping window/direct else 319221b1638SMasahiro Yamada - Larger unrolled copy loops (three is about right) 320221b1638SMasahiro Yamada - Moving len -= 3 statement into middle of loop 321221b1638SMasahiro Yamada */ 322221b1638SMasahiro Yamada 323221b1638SMasahiro Yamada #endif /* !ASMINF */ 324