19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* infback.c -- inflate using a call-back interface 2ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes * Copyright (C) 1995-2011 Mark Adler 39e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project * For conditions of distribution and use, see copyright notice in zlib.h 49e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */ 59e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 69e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* 79e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project This code is largely copied from inflate.c. Normally either infback.o or 89e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflate.o would be linked into an application--not both. The interface 99e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project with inffast.c is retained so that optimized assembler-coded versions of 109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflate_fast() can be used with either inflate.c or infback.c. 119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */ 129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "zutil.h" 149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "inftrees.h" 159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "inflate.h" 169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "inffast.h" 179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* function prototypes */ 199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void fixedtables OF((struct inflate_state FAR *state)); 209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* 229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm provides memory allocation functions in zalloc and zfree, or 239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Z_NULL to use the library memory allocation functions. 249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project windowBits is in the range 8..15, and window is a user-supplied 269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project window and output buffer that is 2**windowBits bytes. 279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */ 289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) 299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectz_streamp strm; 309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint windowBits; 319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectunsigned char FAR *window; 329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectconst char *version; 339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint stream_size; 349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project struct inflate_state FAR *state; 369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || 389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project stream_size != (int)(sizeof(z_stream))) 399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_VERSION_ERROR; 409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (strm == Z_NULL || window == Z_NULL || 419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project windowBits < 8 || windowBits > 15) 429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_STREAM_ERROR; 439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = Z_NULL; /* in case we return an error */ 449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (strm->zalloc == (alloc_func)0) { 45ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#ifdef Z_SOLO 46ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes return Z_STREAM_ERROR; 47ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#else 489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->zalloc = zcalloc; 499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->opaque = (voidpf)0; 50ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#endif 519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 52ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes if (strm->zfree == (free_func)0) 53ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#ifdef Z_SOLO 54ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes return Z_STREAM_ERROR; 55ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#else 56ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes strm->zfree = zcfree; 57ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#endif 589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state = (struct inflate_state FAR *)ZALLOC(strm, 1, 599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project sizeof(struct inflate_state)); 609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state == Z_NULL) return Z_MEM_ERROR; 619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: allocated\n")); 629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->state = (struct internal_state FAR *)state; 639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->dmax = 32768U; 649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->wbits = windowBits; 659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->wsize = 1U << windowBits; 669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->window = window; 67381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->wnext = 0; 689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->whave = 0; 699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_OK; 709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* 739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Return state with length and distance decoding tables and index sizes set to 749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fixed code decoding. Normally this returns fixed tables from inffixed.h. 759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project If BUILDFIXED is defined, then instead this routine builds the tables the 769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project first time it's called, and returns those tables the first time and 779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project thereafter. This reduces the size of the code by about 2K bytes, in 789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project exchange for a little execution time. However, BUILDFIXED should not be 799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project used for threaded applications, since the rewriting of the tables and virgin 809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project may not be thread-safe. 819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */ 829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectlocal void fixedtables(state) 839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectstruct inflate_state FAR *state; 849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#ifdef BUILDFIXED 869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project static int virgin = 1; 879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project static code *lenfix, *distfix; 889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project static code fixed[544]; 899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* build fixed huffman tables if first call (may not be thread safe) */ 919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (virgin) { 929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned sym, bits; 939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project static code *next; 949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* literal/length table */ 969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project sym = 0; 979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (sym < 144) state->lens[sym++] = 8; 989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (sym < 256) state->lens[sym++] = 9; 999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (sym < 280) state->lens[sym++] = 7; 1009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (sym < 288) state->lens[sym++] = 8; 1019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project next = fixed; 1029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project lenfix = next; 1039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bits = 9; 1049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); 1059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* distance table */ 1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project sym = 0; 1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (sym < 32) state->lens[sym++] = 5; 1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project distfix = next; 1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bits = 5; 1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); 1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* do this just once */ 1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project virgin = 0; 1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#else /* !BUILDFIXED */ 1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project# include "inffixed.h" 1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#endif /* BUILDFIXED */ 1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->lencode = lenfix; 1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->lenbits = 9; 1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->distcode = distfix; 1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->distbits = 5; 1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Macros for inflateBack(): */ 1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Load returned state from inflate_fast() */ 1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define LOAD() \ 1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { \ 1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project put = strm->next_out; \ 1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left = strm->avail_out; \ 1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project next = strm->next_in; \ 1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have = strm->avail_in; \ 1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project hold = state->hold; \ 1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bits = state->bits; \ 1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (0) 1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Set state from registers for inflate_fast() */ 1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define RESTORE() \ 1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { \ 1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->next_out = put; \ 1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->avail_out = left; \ 1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->next_in = next; \ 1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->avail_in = have; \ 1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->hold = hold; \ 1469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->bits = bits; \ 1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (0) 1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Clear the input bit accumulator */ 1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define INITBITS() \ 1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { \ 1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project hold = 0; \ 1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bits = 0; \ 1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (0) 1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Assure that some input is available. If input is requested, but denied, 1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project then return a Z_BUF_ERROR from inflateBack(). */ 1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define PULL() \ 1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { \ 1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (have == 0) { \ 1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have = in(in_desc, &next); \ 1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (have == 0) { \ 1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project next = Z_NULL; \ 1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = Z_BUF_ERROR; \ 1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project goto inf_leave; \ 1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } \ 1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } \ 1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (0) 1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Get a byte of input into the bit accumulator, or return from inflateBack() 1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project with an error if there is no input available. */ 1729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define PULLBYTE() \ 1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { \ 1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project PULL(); \ 1759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have--; \ 1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project hold += (unsigned long)(*next++) << bits; \ 1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bits += 8; \ 1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (0) 1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Assure that there are at least n bits in the bit accumulator. If there is 1819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project not enough available input to do that, then return from inflateBack() with 1829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project an error. */ 1839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define NEEDBITS(n) \ 1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { \ 1859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (bits < (unsigned)(n)) \ 1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project PULLBYTE(); \ 1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (0) 1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Return the low n bits of the bit accumulator (n < 16) */ 1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define BITS(n) \ 1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ((unsigned)hold & ((1U << (n)) - 1)) 1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Remove n bits from the bit accumulator */ 1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define DROPBITS(n) \ 1959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { \ 1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project hold >>= (n); \ 1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bits -= (unsigned)(n); \ 1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (0) 1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Remove zero to seven bits as needed to go to a byte boundary */ 2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define BYTEBITS() \ 2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { \ 2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project hold >>= bits & 7; \ 2049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bits -= bits & 7; \ 2059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (0) 2069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Assure that some output space is available, by writing out the window 2089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if it's full. If the write fails, return from inflateBack() with a 2099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Z_BUF_ERROR. */ 2109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define ROOM() \ 2119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { \ 2129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (left == 0) { \ 2139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project put = state->window; \ 2149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left = state->wsize; \ 2159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->whave = left; \ 2169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (out(out_desc, put, left)) { \ 2179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = Z_BUF_ERROR; \ 2189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project goto inf_leave; \ 2199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } \ 2209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } \ 2219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (0) 2229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* 2249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm provides the memory allocation functions and window buffer on input, 2259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project and provides information on the unused input on return. For Z_DATA_ERROR 2269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project returns, strm will also provide an error message. 2279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project in() and out() are the call-back input and output functions. When 2299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflateBack() needs more input, it calls in(). When inflateBack() has 2309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project filled the window with output, or when it completes with data in the 2319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project window, it calls out() to write out the data. The application must not 2329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project change the provided input until in() is called again or inflateBack() 2339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project returns. The application must not change the window/output buffer until 2349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflateBack() returns. 2359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project in() and out() are called with a descriptor parameter provided in the 2379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflateBack() call. This parameter can be a structure that provides the 2389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project information required to do the read or write, as well as accumulated 2399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project information on the input and output such as totals and check values. 2409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project in() should return zero on failure. out() should return non-zero on 2429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project failure. If either in() or out() fails, than inflateBack() returns a 2439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it 2449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project was in() or out() that caused in the error. Otherwise, inflateBack() 2459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format 2469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project error, or Z_MEM_ERROR if it could not allocate memory for the state. 2479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflateBack() can also return Z_STREAM_ERROR if the input parameters 2489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project are not correct, i.e. strm is Z_NULL or the state was not initialized. 2499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */ 2509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) 2519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectz_streamp strm; 2529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectin_func in; 2539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectvoid FAR *in_desc; 2549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectout_func out; 2559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectvoid FAR *out_desc; 2569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 2579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project struct inflate_state FAR *state; 2589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned char FAR *next; /* next input */ 2599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned char FAR *put; /* next output */ 2609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned have, left; /* available input and output */ 2619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned long hold; /* bit buffer */ 2629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned bits; /* bits in bit buffer */ 2639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned copy; /* number of stored or match bytes to copy */ 2649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned char FAR *from; /* where to copy match bytes from */ 265381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes code here; /* current decoding table entry */ 2669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project code last; /* parent table entry */ 2679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned len; /* length to copy for repeats, bits to drop */ 2689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int ret; /* return code */ 2699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project static const unsigned short order[19] = /* permutation of code lengths */ 2709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; 2719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* Check that the strm exists and that the state was initialized */ 2739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (strm == Z_NULL || strm->state == Z_NULL) 2749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_STREAM_ERROR; 2759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state = (struct inflate_state FAR *)strm->state; 2769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* Reset the state */ 2789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = Z_NULL; 2799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = TYPE; 2809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->last = 0; 2819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->whave = 0; 2829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project next = strm->next_in; 2839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have = next != Z_NULL ? strm->avail_in : 0; 2849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project hold = 0; 2859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project bits = 0; 2869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project put = state->window; 2879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left = state->wsize; 2889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* Inflate until end of block marked as last */ 2909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project for (;;) 2919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project switch (state->mode) { 2929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case TYPE: 2939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* determine and dispatch block type */ 2949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state->last) { 2959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project BYTEBITS(); 2969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = DONE; 2979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 2989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 2999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project NEEDBITS(3); 3009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->last = BITS(1); 3019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(1); 3029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project switch (BITS(2)) { 3039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case 0: /* stored block */ 3049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: stored block%s\n", 3059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->last ? " (last)" : "")); 3069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = STORED; 3079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 3089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case 1: /* fixed block */ 3099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fixedtables(state); 3109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: fixed codes block%s\n", 3119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->last ? " (last)" : "")); 3129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = LEN; /* decode codes */ 3139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 3149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case 2: /* dynamic block */ 3159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: dynamic codes block%s\n", 3169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->last ? " (last)" : "")); 3179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = TABLE; 3189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 3199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case 3: 3209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid block type"; 3219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 3229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(2); 3249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 3259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case STORED: 3279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* get and verify stored block length */ 3289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project BYTEBITS(); /* go to byte boundary */ 3299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project NEEDBITS(32); 3309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { 3319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid stored block lengths"; 3329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 3339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 3349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->length = (unsigned)hold & 0xffff; 3369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: stored length %u\n", 3379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->length)); 3389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project INITBITS(); 3399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* copy stored block from input to output */ 3419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (state->length != 0) { 3429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project copy = state->length; 3439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project PULL(); 3449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ROOM(); 3459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (copy > have) copy = have; 3469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (copy > left) copy = left; 3479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project zmemcpy(put, next, copy); 3489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have -= copy; 3499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project next += copy; 3509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left -= copy; 3519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project put += copy; 3529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->length -= copy; 3539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: stored end\n")); 3559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = TYPE; 3569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 3579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case TABLE: 3599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* get dynamic table entries descriptor */ 3609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project NEEDBITS(14); 3619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->nlen = BITS(5) + 257; 3629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(5); 3639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->ndist = BITS(5) + 1; 3649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(5); 3659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->ncode = BITS(4) + 4; 3669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(4); 3679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#ifndef PKZIP_BUG_WORKAROUND 3689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state->nlen > 286 || state->ndist > 30) { 3699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"too many length or distance symbols"; 3709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 3719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 3729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#endif 3749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: table sizes ok\n")); 3759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* get code length code lengths (not a typo) */ 3779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->have = 0; 3789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (state->have < state->ncode) { 3799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project NEEDBITS(3); 3809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->lens[order[state->have++]] = (unsigned short)BITS(3); 3819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(3); 3829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (state->have < 19) 3849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->lens[order[state->have++]] = 0; 3859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->next = state->codes; 3869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->lencode = (code const FAR *)(state->next); 3879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->lenbits = 7; 3889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = inflate_table(CODES, state->lens, 19, &(state->next), 3899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project &(state->lenbits), state->work); 3909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret) { 3919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid code lengths set"; 3929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 3939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 3949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 3959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: code lengths ok\n")); 3969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 3979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* get length and distance code code lengths */ 3989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->have = 0; 3999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (state->have < state->nlen + state->ndist) { 4009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project for (;;) { 401381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes here = state->lencode[BITS(state->lenbits)]; 402381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if ((unsigned)(here.bits) <= bits) break; 4039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project PULLBYTE(); 4049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 405381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (here.val < 16) { 406381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes DROPBITS(here.bits); 407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->lens[state->have++] = here.val; 4089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project else { 410381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (here.val == 16) { 411381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEEDBITS(here.bits + 2); 412381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes DROPBITS(here.bits); 4139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state->have == 0) { 4149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid bit length repeat"; 4159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 4169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 4179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project len = (unsigned)(state->lens[state->have - 1]); 4199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project copy = 3 + BITS(2); 4209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(2); 4219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 422381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes else if (here.val == 17) { 423381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEEDBITS(here.bits + 3); 424381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes DROPBITS(here.bits); 4259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project len = 0; 4269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project copy = 3 + BITS(3); 4279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(3); 4289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project else { 430381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes NEEDBITS(here.bits + 7); 431381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes DROPBITS(here.bits); 4329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project len = 0; 4339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project copy = 11 + BITS(7); 4349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(7); 4359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state->have + copy > state->nlen + state->ndist) { 4379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid bit length repeat"; 4389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 4399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 4409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project while (copy--) 4429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->lens[state->have++] = (unsigned short)len; 4439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* handle error breaks in while */ 4479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state->mode == BAD) break; 4489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 449381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* check for end-of-block code (better have one) */ 450381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (state->lens[256] == 0) { 451381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes strm->msg = (char *)"invalid code -- missing end-of-block"; 452381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->mode = BAD; 453381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes break; 454381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes } 455381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 456381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* build code tables -- note: do not change the lenbits or distbits 457381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes values here (9 and 6) without reading the comments in inftrees.h 458381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes concerning the ENOUGH constants, which depend on those values */ 4599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->next = state->codes; 4609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->lencode = (code const FAR *)(state->next); 4619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->lenbits = 9; 4629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), 4639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project &(state->lenbits), state->work); 4649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret) { 4659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid literal/lengths set"; 4669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 4679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 4689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->distcode = (code const FAR *)(state->next); 4709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->distbits = 6; 4719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, 4729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project &(state->next), &(state->distbits), state->work); 4739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret) { 4749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid distances set"; 4759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 4769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 4779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: codes ok\n")); 4799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = LEN; 4809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case LEN: 4829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* use inflate_fast() if we have enough input and output */ 4839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (have >= 6 && left >= 258) { 4849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project RESTORE(); 4859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state->whave < state->wsize) 4869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->whave = state->wsize - left; 4879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inflate_fast(strm, state->wsize); 4889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project LOAD(); 4899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 4909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 4919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 4929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* get a literal, length, or end-of-block code */ 4939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project for (;;) { 494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes here = state->lencode[BITS(state->lenbits)]; 495381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if ((unsigned)(here.bits) <= bits) break; 4969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project PULLBYTE(); 4979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 498381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (here.op && (here.op & 0xf0) == 0) { 499381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes last = here; 5009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project for (;;) { 501381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes here = state->lencode[last.val + 5029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project (BITS(last.bits + last.op) >> last.bits)]; 503381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if ((unsigned)(last.bits + here.bits) <= bits) break; 5049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project PULLBYTE(); 5059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(last.bits); 5079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 508381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes DROPBITS(here.bits); 509381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->length = (unsigned)here.val; 5109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 5119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* process literal */ 512381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (here.op == 0) { 513381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? 5149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project "inflate: literal '%c'\n" : 515381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes "inflate: literal 0x%02x\n", here.val)); 5169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ROOM(); 5179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *put++ = (unsigned char)(state->length); 5189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left--; 5199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = LEN; 5209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 5219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 5239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* process end of block */ 524381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (here.op & 32) { 5259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracevv((stderr, "inflate: end of block\n")); 5269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = TYPE; 5279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 5289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 5309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* invalid code */ 531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (here.op & 64) { 5329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid literal/length code"; 5339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 5349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 5359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 5379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* length code -- get extra bits, if any */ 538381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->extra = (unsigned)(here.op) & 15; 5399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state->extra != 0) { 5409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project NEEDBITS(state->extra); 5419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->length += BITS(state->extra); 5429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(state->extra); 5439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracevv((stderr, "inflate: length %u\n", state->length)); 5459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 5469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* get distance code */ 5479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project for (;;) { 548381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes here = state->distcode[BITS(state->distbits)]; 549381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if ((unsigned)(here.bits) <= bits) break; 5509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project PULLBYTE(); 5519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 552381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if ((here.op & 0xf0) == 0) { 553381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes last = here; 5549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project for (;;) { 555381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes here = state->distcode[last.val + 5569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project (BITS(last.bits + last.op) >> last.bits)]; 557381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if ((unsigned)(last.bits + here.bits) <= bits) break; 5589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project PULLBYTE(); 5599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(last.bits); 5619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 562381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes DROPBITS(here.bits); 563381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes if (here.op & 64) { 5649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid distance code"; 5659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 5669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 5679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 568381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->offset = (unsigned)here.val; 5699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 5709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* get distance extra bits, if any */ 571381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes state->extra = (unsigned)(here.op) & 15; 5729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state->extra != 0) { 5739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project NEEDBITS(state->extra); 5749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->offset += BITS(state->extra); 5759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project DROPBITS(state->extra); 5769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (state->offset > state->wsize - (state->whave < state->wsize ? 5789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left : 0)) { 5799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->msg = (char *)"invalid distance too far back"; 5809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->mode = BAD; 5819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 5829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracevv((stderr, "inflate: distance %u\n", state->offset)); 5849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 5859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* copy match from window to output */ 5869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 5879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ROOM(); 5889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project copy = state->wsize - state->offset; 5899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (copy < left) { 5909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project from = put + copy; 5919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project copy = left - copy; 5929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project else { 5949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project from = put - state->offset; 5959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project copy = left; 5969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 5979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (copy > state->length) copy = state->length; 5989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project state->length -= copy; 5999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project left -= copy; 6009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 6019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project *put++ = *from++; 6029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (--copy); 6039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (state->length != 0); 6049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 6059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 6069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case DONE: 6079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* inflate stream terminated properly -- write leftover output */ 6089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = Z_STREAM_END; 6099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (left < state->wsize) { 6109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (out(out_desc, state->window, state->wsize - left)) 6119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = Z_BUF_ERROR; 6129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 6139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project goto inf_leave; 6149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 6159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case BAD: 6169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = Z_DATA_ERROR; 6179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project goto inf_leave; 6189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 6199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project default: /* can't happen, but makes compilers happy */ 6209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = Z_STREAM_ERROR; 6219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project goto inf_leave; 6229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 6239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 6249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* Return unused input */ 6259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inf_leave: 6269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->next_in = next; 6279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->avail_in = have; 6289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return ret; 6299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 6309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 6319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint ZEXPORT inflateBackEnd(strm) 6329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectz_streamp strm; 6339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 6349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) 6359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_STREAM_ERROR; 6369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ZFREE(strm, strm->state); 6379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm->state = Z_NULL; 6389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Tracev((stderr, "inflate: end\n")); 6399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_OK; 6409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 641