0001
0002
0003
0004
0005
0006 #include <linux/zutil.h>
0007 #include "inftrees.h"
0008 #include "inflate.h"
0009 #include "inffast.h"
0010
0011 #ifndef ASMINF
0012
0013 union uu {
0014 unsigned short us;
0015 unsigned char b[2];
0016 };
0017
0018
0019 static inline unsigned short
0020 get_unaligned16(const unsigned short *p)
0021 {
0022 union uu mm;
0023 unsigned char *b = (unsigned char *)p;
0024
0025 mm.b[0] = b[0];
0026 mm.b[1] = b[1];
0027 return mm.us;
0028 }
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 void inflate_fast(z_streamp strm, unsigned start)
0068 {
0069 struct inflate_state *state;
0070 const unsigned char *in;
0071 const unsigned char *last;
0072 unsigned char *out;
0073 unsigned char *beg;
0074 unsigned char *end;
0075 #ifdef INFLATE_STRICT
0076 unsigned dmax;
0077 #endif
0078 unsigned wsize;
0079 unsigned whave;
0080 unsigned write;
0081 unsigned char *window;
0082 unsigned long hold;
0083 unsigned bits;
0084 code const *lcode;
0085 code const *dcode;
0086 unsigned lmask;
0087 unsigned dmask;
0088 code this;
0089 unsigned op;
0090
0091 unsigned len;
0092 unsigned dist;
0093 unsigned char *from;
0094
0095
0096 state = (struct inflate_state *)strm->state;
0097 in = strm->next_in;
0098 last = in + (strm->avail_in - 5);
0099 out = strm->next_out;
0100 beg = out - (start - strm->avail_out);
0101 end = out + (strm->avail_out - 257);
0102 #ifdef INFLATE_STRICT
0103 dmax = state->dmax;
0104 #endif
0105 wsize = state->wsize;
0106 whave = state->whave;
0107 write = state->write;
0108 window = state->window;
0109 hold = state->hold;
0110 bits = state->bits;
0111 lcode = state->lencode;
0112 dcode = state->distcode;
0113 lmask = (1U << state->lenbits) - 1;
0114 dmask = (1U << state->distbits) - 1;
0115
0116
0117
0118 do {
0119 if (bits < 15) {
0120 hold += (unsigned long)(*in++) << bits;
0121 bits += 8;
0122 hold += (unsigned long)(*in++) << bits;
0123 bits += 8;
0124 }
0125 this = lcode[hold & lmask];
0126 dolen:
0127 op = (unsigned)(this.bits);
0128 hold >>= op;
0129 bits -= op;
0130 op = (unsigned)(this.op);
0131 if (op == 0) {
0132 *out++ = (unsigned char)(this.val);
0133 }
0134 else if (op & 16) {
0135 len = (unsigned)(this.val);
0136 op &= 15;
0137 if (op) {
0138 if (bits < op) {
0139 hold += (unsigned long)(*in++) << bits;
0140 bits += 8;
0141 }
0142 len += (unsigned)hold & ((1U << op) - 1);
0143 hold >>= op;
0144 bits -= op;
0145 }
0146 if (bits < 15) {
0147 hold += (unsigned long)(*in++) << bits;
0148 bits += 8;
0149 hold += (unsigned long)(*in++) << bits;
0150 bits += 8;
0151 }
0152 this = dcode[hold & dmask];
0153 dodist:
0154 op = (unsigned)(this.bits);
0155 hold >>= op;
0156 bits -= op;
0157 op = (unsigned)(this.op);
0158 if (op & 16) {
0159 dist = (unsigned)(this.val);
0160 op &= 15;
0161 if (bits < op) {
0162 hold += (unsigned long)(*in++) << bits;
0163 bits += 8;
0164 if (bits < op) {
0165 hold += (unsigned long)(*in++) << bits;
0166 bits += 8;
0167 }
0168 }
0169 dist += (unsigned)hold & ((1U << op) - 1);
0170 #ifdef INFLATE_STRICT
0171 if (dist > dmax) {
0172 strm->msg = (char *)"invalid distance too far back";
0173 state->mode = BAD;
0174 break;
0175 }
0176 #endif
0177 hold >>= op;
0178 bits -= op;
0179 op = (unsigned)(out - beg);
0180 if (dist > op) {
0181 op = dist - op;
0182 if (op > whave) {
0183 strm->msg = (char *)"invalid distance too far back";
0184 state->mode = BAD;
0185 break;
0186 }
0187 from = window;
0188 if (write == 0) {
0189 from += wsize - op;
0190 if (op < len) {
0191 len -= op;
0192 do {
0193 *out++ = *from++;
0194 } while (--op);
0195 from = out - dist;
0196 }
0197 }
0198 else if (write < op) {
0199 from += wsize + write - op;
0200 op -= write;
0201 if (op < len) {
0202 len -= op;
0203 do {
0204 *out++ = *from++;
0205 } while (--op);
0206 from = window;
0207 if (write < len) {
0208 op = write;
0209 len -= op;
0210 do {
0211 *out++ = *from++;
0212 } while (--op);
0213 from = out - dist;
0214 }
0215 }
0216 }
0217 else {
0218 from += write - op;
0219 if (op < len) {
0220 len -= op;
0221 do {
0222 *out++ = *from++;
0223 } while (--op);
0224 from = out - dist;
0225 }
0226 }
0227 while (len > 2) {
0228 *out++ = *from++;
0229 *out++ = *from++;
0230 *out++ = *from++;
0231 len -= 3;
0232 }
0233 if (len) {
0234 *out++ = *from++;
0235 if (len > 1)
0236 *out++ = *from++;
0237 }
0238 }
0239 else {
0240 unsigned short *sout;
0241 unsigned long loops;
0242
0243 from = out - dist;
0244
0245
0246 if (!((long)(out - 1) & 1)) {
0247 *out++ = *from++;
0248 len--;
0249 }
0250 sout = (unsigned short *)(out);
0251 if (dist > 2) {
0252 unsigned short *sfrom;
0253
0254 sfrom = (unsigned short *)(from);
0255 loops = len >> 1;
0256 do {
0257 if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
0258 *sout++ = *sfrom++;
0259 else
0260 *sout++ = get_unaligned16(sfrom++);
0261 } while (--loops);
0262 out = (unsigned char *)sout;
0263 from = (unsigned char *)sfrom;
0264 } else {
0265 unsigned short pat16;
0266
0267 pat16 = *(sout-1);
0268 if (dist == 1) {
0269 union uu mm;
0270
0271 mm.us = pat16;
0272 mm.b[0] = mm.b[1];
0273 pat16 = mm.us;
0274 }
0275 loops = len >> 1;
0276 do
0277 *sout++ = pat16;
0278 while (--loops);
0279 out = (unsigned char *)sout;
0280 }
0281 if (len & 1)
0282 *out++ = *from++;
0283 }
0284 }
0285 else if ((op & 64) == 0) {
0286 this = dcode[this.val + (hold & ((1U << op) - 1))];
0287 goto dodist;
0288 }
0289 else {
0290 strm->msg = (char *)"invalid distance code";
0291 state->mode = BAD;
0292 break;
0293 }
0294 }
0295 else if ((op & 64) == 0) {
0296 this = lcode[this.val + (hold & ((1U << op) - 1))];
0297 goto dolen;
0298 }
0299 else if (op & 32) {
0300 state->mode = TYPE;
0301 break;
0302 }
0303 else {
0304 strm->msg = (char *)"invalid literal/length code";
0305 state->mode = BAD;
0306 break;
0307 }
0308 } while (in < last && out < end);
0309
0310
0311 len = bits >> 3;
0312 in -= len;
0313 bits -= len << 3;
0314 hold &= (1U << bits) - 1;
0315
0316
0317 strm->next_in = in;
0318 strm->next_out = out;
0319 strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
0320 strm->avail_out = (unsigned)(out < end ?
0321 257 + (end - out) : 257 - (out - end));
0322 state->hold = hold;
0323 state->bits = bits;
0324 return;
0325 }
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341 #endif