Skip to content

Commit

Permalink
Fix for SGI Decode buffer overrun CVE-2020-35655
Browse files Browse the repository at this point in the history
* Independently found by a contributor and sent to Tidelift, and by Google's OSS Fuzz.
  • Loading branch information
wiredfool authored and radarhere committed Jan 2, 2021
1 parent e6ef8a6 commit 7e95c63
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 8 deletions.
Binary file not shown.
Binary file added Tests/images/ossfuzz-5730089102868480.sgi
Binary file not shown.
8 changes: 7 additions & 1 deletion Tests/test_sgi_crash.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@

@pytest.mark.parametrize(
"test_file",
["Tests/images/sgi_overrun_expandrowF04.bin", "Tests/images/sgi_crash.bin"],
[
"Tests/images/sgi_overrun_expandrowF04.bin",
"Tests/images/sgi_crash.bin",
"Tests/images/crash-6b7f2244da6d0ae297ee0754a424213444e92778.sgi",
"Tests/images/ossfuzz-5730089102868480.sgi",
],
)
def test_crashes(test_file):
with open(test_file, "rb") as f:
Expand Down
23 changes: 16 additions & 7 deletions src/libImaging/SgiRleDecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,27 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
int err = 0;
int status;

/* size check */
if (im->xsize > INT_MAX / im->bands ||
im->ysize > INT_MAX / im->bands) {
return IMAGING_CODEC_MEMORY;
}

/* Get all data from File descriptor */
c = (SGISTATE*)state->context;
_imaging_seek_pyFd(state->fd, 0L, SEEK_END);
c->bufsize = _imaging_tell_pyFd(state->fd);
c->bufsize -= SGI_HEADER_SIZE;

c->tablen = im->bands * im->ysize;
/* below, we populate the starttab and lentab into the bufsize,
each with 4 bytes per element of tablen
Check here before we allocate any memory
*/
if (c->bufsize < 8*c->tablen) {
return IMAGING_CODEC_MEMORY;
}

ptr = malloc(sizeof(UINT8) * c->bufsize);
if (!ptr) {
return IMAGING_CODEC_MEMORY;
Expand All @@ -134,18 +150,11 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
state->ystep = 1;
}

if (im->xsize > INT_MAX / im->bands ||
im->ysize > INT_MAX / im->bands) {
err = IMAGING_CODEC_MEMORY;
goto sgi_finish_decode;
}

/* Allocate memory for RLE tables and rows */
free(state->buffer);
state->buffer = NULL;
/* malloc overflow check above */
state->buffer = calloc(im->xsize * im->bands, sizeof(UINT8) * 2);
c->tablen = im->bands * im->ysize;
c->starttab = calloc(c->tablen, sizeof(UINT32));
c->lengthtab = calloc(c->tablen, sizeof(UINT32));
if (!state->buffer ||
Expand Down

0 comments on commit 7e95c63

Please # to comment.