xref: /PHP-7.2/ext/zip/lib/zip_source_deflate.c (revision 9e0cc7a1)
1 /*
2   zip_source_deflate.c -- deflate (de)compressoin routines
3   Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner
4 
5   This file is part of libzip, a library to manipulate ZIP archives.
6   The authors can be contacted at <libzip@nih.at>
7 
8   Redistribution and use in source and binary forms, with or without
9   modification, are permitted provided that the following conditions
10   are met:
11   1. Redistributions of source code must retain the above copyright
12      notice, this list of conditions and the following disclaimer.
13   2. Redistributions in binary form must reproduce the above copyright
14      notice, this list of conditions and the following disclaimer in
15      the documentation and/or other materials provided with the
16      distribution.
17   3. The names of the authors may not be used to endorse or promote
18      products derived from this software without specific prior
19      written permission.
20 
21   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 #include <stdlib.h>
35 #include <string.h>
36 #include <limits.h>
37 
38 #include "zipint.h"
39 
40 struct deflate {
41     zip_error_t error;
42 
43     bool eof;
44     bool can_store;
45     bool is_stored;
46     int mem_level;
47     zip_uint64_t size;
48     zip_uint8_t buffer[BUFSIZE];
49     z_stream zstr;
50 };
51 
52 static zip_int64_t compress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t);
53 static zip_int64_t decompress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t);
54 static zip_int64_t deflate_compress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
55 static zip_int64_t deflate_decompress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
56 static void deflate_free(struct deflate *);
57 
58 
59 zip_source_t *
zip_source_deflate(zip_t * za,zip_source_t * src,zip_int32_t cm,int flags)60 zip_source_deflate(zip_t *za, zip_source_t *src, zip_int32_t cm, int flags)
61 {
62     struct deflate *ctx;
63     zip_source_t *s2;
64 
65     if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) {
66 	zip_error_set(&za->error, ZIP_ER_INVAL, 0);
67 	return NULL;
68     }
69 
70     if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) {
71 	zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
72 	return NULL;
73     }
74 
75     zip_error_init(&ctx->error);
76     ctx->eof = false;
77     ctx->is_stored = false;
78     ctx->can_store = ZIP_CM_IS_DEFAULT(cm);
79     if (flags & ZIP_CODEC_ENCODE) {
80 	ctx->mem_level = MAX_MEM_LEVEL;
81     }
82 
83     if ((s2=zip_source_layered(za, src,
84 			       ((flags & ZIP_CODEC_ENCODE)
85 				? deflate_compress : deflate_decompress),
86 			       ctx)) == NULL) {
87 	deflate_free(ctx);
88 	return NULL;
89     }
90 
91     return s2;
92 }
93 
94 
95 static zip_int64_t
compress_read(zip_source_t * src,struct deflate * ctx,void * data,zip_uint64_t len)96 compress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
97 {
98     int end, ret;
99     zip_int64_t n;
100     zip_uint64_t out_offset;
101     uInt out_len;
102 
103     if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
104 	return -1;
105 
106     if (len == 0 || ctx->is_stored) {
107 	return 0;
108     }
109 
110     out_offset = 0;
111     out_len = (uInt)ZIP_MIN(UINT_MAX, len);
112     ctx->zstr.next_out = (Bytef *)data;
113     ctx->zstr.avail_out = out_len;
114 
115     end = 0;
116     while (!end) {
117 	ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);
118 
119 	switch (ret) {
120         case Z_STREAM_END:
121             if (ctx->can_store && ctx->zstr.total_in <= ctx->zstr.total_out) {
122                 ctx->is_stored = true;
123                 ctx->size = ctx->zstr.total_in;
124                 memcpy(data, ctx->buffer, ctx->size);
125                 return (zip_int64_t)ctx->size;
126             }
127             /* fallthrough */
128 	case Z_OK:
129 	    /* all ok */
130 
131 	    if (ctx->zstr.avail_out == 0) {
132 		out_offset += out_len;
133 		if (out_offset < len) {
134 		    out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
135 		    ctx->zstr.next_out = (Bytef *)data+out_offset;
136 		    ctx->zstr.avail_out = out_len;
137 		}
138 		else {
139                     ctx->can_store = false;
140 		    end = 1;
141 		}
142 	    }
143 	    else if (ctx->eof && ctx->zstr.avail_in == 0)
144 		end = 1;
145 	    break;
146 
147 	case Z_BUF_ERROR:
148 	    if (ctx->zstr.avail_in == 0) {
149 		if (ctx->eof) {
150 		    end = 1;
151 		    break;
152 		}
153 
154 		if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
155                     _zip_error_set_from_source(&ctx->error, src);
156 		    end = 1;
157 		    break;
158 		}
159 		else if (n == 0) {
160 		    ctx->eof = true;
161 		    /* TODO: check against stat of src? */
162 		    ctx->size = ctx->zstr.total_in;
163 		}
164 		else {
165                     if (ctx->zstr.total_in > 0) {
166                         /* we overwrote a previously filled ctx->buffer */
167                         ctx->can_store = false;
168                     }
169 		    ctx->zstr.next_in = (Bytef *)ctx->buffer;
170 		    ctx->zstr.avail_in = (uInt)n;
171 		}
172 		continue;
173 	    }
174 	    /* fallthrough */
175 	case Z_NEED_DICT:
176 	case Z_DATA_ERROR:
177 	case Z_STREAM_ERROR:
178 	case Z_MEM_ERROR:
179             zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
180 
181 	    end = 1;
182 	    break;
183 	}
184     }
185 
186     if (ctx->zstr.avail_out < len) {
187 	ctx->can_store = false;
188 	return (zip_int64_t)(len - ctx->zstr.avail_out);
189     }
190 
191     return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
192 }
193 
194 
195 static zip_int64_t
decompress_read(zip_source_t * src,struct deflate * ctx,void * data,zip_uint64_t len)196 decompress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
197 {
198     int end, ret;
199     zip_int64_t n;
200     zip_uint64_t out_offset;
201     uInt out_len;
202 
203     if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
204 	return -1;
205 
206     if (len == 0)
207 	return 0;
208 
209     out_offset = 0;
210     out_len = (uInt)ZIP_MIN(UINT_MAX, len);
211     ctx->zstr.next_out = (Bytef *)data;
212     ctx->zstr.avail_out = out_len;
213 
214     end = 0;
215     while (!end) {
216 	ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
217 
218 	switch (ret) {
219 	case Z_OK:
220 	    if (ctx->zstr.avail_out == 0) {
221 		out_offset += out_len;
222 		if (out_offset < len) {
223 		    out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
224 		    ctx->zstr.next_out = (Bytef *)data+out_offset;
225 		    ctx->zstr.avail_out = out_len;
226 		}
227 		else {
228 		    end = 1;
229 		}
230 	    }
231 	    break;
232 
233 	case Z_STREAM_END:
234 	    ctx->eof = 1;
235 	    end = 1;
236 	    break;
237 
238 	case Z_BUF_ERROR:
239 	    if (ctx->zstr.avail_in == 0) {
240 		if (ctx->eof) {
241 		    end = 1;
242 		    break;
243 		}
244 
245 		if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
246                     _zip_error_set_from_source(&ctx->error, src);
247 		    end = 1;
248 		    break;
249 		}
250 		else if (n == 0) {
251 		    ctx->eof = 1;
252 		}
253 		else {
254 		    ctx->zstr.next_in = (Bytef *)ctx->buffer;
255 		    ctx->zstr.avail_in = (uInt)n;
256 		}
257 		continue;
258 	    }
259 	    /* fallthrough */
260 	case Z_NEED_DICT:
261 	case Z_DATA_ERROR:
262 	case Z_STREAM_ERROR:
263 	case Z_MEM_ERROR:
264             zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
265 	    end = 1;
266 	    break;
267 	}
268     }
269 
270     if (ctx->zstr.avail_out < len)
271 	return (zip_int64_t)(len - ctx->zstr.avail_out);
272 
273     return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
274 }
275 
276 
277 static zip_int64_t
deflate_compress(zip_source_t * src,void * ud,void * data,zip_uint64_t len,zip_source_cmd_t cmd)278 deflate_compress(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
279 {
280     struct deflate *ctx;
281     int ret;
282 
283     ctx = (struct deflate *)ud;
284 
285     switch (cmd) {
286     case ZIP_SOURCE_OPEN:
287 	ctx->zstr.zalloc = Z_NULL;
288 	ctx->zstr.zfree = Z_NULL;
289 	ctx->zstr.opaque = NULL;
290 	ctx->zstr.avail_in = 0;
291 	ctx->zstr.next_in = NULL;
292 	ctx->zstr.avail_out = 0;
293 	ctx->zstr.next_out = NULL;
294 
295 	/* negative value to tell zlib not to write a header */
296 	if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY)) != Z_OK) {
297             zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
298 	    return -1;
299 	}
300 
301 	return 0;
302 
303     case ZIP_SOURCE_READ:
304 	return compress_read(src, ctx, data, len);
305 
306     case ZIP_SOURCE_CLOSE:
307 	deflateEnd(&ctx->zstr);
308 	return 0;
309 
310     case ZIP_SOURCE_STAT:
311     	{
312 	    zip_stat_t *st;
313 
314 	    st = (zip_stat_t *)data;
315 
316 	    st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_DEFLATE;
317 	    st->valid |= ZIP_STAT_COMP_METHOD;
318 	    if (ctx->eof) {
319 		st->comp_size = ctx->size;
320 		st->valid |= ZIP_STAT_COMP_SIZE;
321 	    }
322 	    else
323 		st->valid &= ~ZIP_STAT_COMP_SIZE;
324 	}
325 	return 0;
326 
327     case ZIP_SOURCE_ERROR:
328         return zip_error_to_data(&ctx->error, data, len);
329 
330     case ZIP_SOURCE_FREE:
331 	deflate_free(ctx);
332 	return 0;
333 
334     case ZIP_SOURCE_SUPPORTS:
335         return ZIP_SOURCE_SUPPORTS_READABLE;
336 
337     default:
338         zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
339 	return -1;
340     }
341 }
342 
343 
344 static zip_int64_t
deflate_decompress(zip_source_t * src,void * ud,void * data,zip_uint64_t len,zip_source_cmd_t cmd)345 deflate_decompress(zip_source_t *src, void *ud, void *data,
346 		   zip_uint64_t len, zip_source_cmd_t cmd)
347 {
348     struct deflate *ctx;
349     zip_int64_t n;
350     int ret;
351 
352     ctx = (struct deflate *)ud;
353 
354     switch (cmd) {
355         case ZIP_SOURCE_OPEN:
356             if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
357                 _zip_error_set_from_source(&ctx->error, src);
358                 return -1;
359             }
360 
361             ctx->zstr.zalloc = Z_NULL;
362             ctx->zstr.zfree = Z_NULL;
363             ctx->zstr.opaque = NULL;
364             ctx->zstr.next_in = (Bytef *)ctx->buffer;
365             ctx->zstr.avail_in = (uInt)n;
366 
367             /* negative value to tell zlib that there is no header */
368             if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
369                 zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
370                 return -1;
371             }
372             return 0;
373 
374         case ZIP_SOURCE_READ:
375             return decompress_read(src, ctx, data, len);
376 
377         case ZIP_SOURCE_CLOSE:
378             inflateEnd(&ctx->zstr);
379             return 0;
380 
381         case ZIP_SOURCE_STAT:
382         {
383             zip_stat_t *st;
384 
385             st = (zip_stat_t *)data;
386 
387             st->comp_method = ZIP_CM_STORE;
388             if (st->comp_size > 0 && st->size > 0)
389                 st->comp_size = st->size;
390 
391             return 0;
392         }
393 
394         case ZIP_SOURCE_ERROR:
395             return zip_error_to_data(&ctx->error, data, len);
396 
397         case ZIP_SOURCE_FREE:
398             free(ctx);
399             return 0;
400 
401         case ZIP_SOURCE_SUPPORTS:
402             return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
403 
404         default:
405             zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
406             return -1;
407     }
408 }
409 
410 
411 static void
deflate_free(struct deflate * ctx)412 deflate_free(struct deflate *ctx)
413 {
414     free(ctx);
415 }
416