f5c1c7
From cc9658731ba1ea291f83ea959acc27ac28384a2c Mon Sep 17 00:00:00 2001
f5c1c7
From: Lumir Balhar <lbalhar@redhat.com>
f5c1c7
Date: Fri, 14 Feb 2020 11:14:53 +0100
f5c1c7
Subject: [PATCH] Combined fix for CVE-2020-5312 and CVE-2019-16865
f5c1c7
f5c1c7
---
f5c1c7
 src/PIL/GifImagePlugin.py     |  1 +
f5c1c7
 src/PIL/IcoImagePlugin.py     |  1 +
f5c1c7
 src/PIL/PsdImagePlugin.py     |  6 ++++--
f5c1c7
 src/PIL/TiffImagePlugin.py    |  4 ++--
f5c1c7
 src/libImaging/FliDecode.c    | 14 +++++++++++---
f5c1c7
 src/libImaging/PcxDecode.c    |  8 ++++++++
f5c1c7
 src/libImaging/RawDecode.c    | 11 +++++++++--
f5c1c7
 src/libImaging/SgiRleDecode.c |  5 +++++
f5c1c7
 8 files changed, 41 insertions(+), 9 deletions(-)
f5c1c7
f5c1c7
diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py
f5c1c7
index c01adff..99af4a5 100644
f5c1c7
--- a/src/PIL/GifImagePlugin.py
f5c1c7
+++ b/src/PIL/GifImagePlugin.py
f5c1c7
@@ -251,6 +251,7 @@ class GifImageFile(ImageFile.ImageFile):
f5c1c7
                 self.dispose = None
f5c1c7
             elif self.disposal_method == 2:
f5c1c7
                 # replace with background colour
f5c1c7
+                Image._decompression_bomb_check(self.size)
f5c1c7
                 self.dispose = Image.core.fill("P", self.size,
f5c1c7
                                                self.info["background"])
f5c1c7
             else:
f5c1c7
diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py
f5c1c7
index 428fdd4..2b6d1e0 100644
f5c1c7
--- a/src/PIL/IcoImagePlugin.py
f5c1c7
+++ b/src/PIL/IcoImagePlugin.py
f5c1c7
@@ -167,6 +167,7 @@ class IcoFile(object):
f5c1c7
         else:
f5c1c7
             # XOR + AND mask bmp frame
f5c1c7
             im = BmpImagePlugin.DibImageFile(self.buf)
f5c1c7
+            Image._decompression_bomb_check(im.size)
f5c1c7
 
f5c1c7
             # change tile dimension to only encompass XOR image
f5c1c7
             im.size = (im.size[0], int(im.size[1] / 2))
f5c1c7
diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py
f5c1c7
index f6e04f7..fe2a2ff 100644
f5c1c7
--- a/src/PIL/PsdImagePlugin.py
f5c1c7
+++ b/src/PIL/PsdImagePlugin.py
f5c1c7
@@ -209,9 +209,11 @@ def _layerinfo(file):
f5c1c7
         # skip over blend flags and extra information
f5c1c7
         filler = read(12)
f5c1c7
         name = ""
f5c1c7
-        size = i32(read(4))
f5c1c7
+        size = i32(read(4))  # length of the extra data field
f5c1c7
         combined = 0
f5c1c7
         if size:
f5c1c7
+            data_end = file.tell() + size
f5c1c7
+
f5c1c7
             length = i32(read(4))
f5c1c7
             if length:
f5c1c7
                 mask_y = i32(read(4))
f5c1c7
@@ -233,7 +235,7 @@ def _layerinfo(file):
f5c1c7
                 name = read(length).decode('latin-1', 'replace')
f5c1c7
             combined += length + 1
f5c1c7
 
f5c1c7
-        file.seek(size - combined, 1)
f5c1c7
+            file.seek(data_end)
f5c1c7
         layers.append((name, mode, (x0, y0, x1, y1)))
f5c1c7
 
f5c1c7
     # get tiles
f5c1c7
diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py
f5c1c7
index f903918..b9a1ef7 100644
f5c1c7
--- a/src/PIL/TiffImagePlugin.py
f5c1c7
+++ b/src/PIL/TiffImagePlugin.py
f5c1c7
@@ -1170,8 +1170,8 @@ class TiffImageFile(ImageFile.ImageFile):
f5c1c7
             print("- fill_order:", fillorder)
f5c1c7
 
f5c1c7
         # size
f5c1c7
-        xsize = self.tag_v2.get(IMAGEWIDTH)
f5c1c7
-        ysize = self.tag_v2.get(IMAGELENGTH)
f5c1c7
+        xsize = int(self.tag_v2.get(IMAGEWIDTH))
f5c1c7
+        ysize = int(self.tag_v2.get(IMAGELENGTH))
f5c1c7
         self.size = xsize, ysize
f5c1c7
 
f5c1c7
         if DEBUG:
f5c1c7
diff --git a/src/libImaging/FliDecode.c b/src/libImaging/FliDecode.c
f5c1c7
index 6d22c6c..a99aca8 100644
f5c1c7
--- a/src/libImaging/FliDecode.c
f5c1c7
+++ b/src/libImaging/FliDecode.c
f5c1c7
@@ -30,7 +30,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
f5c1c7
 {
f5c1c7
     UINT8* ptr;
f5c1c7
     int framesize;
f5c1c7
-    int c, chunks;
f5c1c7
+    int c, chunks, advance;
f5c1c7
     int l, lines;
f5c1c7
     int i, j, x = 0, y, ymax;
f5c1c7
 
f5c1c7
@@ -59,10 +59,16 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
f5c1c7
 
f5c1c7
     chunks = I16(ptr+6);
f5c1c7
     ptr += 16;
f5c1c7
+	bytes -= 16;
f5c1c7
 
f5c1c7
     /* Process subchunks */
f5c1c7
     for (c = 0; c < chunks; c++) {
f5c1c7
-	UINT8 *data = ptr + 6;
f5c1c7
+	UINT8* data;
f5c1c7
+	if (bytes < 10) {
f5c1c7
+	    state->errcode = IMAGING_CODEC_OVERRUN;
f5c1c7
+	    return -1;
f5c1c7
+	}
f5c1c7
+	data = ptr + 6;
f5c1c7
 	switch (I16(ptr+4)) {
f5c1c7
 	case 4: case 11:
f5c1c7
 	    /* FLI COLOR chunk */
f5c1c7
@@ -198,7 +204,9 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
f5c1c7
 	    state->errcode = IMAGING_CODEC_UNKNOWN;
f5c1c7
 	    return -1;
f5c1c7
 	}
f5c1c7
-	ptr += I32(ptr);
f5c1c7
+	advance = I32(ptr);
f5c1c7
+	ptr += advance;
f5c1c7
+	bytes -= advance;
f5c1c7
     }
f5c1c7
 
f5c1c7
     return -1; /* end of frame */
f5c1c7
diff --git a/src/libImaging/PcxDecode.c b/src/libImaging/PcxDecode.c
f5c1c7
index e5417f1..aaf5867 100644
f5c1c7
--- a/src/libImaging/PcxDecode.c
f5c1c7
+++ b/src/libImaging/PcxDecode.c
f5c1c7
@@ -22,6 +22,14 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
f5c1c7
     UINT8 n;
f5c1c7
     UINT8* ptr;
f5c1c7
 
f5c1c7
+    if (strcmp(im->mode, "1") == 0 && state->xsize > state->bytes * 8) {
f5c1c7
+        state->errcode = IMAGING_CODEC_OVERRUN;
f5c1c7
+        return -1;
f5c1c7
+    } else if (strcmp(im->mode, "P") == 0 && state->xsize > state->bytes) {
f5c1c7
+        state->errcode = IMAGING_CODEC_OVERRUN;
f5c1c7
+        return -1;
f5c1c7
+    }
f5c1c7
+
f5c1c7
     ptr = buf;
f5c1c7
 
f5c1c7
     for (;;) {
f5c1c7
diff --git a/src/libImaging/RawDecode.c b/src/libImaging/RawDecode.c
f5c1c7
index 40c0cb7..d4b7994 100644
f5c1c7
--- a/src/libImaging/RawDecode.c
f5c1c7
+++ b/src/libImaging/RawDecode.c
f5c1c7
@@ -33,8 +33,15 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
f5c1c7
 
f5c1c7
 	/* get size of image data and padding */
f5c1c7
 	state->bytes = (state->xsize * state->bits + 7) / 8;
f5c1c7
-	rawstate->skip = (rawstate->stride) ?
f5c1c7
-	    rawstate->stride - state->bytes : 0;
f5c1c7
+	if (rawstate->stride) {
f5c1c7
+	    rawstate->skip = rawstate->stride - state->bytes;
f5c1c7
+	    if (rawstate->skip < 0) {
f5c1c7
+	        state->errcode = IMAGING_CODEC_CONFIG;
f5c1c7
+	        return -1;
f5c1c7
+	    }
f5c1c7
+	} else {
f5c1c7
+	    rawstate->skip = 0;
f5c1c7
+	}
f5c1c7
 
f5c1c7
 	/* check image orientation */
f5c1c7
 	if (state->ystep < 0) {
f5c1c7
diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c
f5c1c7
index 9d8e563..39e7b3a 100644
f5c1c7
--- a/src/libImaging/SgiRleDecode.c
f5c1c7
+++ b/src/libImaging/SgiRleDecode.c
f5c1c7
@@ -156,6 +156,11 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
f5c1c7
             c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize];
f5c1c7
             c->rleoffset -= SGI_HEADER_SIZE;
f5c1c7
 
f5c1c7
+            if (c->rleoffset + c->rlelength > c->bufsize) {
f5c1c7
+                state->errcode = IMAGING_CODEC_OVERRUN;
f5c1c7
+                return -1;
f5c1c7
+            }
f5c1c7
+
f5c1c7
             /* row decompression */
f5c1c7
             if (c->bpc ==1) {
f5c1c7
                 if(expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands))
f5c1c7
-- 
f5c1c7
2.24.1
f5c1c7