00001
00002
00003
00004
00005
00006 #include "zutil.h"
00007 #include "inftrees.h"
00008 #include "inflate.h"
00009 #include "inffast.h"
00010
00011 #ifndef ASMINF
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef POSTINC
00025 # define OFF 0
00026 # define PUP(a) *(a)++
00027 #else
00028 # define OFF 1
00029 # define PUP(a) *++(a)
00030 #endif
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 void ZLIB_INTERNAL inflate_fast(strm, start)
00068 z_streamp strm;
00069 unsigned start;
00070 {
00071 struct inflate_state FAR *state;
00072 unsigned char FAR *in;
00073 unsigned char FAR *last;
00074 unsigned char FAR *out;
00075 unsigned char FAR *beg;
00076 unsigned char FAR *end;
00077 #ifdef INFLATE_STRICT
00078 unsigned dmax;
00079 #endif
00080 unsigned wsize;
00081 unsigned whave;
00082 unsigned wnext;
00083 unsigned char FAR *window;
00084 unsigned long hold;
00085 unsigned bits;
00086 code const FAR *lcode;
00087 code const FAR *dcode;
00088 unsigned lmask;
00089 unsigned dmask;
00090 code here;
00091 unsigned op;
00092
00093 unsigned len;
00094 unsigned dist;
00095 unsigned char FAR *from;
00096
00097
00098 state = (struct inflate_state FAR *)strm->state;
00099 in = strm->next_in - OFF;
00100 last = in + (strm->avail_in - 5);
00101 out = strm->next_out - OFF;
00102 beg = out - (start - strm->avail_out);
00103 end = out + (strm->avail_out - 257);
00104 #ifdef INFLATE_STRICT
00105 dmax = state->dmax;
00106 #endif
00107 wsize = state->wsize;
00108 whave = state->whave;
00109 wnext = state->wnext;
00110 window = state->window;
00111 hold = state->hold;
00112 bits = state->bits;
00113 lcode = state->lencode;
00114 dcode = state->distcode;
00115 lmask = (1U << state->lenbits) - 1;
00116 dmask = (1U << state->distbits) - 1;
00117
00118
00119
00120 do {
00121 if (bits < 15) {
00122 hold += (unsigned long)(PUP(in)) << bits;
00123 bits += 8;
00124 hold += (unsigned long)(PUP(in)) << bits;
00125 bits += 8;
00126 }
00127 here = lcode[hold & lmask];
00128 dolen:
00129 op = (unsigned)(here.bits);
00130 hold >>= op;
00131 bits -= op;
00132 op = (unsigned)(here.op);
00133 if (op == 0) {
00134 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
00135 "inflate: literal '%c'\n" :
00136 "inflate: literal 0x%02x\n", here.val));
00137 PUP(out) = (unsigned char)(here.val);
00138 }
00139 else if (op & 16) {
00140 len = (unsigned)(here.val);
00141 op &= 15;
00142 if (op) {
00143 if (bits < op) {
00144 hold += (unsigned long)(PUP(in)) << bits;
00145 bits += 8;
00146 }
00147 len += (unsigned)hold & ((1U << op) - 1);
00148 hold >>= op;
00149 bits -= op;
00150 }
00151 Tracevv((stderr, "inflate: length %u\n", len));
00152 if (bits < 15) {
00153 hold += (unsigned long)(PUP(in)) << bits;
00154 bits += 8;
00155 hold += (unsigned long)(PUP(in)) << bits;
00156 bits += 8;
00157 }
00158 here = dcode[hold & dmask];
00159 dodist:
00160 op = (unsigned)(here.bits);
00161 hold >>= op;
00162 bits -= op;
00163 op = (unsigned)(here.op);
00164 if (op & 16) {
00165 dist = (unsigned)(here.val);
00166 op &= 15;
00167 if (bits < op) {
00168 hold += (unsigned long)(PUP(in)) << bits;
00169 bits += 8;
00170 if (bits < op) {
00171 hold += (unsigned long)(PUP(in)) << bits;
00172 bits += 8;
00173 }
00174 }
00175 dist += (unsigned)hold & ((1U << op) - 1);
00176 #ifdef INFLATE_STRICT
00177 if (dist > dmax) {
00178 strm->msg = (char *)"invalid distance too far back";
00179 state->mode = BAD;
00180 break;
00181 }
00182 #endif
00183 hold >>= op;
00184 bits -= op;
00185 Tracevv((stderr, "inflate: distance %u\n", dist));
00186 op = (unsigned)(out - beg);
00187 if (dist > op) {
00188 op = dist - op;
00189 if (op > whave) {
00190 if (state->sane) {
00191 strm->msg =
00192 (char *)"invalid distance too far back";
00193 state->mode = BAD;
00194 break;
00195 }
00196 #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
00197 if (len <= op - whave) {
00198 do {
00199 PUP(out) = 0;
00200 } while (--len);
00201 continue;
00202 }
00203 len -= op - whave;
00204 do {
00205 PUP(out) = 0;
00206 } while (--op > whave);
00207 if (op == 0) {
00208 from = out - dist;
00209 do {
00210 PUP(out) = PUP(from);
00211 } while (--len);
00212 continue;
00213 }
00214 #endif
00215 }
00216 from = window - OFF;
00217 if (wnext == 0) {
00218 from += wsize - op;
00219 if (op < len) {
00220 len -= op;
00221 do {
00222 PUP(out) = PUP(from);
00223 } while (--op);
00224 from = out - dist;
00225 }
00226 }
00227 else if (wnext < op) {
00228 from += wsize + wnext - op;
00229 op -= wnext;
00230 if (op < len) {
00231 len -= op;
00232 do {
00233 PUP(out) = PUP(from);
00234 } while (--op);
00235 from = window - OFF;
00236 if (wnext < len) {
00237 op = wnext;
00238 len -= op;
00239 do {
00240 PUP(out) = PUP(from);
00241 } while (--op);
00242 from = out - dist;
00243 }
00244 }
00245 }
00246 else {
00247 from += wnext - op;
00248 if (op < len) {
00249 len -= op;
00250 do {
00251 PUP(out) = PUP(from);
00252 } while (--op);
00253 from = out - dist;
00254 }
00255 }
00256 while (len > 2) {
00257 PUP(out) = PUP(from);
00258 PUP(out) = PUP(from);
00259 PUP(out) = PUP(from);
00260 len -= 3;
00261 }
00262 if (len) {
00263 PUP(out) = PUP(from);
00264 if (len > 1)
00265 PUP(out) = PUP(from);
00266 }
00267 }
00268 else {
00269 from = out - dist;
00270 do {
00271 PUP(out) = PUP(from);
00272 PUP(out) = PUP(from);
00273 PUP(out) = PUP(from);
00274 len -= 3;
00275 } while (len > 2);
00276 if (len) {
00277 PUP(out) = PUP(from);
00278 if (len > 1)
00279 PUP(out) = PUP(from);
00280 }
00281 }
00282 }
00283 else if ((op & 64) == 0) {
00284 here = dcode[here.val + (hold & ((1U << op) - 1))];
00285 goto dodist;
00286 }
00287 else {
00288 strm->msg = (char *)"invalid distance code";
00289 state->mode = BAD;
00290 break;
00291 }
00292 }
00293 else if ((op & 64) == 0) {
00294 here = lcode[here.val + (hold & ((1U << op) - 1))];
00295 goto dolen;
00296 }
00297 else if (op & 32) {
00298 Tracevv((stderr, "inflate: end of block\n"));
00299 state->mode = TYPE;
00300 break;
00301 }
00302 else {
00303 strm->msg = (char *)"invalid literal/length code";
00304 state->mode = BAD;
00305 break;
00306 }
00307 } while (in < last && out < end);
00308
00309
00310 len = bits >> 3;
00311 in -= len;
00312 bits -= len << 3;
00313 hold &= (1U << bits) - 1;
00314
00315
00316 strm->next_in = in + OFF;
00317 strm->next_out = out + OFF;
00318 strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
00319 strm->avail_out = (unsigned)(out < end ?
00320 257 + (end - out) : 257 - (out - end));
00321 state->hold = hold;
00322 state->bits = bits;
00323 return;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 #endif