aboutsummaryrefslogtreecommitdiff
path: root/uncompr.c
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2014-04-26 08:04:09 -0700
committerMark Adler <madler@alumni.caltech.edu>2014-04-26 08:08:25 -0700
commit7d54c69413ed2275b9ea25b376627294ffac5ca8 (patch)
tree215ba1d8599e9f637a89e16b4b3ddec43a405035 /uncompr.c
parentf898bbed8991fb2220940d19d70803cc68697b60 (diff)
downloadzlib-7d54c69413ed2275b9ea25b376627294ffac5ca8.tar.gz
zlib-7d54c69413ed2275b9ea25b376627294ffac5ca8.tar.bz2
zlib-7d54c69413ed2275b9ea25b376627294ffac5ca8.zip
Fix uncompress() to work on lengths more than a maximum unsigned.
Diffstat (limited to 'uncompr.c')
-rw-r--r--uncompr.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/uncompr.c b/uncompr.c
index 242e949..2ec3eba 100644
--- a/uncompr.c
+++ b/uncompr.c
@@ -1,5 +1,5 @@
1/* uncompr.c -- decompress a memory buffer 1/* uncompr.c -- decompress a memory buffer
2 * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. 2 * Copyright (C) 1995-2003, 2010, 2014 Jean-loup Gailly, Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h 3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */ 4 */
5 5
@@ -19,7 +19,8 @@
19 19
20 uncompress returns Z_OK if success, Z_MEM_ERROR if there was not 20 uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
21 enough memory, Z_BUF_ERROR if there was not enough room in the output 21 enough memory, Z_BUF_ERROR if there was not enough room in the output
22 buffer, or Z_DATA_ERROR if the input data was corrupted. 22 buffer, or Z_DATA_ERROR if the input data was corrupted, including if the
23 input data is an incomplete zlib stream.
23*/ 24*/
24int ZEXPORT uncompress (dest, destLen, source, sourceLen) 25int ZEXPORT uncompress (dest, destLen, source, sourceLen)
25 Bytef *dest; 26 Bytef *dest;
@@ -29,31 +30,51 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen)
29{ 30{
30 z_stream stream; 31 z_stream stream;
31 int err; 32 int err;
33 const uInt max = -1;
34 uLong left;
35 Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
32 36
33 stream.next_in = (z_const Bytef *)source; 37 if (*destLen) {
34 stream.avail_in = (uInt)sourceLen; 38 left = *destLen;
35 /* Check for source > 64K on 16-bit machine: */ 39 *destLen = 0;
36 if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; 40 }
37 41 else {
38 stream.next_out = dest; 42 left = 1;
39 stream.avail_out = (uInt)*destLen; 43 dest = buf;
40 if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; 44 }
41 45
46 stream.next_in = (z_const Bytef *)source;
47 stream.avail_in = 0;
42 stream.zalloc = (alloc_func)0; 48 stream.zalloc = (alloc_func)0;
43 stream.zfree = (free_func)0; 49 stream.zfree = (free_func)0;
50 stream.opaque = (voidpf)0;
44 51
45 err = inflateInit(&stream); 52 err = inflateInit(&stream);
46 if (err != Z_OK) return err; 53 if (err != Z_OK) return err;
47 54
48 err = inflate(&stream, Z_FINISH); 55 stream.next_out = dest;
49 if (err != Z_STREAM_END) { 56 stream.avail_out = 0;
50 inflateEnd(&stream); 57
51 if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) 58 do {
52 return Z_DATA_ERROR; 59 if (stream.avail_out == 0) {
53 return err; 60 stream.avail_out = left > (uLong)max ? max : (uInt)left;
54 } 61 left -= stream.avail_out;
55 *destLen = stream.total_out; 62 }
63 if (stream.avail_in == 0) {
64 stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
65 sourceLen -= stream.avail_in;
66 }
67 err = inflate(&stream, Z_NO_FLUSH);
68 } while (err == Z_OK);
69
70 if (dest != buf)
71 *destLen = stream.total_out;
72 else if (stream.total_out && err == Z_BUF_ERROR)
73 left = 1;
56 74
57 err = inflateEnd(&stream); 75 inflateEnd(&stream);
58 return err; 76 return err == Z_STREAM_END ? Z_OK :
77 err == Z_NEED_DICT ? Z_DATA_ERROR :
78 err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
79 err;
59} 80}