Skip to content

Commit fbbde8a

Browse files
committed
Accomodate very long headers
1 parent 491c355 commit fbbde8a

File tree

2 files changed

+20
-22
lines changed

2 files changed

+20
-22
lines changed

src/isal/isal_zlibmodule.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,13 +1295,10 @@ GzipReader__new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
12951295
args, kwargs, format, keywords, &fp, &buffer_size)) {
12961296
return NULL;
12971297
}
1298-
if (buffer_size < 16) {
1299-
// Necessary to distinguish between truncated headers and headers
1300-
// which are too big. A header is at least 10 bytes, but may contain
1301-
// more depending on flags.
1298+
if (buffer_size < 1) {
13021299
PyErr_Format(
13031300
PyExc_ValueError,
1304-
"buffersize must be at least 16, got %zd", buffer_size
1301+
"buffersize must be at least 1, got %zd", buffer_size
13051302
);
13061303
return NULL;
13071304
}
@@ -1336,25 +1333,29 @@ GzipReader__new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
13361333

13371334
static inline ssize_t GzipReader_read_from_file(GzipReader *self)
13381335
{
1339-
uint8_t *input_buffer = self->input_buffer;
1336+
13401337
uint8_t *current_pos = self->current_pos;
13411338
uint8_t *buffer_end = self->buffer_end;
13421339
size_t remaining = buffer_end - current_pos;
1343-
if (remaining > 0) {
1344-
memmove(input_buffer, current_pos, remaining);
1340+
if (remaining == self->buffer_size) {
1341+
/* Buffer is full but a new read request was issued. This will be due
1342+
to the header being bigger than the header. Enlarge the buffer
1343+
to accommodate the hzip header. */
1344+
size_t new_buffer_size = self->buffer_size * 2;
1345+
uint8_t *tmp_buffer = PyMem_Realloc(self->input_buffer, new_buffer_size);
1346+
if (tmp_buffer == NULL) {
1347+
PyErr_NoMemory();
1348+
return -1;
1349+
}
1350+
self->input_buffer = tmp_buffer;
1351+
self->buffer_size = new_buffer_size;
1352+
} else if (remaining > 0) {
1353+
memmove(self->input_buffer, current_pos, remaining);
13451354
}
1355+
uint8_t *input_buffer = self->input_buffer;
13461356
current_pos = input_buffer;
13471357
buffer_end = input_buffer + remaining;
13481358
size_t read_in_size = self->buffer_size - remaining;
1349-
if (read_in_size == 0) {
1350-
// The buffer is already full of data but the current position could not
1351-
// progress. This happens when the header is too large.
1352-
PyErr_Format(
1353-
PyExc_OverflowError,
1354-
"header does not fit into buffer of size %zu",
1355-
self->buffer_size);
1356-
return -1;
1357-
}
13581359
PyObject *bufview = PyMemoryView_FromMemory(
13591360
(char *)buffer_end, read_in_size, MEMORYVIEW_READINTO_FLAGS);
13601361
if (bufview == NULL) {

tests/test_igzip.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,11 +447,8 @@ def test_very_long_header_in_file():
447447
b"\x00")
448448
compressed = header + isal_zlib.compress(b"", 3, -15) + 8 * b"\00"
449449
f = io.BytesIO(compressed)
450-
with pytest.raises(OverflowError) as error:
451-
with igzip.open(f, "rb") as gzip_file:
452-
gzip_file.read()
453-
error.match(
454-
f"header does not fit into buffer of size {igzip.READ_BUFFER_SIZE}")
450+
with igzip.open(f) as gzip_file:
451+
assert gzip_file.read() == b""
455452

456453

457454
def test_concatenated_gzip():

0 commit comments

Comments
 (0)