diff options
author | Mark Adler <madler@alumni.caltech.edu> | 2014-04-26 08:04:09 -0700 |
---|---|---|
committer | Mark Adler <madler@alumni.caltech.edu> | 2014-04-26 08:08:25 -0700 |
commit | 7d54c69413ed2275b9ea25b376627294ffac5ca8 (patch) | |
tree | 215ba1d8599e9f637a89e16b4b3ddec43a405035 /uncompr.c | |
parent | f898bbed8991fb2220940d19d70803cc68697b60 (diff) | |
download | zlib-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.c | 61 |
1 files changed, 41 insertions, 20 deletions
@@ -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 | */ |
24 | int ZEXPORT uncompress (dest, destLen, source, sourceLen) | 25 | int 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 | } |