File 004-Catch-buffer-overruns.patch of Package python-Pillow
From ab52630d0644e42a75eb88b78b9a9d7438a6fbeb Mon Sep 17 00:00:00 2001
From: Andrew Murray <radarhere@users.noreply.github.com>
Date: Mon, 30 Sep 2019 18:45:43 +1000
Subject: [PATCH] Catch buffer overruns
---
Tests/test_image.py | 9 +++++++++
src/libImaging/FliDecode.c | 14 +++++++++++---
src/libImaging/PcxDecode.c | 5 +++++
src/libImaging/SgiRleDecode.c | 5 +++++
4 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/Tests/test_image.py b/Tests/test_image.py
index 493b4735ac..47196a1394 100644
--- a/Tests/test_image.py
+++ b/Tests/test_image.py
@@ -534,6 +534,15 @@ def test_no_resource_warning_on_save(self):
with Image.open(test_file) as im:
self.assert_warning(None, im.save, temp_file)
+ def test_overrun(self):
+ for file in ["fli_overrun.bin", "sgi_overrun.bin", "pcx_overrun.bin"]:
+ im = Image.open(os.path.join("Tests/images", file))
+ try:
+ im.load()
+ self.assertFail()
+ except IOError as e:
+ self.assertEqual(str(e), "buffer overrun when reading image file")
+
class MockEncoder(object):
pass
diff --git a/src/libImaging/FliDecode.c b/src/libImaging/FliDecode.c
index e21259900e..5f4485f890 100644
--- a/src/libImaging/FliDecode.c
+++ b/src/libImaging/FliDecode.c
@@ -30,7 +30,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
{
UINT8* ptr;
int framesize;
- int c, chunks;
+ int c, chunks, advance;
int l, lines;
int i, j, x = 0, y, ymax;
@@ -59,10 +59,16 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
chunks = I16(ptr+6);
ptr += 16;
+ bytes -= 16;
/* Process subchunks */
for (c = 0; c < chunks; c++) {
- UINT8 *data = ptr + 6;
+ UINT8* data;
+ if (bytes < 10) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+ data = ptr + 6;
switch (I16(ptr+4)) {
case 4: case 11:
/* FLI COLOR chunk */
@@ -198,7 +204,9 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
state->errcode = IMAGING_CODEC_UNKNOWN;
return -1;
}
- ptr += I32(ptr);
+ advance = I32(ptr);
+ ptr += advance;
+ bytes -= advance;
}
return -1; /* end of frame */
diff --git a/src/libImaging/PcxDecode.c b/src/libImaging/PcxDecode.c
index 4a5931bee7..67dcc1e085 100644
--- a/src/libImaging/PcxDecode.c
+++ b/src/libImaging/PcxDecode.c
@@ -22,6 +22,11 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
UINT8 n;
UINT8* ptr;
+ if (strcmp(im->mode, "1") == 0 && state->xsize > state->bytes * 8) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+
ptr = buf;
for (;;) {
diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c
index d8341f3e55..8a81ba8e6c 100644
--- a/src/libImaging/SgiRleDecode.c
+++ b/src/libImaging/SgiRleDecode.c
@@ -156,6 +156,11 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize];
c->rleoffset -= SGI_HEADER_SIZE;
+ if (c->rleoffset + c->rlelength > c->bufsize) {
+ state->errcode = IMAGING_CODEC_OVERRUN;
+ return -1;
+ }
+
/* row decompression */
if (c->bpc ==1) {
if(expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands))