diff options
Diffstat (limited to 'inflate.c')
-rw-r--r-- | inflate.c | 204 |
1 files changed, 130 insertions, 74 deletions
@@ -15,38 +15,63 @@ struct internal_state { | |||
15 | enum { | 15 | enum { |
16 | METHOD, /* waiting for method byte */ | 16 | METHOD, /* waiting for method byte */ |
17 | FLAG, /* waiting for flag byte */ | 17 | FLAG, /* waiting for flag byte */ |
18 | START, /* make new blocks state */ | ||
19 | BLOCKS, /* decompressing blocks */ | 18 | BLOCKS, /* decompressing blocks */ |
20 | CHECK4, /* four check bytes to go */ | 19 | CHECK4, /* four check bytes to go */ |
21 | CHECK3, /* three check bytes to go */ | 20 | CHECK3, /* three check bytes to go */ |
22 | CHECK2, /* two check bytes to go */ | 21 | CHECK2, /* two check bytes to go */ |
23 | CHECK1, /* one check byte to go */ | 22 | CHECK1, /* one check byte to go */ |
24 | DONE, /* finished check, done */ | 23 | DONE, /* finished check, done */ |
25 | INF_ERROR}/* got an error--stay here */ | 24 | BAD} /* got an error--stay here */ |
26 | mode; /* current inflate mode */ | 25 | mode; /* current inflate mode */ |
27 | 26 | ||
28 | /* mode dependent information */ | 27 | /* mode dependent information */ |
29 | union { | 28 | union { |
30 | uInt method; /* if FLAGS, method byte */ | 29 | uInt method; /* if FLAGS, method byte */ |
31 | struct inflate_blocks_state | ||
32 | *blocks; /* if BLOCKS, current state */ | ||
33 | struct { | 30 | struct { |
34 | uLong was; /* computed check value */ | 31 | uLong was; /* computed check value */ |
35 | uLong need; /* stream check value */ | 32 | uLong need; /* stream check value */ |
36 | } check; /* if CHECK, check values to compare */ | 33 | } check; /* if CHECK, check values to compare */ |
34 | uInt marker; /* if BAD, inflateSync's marker bytes count */ | ||
37 | } sub; /* submode */ | 35 | } sub; /* submode */ |
38 | 36 | ||
39 | /* mode independent information */ | 37 | /* mode independent information */ |
40 | int nowrap; /* flag for no wrapper */ | 38 | int nowrap; /* flag for no wrapper */ |
41 | uInt wbits; /* log2(window size) (8..15, defaults to 15) */ | 39 | uInt wbits; /* log2(window size) (8..15, defaults to 15) */ |
40 | struct inflate_blocks_state | ||
41 | *blocks; /* current inflate_blocks state */ | ||
42 | 42 | ||
43 | }; | 43 | }; |
44 | 44 | ||
45 | 45 | ||
46 | int inflateInit(z) | 46 | int inflateReset(z) |
47 | z_stream *z; | 47 | z_stream *z; |
48 | { | 48 | { |
49 | return inflateInit2(z, WBITS); | 49 | uLong c; |
50 | |||
51 | if (z == Z_NULL || z->state == Z_NULL) | ||
52 | return Z_STREAM_ERROR; | ||
53 | z->total_in = z->total_out = 0; | ||
54 | z->msg = Z_NULL; | ||
55 | z->state->mode = z->state->nowrap ? BLOCKS : METHOD; | ||
56 | inflate_blocks_reset(z->state->blocks, z, &c); | ||
57 | Trace((stderr, "inflate: reset\n")); | ||
58 | return Z_OK; | ||
59 | } | ||
60 | |||
61 | |||
62 | int inflateEnd(z) | ||
63 | z_stream *z; | ||
64 | { | ||
65 | uLong c; | ||
66 | |||
67 | if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) | ||
68 | return Z_STREAM_ERROR; | ||
69 | if (z->state->blocks != Z_NULL) | ||
70 | inflate_blocks_free(z->state->blocks, z, &c); | ||
71 | ZFREE(z, z->state); | ||
72 | z->state = Z_NULL; | ||
73 | Trace((stderr, "inflate: end\n")); | ||
74 | return Z_OK; | ||
50 | } | 75 | } |
51 | 76 | ||
52 | 77 | ||
@@ -59,12 +84,10 @@ int w; | |||
59 | return Z_STREAM_ERROR; | 84 | return Z_STREAM_ERROR; |
60 | if (z->zalloc == Z_NULL) z->zalloc = zcalloc; | 85 | if (z->zalloc == Z_NULL) z->zalloc = zcalloc; |
61 | if (z->zfree == Z_NULL) z->zfree = zcfree; | 86 | if (z->zfree == Z_NULL) z->zfree = zcfree; |
62 | z->total_in = z->total_out = 0; | ||
63 | z->msg = Z_NULL; | ||
64 | if ((z->state = (struct internal_state *) | 87 | if ((z->state = (struct internal_state *) |
65 | ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) | 88 | ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) |
66 | return Z_MEM_ERROR; | 89 | return Z_MEM_ERROR; |
67 | z->state->mode = METHOD; | 90 | z->state->blocks = Z_NULL; |
68 | 91 | ||
69 | /* handle undocumented nowrap option (no zlib header or check) */ | 92 | /* handle undocumented nowrap option (no zlib header or check) */ |
70 | z->state->nowrap = 0; | 93 | z->state->nowrap = 0; |
@@ -72,7 +95,6 @@ int w; | |||
72 | { | 95 | { |
73 | w = - w; | 96 | w = - w; |
74 | z->state->nowrap = 1; | 97 | z->state->nowrap = 1; |
75 | z->state->mode = START; | ||
76 | } | 98 | } |
77 | 99 | ||
78 | /* set window size */ | 100 | /* set window size */ |
@@ -81,20 +103,40 @@ int w; | |||
81 | inflateEnd(z); | 103 | inflateEnd(z); |
82 | return Z_STREAM_ERROR; | 104 | return Z_STREAM_ERROR; |
83 | } | 105 | } |
84 | z->state->wbits = w; | 106 | z->state->wbits = (uInt)w; |
107 | |||
108 | /* create inflate_blocks state */ | ||
109 | if ((z->state->blocks = | ||
110 | inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w)) | ||
111 | == Z_NULL) | ||
112 | { | ||
113 | inflateEnd(z); | ||
114 | return Z_MEM_ERROR; | ||
115 | } | ||
116 | Trace((stderr, "inflate: allocated\n")); | ||
117 | |||
118 | /* reset state */ | ||
119 | inflateReset(z); | ||
85 | return Z_OK; | 120 | return Z_OK; |
86 | } | 121 | } |
87 | 122 | ||
88 | 123 | ||
124 | int inflateInit(z) | ||
125 | z_stream *z; | ||
126 | { | ||
127 | return inflateInit2(z, DEF_WBITS); | ||
128 | } | ||
129 | |||
130 | |||
131 | #define NEEDBYTE {if(z->avail_in==0)return r;r=Z_OK;} | ||
89 | #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) | 132 | #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) |
90 | 133 | ||
91 | int inflate(z, f) | 134 | int inflate(z, f) |
92 | z_stream *z; | 135 | z_stream *z; |
93 | int f; | 136 | int f; |
94 | { | 137 | { |
95 | int r = f; /* to avoid warning about unused f */ | 138 | int r = f; /* to avoid warning about unused f */ |
96 | uInt b; | 139 | uInt b; |
97 | uLong c; | ||
98 | 140 | ||
99 | if (z == Z_NULL || z->next_in == Z_NULL) | 141 | if (z == Z_NULL || z->next_in == Z_NULL) |
100 | return Z_STREAM_ERROR; | 142 | return Z_STREAM_ERROR; |
@@ -102,77 +144,86 @@ int f; | |||
102 | while (1) switch (z->state->mode) | 144 | while (1) switch (z->state->mode) |
103 | { | 145 | { |
104 | case METHOD: | 146 | case METHOD: |
105 | if (z->avail_in == 0) return r; r = Z_OK; | 147 | NEEDBYTE |
106 | if (((z->state->sub.method = NEXTBYTE) & 0xf != DEFLATED)) | 148 | if (((z->state->sub.method = NEXTBYTE) & 0xf != DEFLATED)) |
107 | { | 149 | { |
108 | z->state->mode = INF_ERROR; | 150 | z->state->mode = BAD; |
109 | z->msg = "unknown compression method"; | 151 | z->msg = "unknown compression method"; |
110 | return Z_DATA_ERROR; | 152 | z->state->sub.marker = 5; /* can't try inflateSync */ |
153 | break; | ||
111 | } | 154 | } |
112 | if ((z->state->sub.method >> 4) + 8 > z->state->wbits) | 155 | if ((z->state->sub.method >> 4) + 8 > z->state->wbits) |
113 | { | 156 | { |
114 | z->state->mode = INF_ERROR; | 157 | z->state->mode = BAD; |
115 | z->msg = "invalid window size"; | 158 | z->msg = "invalid window size"; |
116 | return Z_DATA_ERROR; | 159 | z->state->sub.marker = 5; /* can't try inflateSync */ |
160 | break; | ||
117 | } | 161 | } |
118 | z->state->mode = FLAG; | 162 | z->state->mode = FLAG; |
119 | case FLAG: | 163 | case FLAG: |
120 | if (z->avail_in == 0) return r; r = Z_OK; | 164 | NEEDBYTE |
121 | if ((b = NEXTBYTE) & 0x20) | 165 | if ((b = NEXTBYTE) & 0x20) |
122 | { | 166 | { |
123 | z->state->mode = INF_ERROR; | 167 | z->state->mode = BAD; |
124 | z->msg = "invalid reserved bit"; | 168 | z->msg = "invalid reserved bit"; |
125 | return Z_DATA_ERROR; | 169 | z->state->sub.marker = 5; /* can't try inflateSync */ |
170 | break; | ||
126 | } | 171 | } |
127 | if (((z->state->sub.method << 8) + b) % 31) | 172 | if (((z->state->sub.method << 8) + b) % 31) |
128 | { | 173 | { |
129 | z->state->mode = INF_ERROR; | 174 | z->state->mode = BAD; |
130 | z->msg = "incorrect header check"; | 175 | z->msg = "incorrect header check"; |
131 | return Z_DATA_ERROR; | 176 | z->state->sub.marker = 5; /* can't try inflateSync */ |
177 | break; | ||
132 | } | 178 | } |
133 | z->state->mode = START; | 179 | Trace((stderr, "inflate: zlib header ok\n")); |
134 | case START: | ||
135 | if ((z->state->sub.blocks = inflate_blocks_new(z, | ||
136 | z->state->nowrap ? Z_NULL : adler32, | ||
137 | 1<< z->state->wbits)) == Z_NULL) | ||
138 | return Z_MEM_ERROR; | ||
139 | z->state->mode = BLOCKS; | 180 | z->state->mode = BLOCKS; |
140 | case BLOCKS: | 181 | case BLOCKS: |
141 | if ((r = inflate_blocks(z->state->sub.blocks, z, r)) != Z_STREAM_END) | 182 | r = inflate_blocks(z->state->blocks, z, r); |
142 | return r; | 183 | if (r == Z_DATA_ERROR) |
143 | inflate_blocks_free(z->state->sub.blocks, z, &c); | 184 | { |
185 | z->state->mode = BAD; | ||
186 | z->state->sub.marker = 0; /* can try inflateSync */ | ||
187 | break; | ||
188 | } | ||
189 | if (r != Z_STREAM_END) | ||
190 | return r; | ||
191 | r = Z_OK; | ||
192 | inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); | ||
144 | if (z->state->nowrap) | 193 | if (z->state->nowrap) |
145 | { | 194 | { |
146 | z->state->mode = DONE; | 195 | z->state->mode = DONE; |
147 | break; | 196 | break; |
148 | } | 197 | } |
149 | z->state->sub.check.was = c; | ||
150 | z->state->mode = CHECK4; | 198 | z->state->mode = CHECK4; |
151 | case CHECK4: | 199 | case CHECK4: |
152 | if (z->avail_in == 0) return r; r = Z_OK; | 200 | NEEDBYTE |
153 | z->state->sub.check.need = (uLong)NEXTBYTE << 24; | 201 | z->state->sub.check.need = (uLong)NEXTBYTE << 24; |
154 | z->state->mode = CHECK3; | 202 | z->state->mode = CHECK3; |
155 | case CHECK3: | 203 | case CHECK3: |
156 | if (z->avail_in == 0) return r; r = Z_OK; | 204 | NEEDBYTE |
157 | z->state->sub.check.need += (uLong)NEXTBYTE << 16; | 205 | z->state->sub.check.need += (uLong)NEXTBYTE << 16; |
158 | z->state->mode = CHECK2; | 206 | z->state->mode = CHECK2; |
159 | case CHECK2: | 207 | case CHECK2: |
160 | if (z->avail_in == 0) return r; r = Z_OK; | 208 | NEEDBYTE |
161 | z->state->sub.check.need += (uLong)NEXTBYTE << 8; | 209 | z->state->sub.check.need += (uLong)NEXTBYTE << 8; |
162 | z->state->mode = CHECK1; | 210 | z->state->mode = CHECK1; |
163 | case CHECK1: | 211 | case CHECK1: |
164 | if (z->avail_in == 0) return r; r = Z_OK; | 212 | NEEDBYTE |
165 | z->state->sub.check.need += (uLong)NEXTBYTE; | 213 | z->state->sub.check.need += (uLong)NEXTBYTE; |
214 | |||
166 | if (z->state->sub.check.was != z->state->sub.check.need) | 215 | if (z->state->sub.check.was != z->state->sub.check.need) |
167 | { | 216 | { |
168 | z->state->mode = INF_ERROR; | 217 | z->state->mode = BAD; |
169 | z->msg = "incorrect data check"; | 218 | z->msg = "incorrect data check"; |
170 | return Z_DATA_ERROR; | 219 | z->state->sub.marker = 5; /* can't try inflateSync */ |
220 | break; | ||
171 | } | 221 | } |
222 | Trace((stderr, "inflate: zlib check ok\n")); | ||
172 | z->state->mode = DONE; | 223 | z->state->mode = DONE; |
173 | case DONE: | 224 | case DONE: |
174 | return Z_STREAM_END; | 225 | return Z_STREAM_END; |
175 | case INF_ERROR: | 226 | case BAD: |
176 | return Z_DATA_ERROR; | 227 | return Z_DATA_ERROR; |
177 | default: | 228 | default: |
178 | return Z_STREAM_ERROR; | 229 | return Z_STREAM_ERROR; |
@@ -180,41 +231,46 @@ int f; | |||
180 | } | 231 | } |
181 | 232 | ||
182 | 233 | ||
183 | int inflateEnd(z) | 234 | int inflateSync(z) |
184 | z_stream *z; | 235 | z_stream *z; |
185 | { | 236 | { |
186 | uLong c; | 237 | uInt n; /* number of bytes to look at */ |
238 | Byte *p; /* pointer to bytes */ | ||
239 | uInt m; /* number of marker bytes found in a row */ | ||
240 | uLong r, w; /* temporaries to save total_in and total_out */ | ||
187 | 241 | ||
188 | if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) | 242 | /* set up */ |
243 | if (z == Z_NULL || z->state == Z_NULL) | ||
189 | return Z_STREAM_ERROR; | 244 | return Z_STREAM_ERROR; |
190 | if (z->state->mode == BLOCKS) | 245 | if (z->state->mode != BAD) |
191 | inflate_blocks_free(z->state->sub.blocks, z, &c); | 246 | z->state->sub.marker = 0; |
192 | ZFREE(z, z->state); | 247 | if ((n = z->avail_in) == 0) |
193 | z->state = Z_NULL; | 248 | return Z_BUF_ERROR; |
194 | return Z_OK; | 249 | p = z->next_in; |
195 | } | 250 | m = z->state->sub.marker; |
196 | |||
197 | |||
198 | /* inflateSync not implemented yet--this just consumes input */ | ||
199 | int inflateSync(z) | ||
200 | z_stream *z; | ||
201 | { | ||
202 | if (z == Z_NULL) return Z_STREAM_ERROR; | ||
203 | if (z->avail_in == 0) return Z_BUF_ERROR; | ||
204 | do { | ||
205 | z->total_in++; | ||
206 | } while (--z->avail_in); | ||
207 | return Z_DATA_ERROR; | ||
208 | } | ||
209 | 251 | ||
252 | /* search */ | ||
253 | while (n && m < 4) | ||
254 | { | ||
255 | if (*p == (m < 2 ? 0 : 0xff)) | ||
256 | m++; | ||
257 | else if (*p || m > 2) | ||
258 | m = 0; | ||
259 | p++, n--; | ||
260 | } | ||
210 | 261 | ||
211 | /* inflateReset not fully implemented yet--this frees and reallocates */ | 262 | /* restore */ |
212 | int inflateReset(z) | 263 | z->total_in += p - z->next_in; |
213 | z_stream *z; | 264 | z->next_in = p; |
214 | { | 265 | z->avail_in = n; |
215 | int r; | 266 | z->state->sub.marker = m; |
216 | 267 | ||
217 | if ((r = inflateEnd(z)) != Z_OK) | 268 | /* return no joy or set up to restart on a new block */ |
218 | return r; | 269 | if (m != 4) |
219 | return inflateInit(z); | 270 | return Z_DATA_ERROR; |
271 | r = z->total_in; w = z->total_out; | ||
272 | inflateReset(z); | ||
273 | z->total_in = r; z->total_out = w; | ||
274 | z->state->mode = BLOCKS; | ||
275 | return Z_OK; | ||
220 | } | 276 | } |