Mercurial > dovecot > core-2.2
changeset 21527:09c06f63c8c4
lib-compress: Fix assert-crash when .gz header size exceeds buffer max length
Instead treat the stream as corrupted and return EINVAL.
Fixes:
Panic: file istream.c: line 182 (i_stream_read): assertion failed: (_stream->skip != _stream->pos)
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Mon, 13 Feb 2017 18:05:13 +0200 |
parents | 6109df9e091b |
children | a9b6b316b9a5 |
files | src/lib-compression/istream-zlib.c src/lib-compression/test-compression.c |
diffstat | 2 files changed, 46 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-compression/istream-zlib.c Fri Feb 10 15:27:13 2017 +0200 +++ b/src/lib-compression/istream-zlib.c Mon Feb 13 18:05:13 2017 +0200 @@ -81,6 +81,11 @@ zlib_read_error(zstream, "missing gz trailer"); stream->istream.stream_errno = EINVAL; } + if (ret == -2) { + zlib_read_error(zstream, "gz header is too large"); + stream->istream.stream_errno = EINVAL; + ret = -1; + } return ret; } zstream->prev_size = size;
--- a/src/lib-compression/test-compression.c Fri Feb 10 15:27:13 2017 +0200 +++ b/src/lib-compression/test-compression.c Mon Feb 13 18:05:13 2017 +0200 @@ -7,6 +7,7 @@ #include "sha1.h" #include "randgen.h" #include "test-common.h" +#include "istream-zlib.h" #include "compression.h" #include <unistd.h> @@ -159,6 +160,45 @@ test_end(); } +static void test_gz_large_header(void) +{ + static const unsigned char gz_input[] = { + 0x1f, 0x8b, 0x08, 0x08, + 'a','a','a','a','a','a','a','a','a','a','a', + 0 + }; + struct istream *file_input, *input; + size_t i; + + test_begin("gz large header"); + + /* max buffer size smaller than gz header */ + for (i = 1; i < sizeof(gz_input); i++) { + file_input = test_istream_create_data(gz_input, sizeof(gz_input)); + test_istream_set_size(file_input, i); + test_istream_set_max_buffer_size(file_input, i); + + input = i_stream_create_gz(file_input, FALSE); + test_assert_idx(i_stream_read(input) == 0, i); + test_assert_idx(i_stream_read(input) == -1 && + input->stream_errno == EINVAL, i); + i_stream_unref(&input); + i_stream_unref(&file_input); + } + + /* max buffer size is exactly the gz header */ + file_input = test_istream_create_data(gz_input, sizeof(gz_input)); + input = i_stream_create_gz(file_input, FALSE); + test_istream_set_size(input, i); + test_istream_set_allow_eof(input, FALSE); + test_istream_set_max_buffer_size(input, i); + test_assert(i_stream_read(input) == 0); + i_stream_unref(&input); + i_stream_unref(&file_input); + + test_end(); +} + static void test_uncompress_file(const char *path) { const struct compression_handler *handler; @@ -249,6 +289,7 @@ test_compression, test_gz_concat, test_gz_no_concat, + test_gz_large_header, NULL }; if (argc == 2) {