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