Skip to content

Commit

Permalink
lib-compress: Fix assert-crash when .gz header size exceeds buffer ma…
Browse files Browse the repository at this point in the history
…x 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)
  • Loading branch information
sirainen committed Feb 17, 2017
1 parent ea6a744 commit e72d13f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/lib-compression/istream-zlib.c
Expand Up @@ -81,6 +81,11 @@ static int i_stream_zlib_read_header(struct istream_private *stream)
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;
Expand Down
41 changes: 41 additions & 0 deletions src/lib-compression/test-compression.c
Expand Up @@ -7,6 +7,7 @@
#include "sha1.h"
#include "randgen.h"
#include "test-common.h"
#include "istream-zlib.h"
#include "compression.h"

#include <unistd.h>
Expand Down Expand Up @@ -159,6 +160,45 @@ static void test_gz_no_concat(void)
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;
Expand Down Expand Up @@ -249,6 +289,7 @@ int main(int argc, char *argv[])
test_compression,
test_gz_concat,
test_gz_no_concat,
test_gz_large_header,
NULL
};
if (argc == 2) {
Expand Down

0 comments on commit e72d13f

Please sign in to comment.