Rizin
unix-like reverse engineering framework and cli tools
inffast.c File Reference
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"

Go to the source code of this file.

Functions

void ZLIB_INTERNAL inflate_fast (z_streamp strm, unsigned start)
 

Function Documentation

◆ inflate_fast()

void ZLIB_INTERNAL inflate_fast ( z_streamp  strm,
unsigned  start 
)

Definition at line 50 of file inffast.c.

53 {
54  struct inflate_state FAR *state;
55  z_const unsigned char FAR *in; /* local strm->next_in */
56  z_const unsigned char FAR *last; /* have enough input while in < last */
57  unsigned char FAR *out; /* local strm->next_out */
58  unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
59  unsigned char FAR *end; /* while out < end, enough space available */
60 #ifdef INFLATE_STRICT
61  unsigned dmax; /* maximum distance from zlib header */
62 #endif
63  unsigned wsize; /* window size or zero if not using window */
64  unsigned whave; /* valid bytes in the window */
65  unsigned wnext; /* window write index */
66  unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
67  unsigned long hold; /* local strm->hold */
68  unsigned bits; /* local strm->bits */
69  code const FAR *lcode; /* local strm->lencode */
70  code const FAR *dcode; /* local strm->distcode */
71  unsigned lmask; /* mask for first level of length codes */
72  unsigned dmask; /* mask for first level of distance codes */
73  code const *here; /* retrieved table entry */
74  unsigned op; /* code bits, operation, extra bits, or */
75  /* window position, window bytes to copy */
76  unsigned len; /* match length, unused bytes */
77  unsigned dist; /* match distance */
78  unsigned char FAR *from; /* where to copy match from */
79 
80  /* copy state to local variables */
81  state = (struct inflate_state FAR *)strm->state;
82  in = strm->next_in;
83  last = in + (strm->avail_in - 5);
84  out = strm->next_out;
85  beg = out - (start - strm->avail_out);
86  end = out + (strm->avail_out - 257);
87 #ifdef INFLATE_STRICT
88  dmax = state->dmax;
89 #endif
90  wsize = state->wsize;
91  whave = state->whave;
92  wnext = state->wnext;
93  window = state->window;
94  hold = state->hold;
95  bits = state->bits;
96  lcode = state->lencode;
97  dcode = state->distcode;
98  lmask = (1U << state->lenbits) - 1;
99  dmask = (1U << state->distbits) - 1;
100 
101  /* decode literals and length/distances until end-of-block or not enough
102  input data or output space */
103  do {
104  if (bits < 15) {
105  hold += (unsigned long)(*in++) << bits;
106  bits += 8;
107  hold += (unsigned long)(*in++) << bits;
108  bits += 8;
109  }
110  here = lcode + (hold & lmask);
111  dolen:
112  op = (unsigned)(here->bits);
113  hold >>= op;
114  bits -= op;
115  op = (unsigned)(here->op);
116  if (op == 0) { /* literal */
117  Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
118  "inflate: literal '%c'\n" :
119  "inflate: literal 0x%02x\n", here->val));
120  *out++ = (unsigned char)(here->val);
121  }
122  else if (op & 16) { /* length base */
123  len = (unsigned)(here->val);
124  op &= 15; /* number of extra bits */
125  if (op) {
126  if (bits < op) {
127  hold += (unsigned long)(*in++) << bits;
128  bits += 8;
129  }
130  len += (unsigned)hold & ((1U << op) - 1);
131  hold >>= op;
132  bits -= op;
133  }
134  Tracevv((stderr, "inflate: length %u\n", len));
135  if (bits < 15) {
136  hold += (unsigned long)(*in++) << bits;
137  bits += 8;
138  hold += (unsigned long)(*in++) << bits;
139  bits += 8;
140  }
141  here = dcode + (hold & dmask);
142  dodist:
143  op = (unsigned)(here->bits);
144  hold >>= op;
145  bits -= op;
146  op = (unsigned)(here->op);
147  if (op & 16) { /* distance base */
148  dist = (unsigned)(here->val);
149  op &= 15; /* number of extra bits */
150  if (bits < op) {
151  hold += (unsigned long)(*in++) << bits;
152  bits += 8;
153  if (bits < op) {
154  hold += (unsigned long)(*in++) << bits;
155  bits += 8;
156  }
157  }
158  dist += (unsigned)hold & ((1U << op) - 1);
159 #ifdef INFLATE_STRICT
160  if (dist > dmax) {
161  strm->msg = (char *)"invalid distance too far back";
162  state->mode = BAD;
163  break;
164  }
165 #endif
166  hold >>= op;
167  bits -= op;
168  Tracevv((stderr, "inflate: distance %u\n", dist));
169  op = (unsigned)(out - beg); /* max distance in output */
170  if (dist > op) { /* see if copy from window */
171  op = dist - op; /* distance back in window */
172  if (op > whave) {
173  if (state->sane) {
174  strm->msg =
175  (char *)"invalid distance too far back";
176  state->mode = BAD;
177  break;
178  }
179 #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
180  if (len <= op - whave) {
181  do {
182  *out++ = 0;
183  } while (--len);
184  continue;
185  }
186  len -= op - whave;
187  do {
188  *out++ = 0;
189  } while (--op > whave);
190  if (op == 0) {
191  from = out - dist;
192  do {
193  *out++ = *from++;
194  } while (--len);
195  continue;
196  }
197 #endif
198  }
199  from = window;
200  if (wnext == 0) { /* very common case */
201  from += wsize - op;
202  if (op < len) { /* some from window */
203  len -= op;
204  do {
205  *out++ = *from++;
206  } while (--op);
207  from = out - dist; /* rest from output */
208  }
209  }
210  else if (wnext < op) { /* wrap around window */
211  from += wsize + wnext - op;
212  op -= wnext;
213  if (op < len) { /* some from end of window */
214  len -= op;
215  do {
216  *out++ = *from++;
217  } while (--op);
218  from = window;
219  if (wnext < len) { /* some from start of window */
220  op = wnext;
221  len -= op;
222  do {
223  *out++ = *from++;
224  } while (--op);
225  from = out - dist; /* rest from output */
226  }
227  }
228  }
229  else { /* contiguous in window */
230  from += wnext - op;
231  if (op < len) { /* some from window */
232  len -= op;
233  do {
234  *out++ = *from++;
235  } while (--op);
236  from = out - dist; /* rest from output */
237  }
238  }
239  while (len > 2) {
240  *out++ = *from++;
241  *out++ = *from++;
242  *out++ = *from++;
243  len -= 3;
244  }
245  if (len) {
246  *out++ = *from++;
247  if (len > 1)
248  *out++ = *from++;
249  }
250  }
251  else {
252  from = out - dist; /* copy direct from output */
253  do { /* minimum length is three */
254  *out++ = *from++;
255  *out++ = *from++;
256  *out++ = *from++;
257  len -= 3;
258  } while (len > 2);
259  if (len) {
260  *out++ = *from++;
261  if (len > 1)
262  *out++ = *from++;
263  }
264  }
265  }
266  else if ((op & 64) == 0) { /* 2nd level distance code */
267  here = dcode + here->val + (hold & ((1U << op) - 1));
268  goto dodist;
269  }
270  else {
271  strm->msg = (char *)"invalid distance code";
272  state->mode = BAD;
273  break;
274  }
275  }
276  else if ((op & 64) == 0) { /* 2nd level length code */
277  here = lcode + here->val + (hold & ((1U << op) - 1));
278  goto dolen;
279  }
280  else if (op & 32) { /* end-of-block */
281  Tracevv((stderr, "inflate: end of block\n"));
282  state->mode = TYPE;
283  break;
284  }
285  else {
286  strm->msg = (char *)"invalid literal/length code";
287  state->mode = BAD;
288  break;
289  }
290  } while (in < last && out < end);
291 
292  /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
293  len = bits >> 3;
294  in -= len;
295  bits -= len << 3;
296  hold &= (1U << bits) - 1;
297 
298  /* update state and return */
299  strm->next_in = in;
300  strm->next_out = out;
301  strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
302  strm->avail_out = (unsigned)(out < end ?
303  257 + (end - out) : 257 - (out - end));
304  state->hold = hold;
305  state->bits = bits;
306  return;
307 }
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
int bits(struct state *s, int need)
Definition: blast.c:72
const lzma_allocator const uint8_t * in
Definition: block.h:527
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags long
Definition: sflib.h:79
static lzma_stream strm
Definition: full_flush.c:20
@ TYPE
Definition: inflate9.h:13
static void struct sockaddr socklen_t static fromlen static backlog static fork char char char static envp int struct rusage static rusage struct utsname static buf struct sembuf unsigned
Definition: sflib.h:97
#define BAD
Definition: regex2.h:141
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
Definition: inftree9.h:24
unsigned char op
Definition: inftree9.h:25
unsigned char bits
Definition: inftree9.h:26
unsigned short val
Definition: inftree9.h:27
unsigned wnext
Definition: inflate.h:99
unsigned long hold
Definition: inflate.h:102
unsigned whave
Definition: inflate.h:98
unsigned wsize
Definition: inflate.h:97
unsigned dmax
Definition: inflate.h:91
uint8_t * next_out
Definition: base.h:490
size_t avail_out
Definition: base.h:491
const uint8_t * next_in
Definition: base.h:486
size_t avail_in
Definition: base.h:487
Definition: dis.h:43
Definition: dis.c:32
struct _window window
#define z_const
Definition: zconf.h:237
#define FAR
Definition: zconf.h:387
#define Tracevv(x)
Definition: zutil.h:254

References lzma_stream::avail_in, lzma_stream::avail_out, BAD, bits(), code::bits, inflate_state::dmax, test_evm::end, FAR, from, inflate_state::hold, in, inflate_state::last, len, long, lzma_stream::next_in, lzma_stream::next_out, op, code::op, out, start, strm, Tracevv, TYPE, unsigned, code::val, inflate_state::whave, inflate_state::wnext, inflate_state::wsize, and z_const.

Referenced by inflate(), and inflateBack().