Fix uncompress() to work on lengths more than a maximum unsigned.

pull/115/head
Mark Adler 11 years ago
parent f898bbed89
commit 7d54c69413
  1. 61
      uncompr.c

@ -1,5 +1,5 @@
/* uncompr.c -- decompress a memory buffer /* uncompr.c -- decompress a memory buffer
* Copyright (C) 1995-2003, 2010 Jean-loup Gailly. * Copyright (C) 1995-2003, 2010, 2014 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -19,7 +19,8 @@
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted. buffer, or Z_DATA_ERROR if the input data was corrupted, including if the
input data is an incomplete zlib stream.
*/ */
int ZEXPORT uncompress (dest, destLen, source, sourceLen) int ZEXPORT uncompress (dest, destLen, source, sourceLen)
Bytef *dest; Bytef *dest;
@ -29,31 +30,51 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen)
{ {
z_stream stream; z_stream stream;
int err; int err;
const uInt max = -1;
uLong left;
Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
stream.next_in = (z_const Bytef *)source; if (*destLen) {
stream.avail_in = (uInt)sourceLen; left = *destLen;
/* Check for source > 64K on 16-bit machine: */ *destLen = 0;
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; }
else {
stream.next_out = dest; left = 1;
stream.avail_out = (uInt)*destLen; dest = buf;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; }
stream.next_in = (z_const Bytef *)source;
stream.avail_in = 0;
stream.zalloc = (alloc_func)0; stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0; stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
err = inflateInit(&stream); err = inflateInit(&stream);
if (err != Z_OK) return err; if (err != Z_OK) return err;
err = inflate(&stream, Z_FINISH); stream.next_out = dest;
if (err != Z_STREAM_END) { stream.avail_out = 0;
inflateEnd(&stream);
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) do {
return Z_DATA_ERROR; if (stream.avail_out == 0) {
return err; stream.avail_out = left > (uLong)max ? max : (uInt)left;
} left -= stream.avail_out;
*destLen = stream.total_out; }
if (stream.avail_in == 0) {
stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
sourceLen -= stream.avail_in;
}
err = inflate(&stream, Z_NO_FLUSH);
} while (err == Z_OK);
if (dest != buf)
*destLen = stream.total_out;
else if (stream.total_out && err == Z_BUF_ERROR)
left = 1;
err = inflateEnd(&stream); inflateEnd(&stream);
return err; return err == Z_STREAM_END ? Z_OK :
err == Z_NEED_DICT ? Z_DATA_ERROR :
err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
err;
} }

Loading…
Cancel
Save