7f73fb
From f276de1139ec16395dc8b382860fb58e331fbd53 Mon Sep 17 00:00:00 2001
7f73fb
From: Eric Soroos <eric-github@soroos.net>
7f73fb
Date: Thu, 29 Oct 2020 23:07:15 +0000
7f73fb
Subject: [PATCH 1/2] Fix for SGI Decode buffer overrun CVE-2020-35655
7f73fb
7f73fb
* Independently found by a contributor and sent to Tidelift, and by Google's OSS Fuzz.
7f73fb
---
7f73fb
 src/libImaging/SgiRleDecode.c | 23 ++++++++++++++++-------
7f73fb
 1 file changed, 16 insertions(+), 7 deletions(-)
7f73fb
7f73fb
diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c
7f73fb
index eb8fc84..c256169 100644
7f73fb
--- a/src/libImaging/SgiRleDecode.c
7f73fb
+++ b/src/libImaging/SgiRleDecode.c
7f73fb
@@ -107,11 +107,27 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
7f73fb
     int err = 0;
7f73fb
     int status;
7f73fb
 
7f73fb
+    /* size check */
7f73fb
+    if (im->xsize > INT_MAX / im->bands ||
7f73fb
+        im->ysize > INT_MAX / im->bands) {
7f73fb
+        return IMAGING_CODEC_MEMORY;
7f73fb
+    }
7f73fb
+
7f73fb
     /* Get all data from File descriptor */
7f73fb
     c = (SGISTATE*)state->context;
7f73fb
     _imaging_seek_pyFd(state->fd, 0L, SEEK_END);
7f73fb
     c->bufsize = _imaging_tell_pyFd(state->fd);
7f73fb
     c->bufsize -= SGI_HEADER_SIZE;
7f73fb
+
7f73fb
+    c->tablen = im->bands * im->ysize;
7f73fb
+    /* below, we populate the starttab and lentab into the bufsize,
7f73fb
+       each with 4 bytes per element of tablen
7f73fb
+       Check here before we allocate any memory
7f73fb
+    */
7f73fb
+    if (c->bufsize < 8*c->tablen) {
7f73fb
+        return IMAGING_CODEC_MEMORY;
7f73fb
+    }
7f73fb
+
7f73fb
     ptr = malloc(sizeof(UINT8) * c->bufsize);
7f73fb
     if (!ptr) {
7f73fb
         return IMAGING_CODEC_MEMORY;
7f73fb
@@ -129,18 +145,11 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
7f73fb
         state->ystep = 1;
7f73fb
     }
7f73fb
 
7f73fb
-    if (im->xsize > INT_MAX / im->bands ||
7f73fb
-        im->ysize > INT_MAX / im->bands) {
7f73fb
-        err = IMAGING_CODEC_MEMORY;
7f73fb
-        goto sgi_finish_decode;
7f73fb
-    }
7f73fb
-
7f73fb
     /* Allocate memory for RLE tables and rows */
7f73fb
     free(state->buffer);
7f73fb
     state->buffer = NULL;
7f73fb
     /* malloc overflow check above */
7f73fb
     state->buffer = calloc(im->xsize * im->bands, sizeof(UINT8) * 2);
7f73fb
-    c->tablen = im->bands * im->ysize;
7f73fb
     c->starttab = calloc(c->tablen, sizeof(UINT32));
7f73fb
     c->lengthtab = calloc(c->tablen, sizeof(UINT32));
7f73fb
     if (!state->buffer ||
7f73fb
-- 
7f73fb
2.29.2
7f73fb
7f73fb
From 18aa14484fa63dabcafea63cf0b7bfb4066e979c Mon Sep 17 00:00:00 2001
7f73fb
From: Eric Soroos <eric-github@soroos.net>
7f73fb
Date: Fri, 30 Oct 2020 09:57:23 +0000
7f73fb
Subject: [PATCH 2/2] Make the SGI code return -1 as an error flag, error in
7f73fb
 state
7f73fb
7f73fb
---
7f73fb
 src/libImaging/SgiRleDecode.c | 16 ++++++++++------
7f73fb
 1 file changed, 10 insertions(+), 6 deletions(-)
7f73fb
7f73fb
diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c
7f73fb
index c256169..2259159 100644
7f73fb
--- a/src/libImaging/SgiRleDecode.c
7f73fb
+++ b/src/libImaging/SgiRleDecode.c
7f73fb
@@ -110,7 +110,8 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
7f73fb
     /* size check */
7f73fb
     if (im->xsize > INT_MAX / im->bands ||
7f73fb
         im->ysize > INT_MAX / im->bands) {
7f73fb
-        return IMAGING_CODEC_MEMORY;
7f73fb
+        state->errcode = IMAGING_CODEC_MEMORY;
7f73fb
+        return -1;
7f73fb
     }
7f73fb
 
7f73fb
     /* Get all data from File descriptor */
7f73fb
@@ -125,12 +126,14 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
7f73fb
        Check here before we allocate any memory
7f73fb
     */
7f73fb
     if (c->bufsize < 8*c->tablen) {
7f73fb
-        return IMAGING_CODEC_MEMORY;
7f73fb
+        state->errcode = IMAGING_CODEC_OVERRUN;
7f73fb
+        return -1;
7f73fb
     }
7f73fb
 
7f73fb
     ptr = malloc(sizeof(UINT8) * c->bufsize);
7f73fb
     if (!ptr) {
7f73fb
-        return IMAGING_CODEC_MEMORY;
7f73fb
+        state->errcode = IMAGING_CODEC_MEMORY;
7f73fb
+        return -1;
7f73fb
     }
7f73fb
     _imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET);
7f73fb
     _imaging_read_pyFd(state->fd, (char*)ptr, c->bufsize);
7f73fb
@@ -178,7 +181,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
7f73fb
 
7f73fb
             if (c->rleoffset + c->rlelength > c->bufsize) {
7f73fb
                 state->errcode = IMAGING_CODEC_OVERRUN;
7f73fb
-                return -1;
7f73fb
+                goto sgi_finish_decode;
7f73fb
             }
7f73fb
 
7f73fb
             /* row decompression */
7f73fb
@@ -190,7 +193,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
7f73fb
             }
7f73fb
             if (status == -1) {
7f73fb
                 state->errcode = IMAGING_CODEC_OVERRUN;
7f73fb
-                return -1;
7f73fb
+                goto sgi_finish_decode;
7f73fb
             } else if (status == 1) {
7f73fb
                 goto sgi_finish_decode;
7f73fb
             }
7f73fb
@@ -211,7 +214,8 @@ sgi_finish_decode: ;
7f73fb
     free(c->lengthtab);
7f73fb
     free(ptr);
7f73fb
     if (err != 0){
7f73fb
-        return err;
7f73fb
+        state->errcode=err;
7f73fb
+        return -1;
7f73fb
     }
7f73fb
     return state->count - c->bufsize;
7f73fb
 }
7f73fb
-- 
7f73fb
2.29.2
7f73fb