diff --git a/CVE-2020-10177.patch b/CVE-2020-10177.patch new file mode 100644 index 0000000000000000000000000000000000000000..5b9dba991b913ad12450e4f99a7f5c4622136ffd --- /dev/null +++ b/CVE-2020-10177.patch @@ -0,0 +1,145 @@ +diff --git a/src/libImaging/FliDecode.c b/src/libImaging/FliDecode.c +index 600528e..2d63bea 100644 +--- a/src/libImaging/FliDecode.c ++++ b/src/libImaging/FliDecode.c +@@ -24,6 +24,11 @@ + #define I32(ptr)\ + ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) + ++#define ERR_IF_DATA_OOB(offset) \ ++ if ((data + (offset)) > ptr + bytes) {\ ++ state->errcode = IMAGING_CODEC_OVERRUN; \ ++ return -1; \ ++ } + + int + ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) +@@ -75,10 +80,12 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + break; /* ignored; handled by Python code */ + case 7: + /* FLI SS2 chunk (word delta) */ ++ /* OOB ok, we've got 4 bytes min on entry */ + lines = I16(data); data += 2; + for (l = y = 0; l < lines && y < state->ysize; l++, y++) { +- UINT8* buf = (UINT8*) im->image[y]; ++ UINT8* local_buf = (UINT8*) im->image[y]; + int p, packets; ++ ERR_IF_DATA_OOB(2) + packets = I16(data); data += 2; + while (packets & 0x8000) { + /* flag word */ +@@ -88,29 +95,33 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + state->errcode = IMAGING_CODEC_OVERRUN; + return -1; + } +- buf = (UINT8*) im->image[y]; ++ local_buf = (UINT8*) im->image[y]; + } else { + /* store last byte (used if line width is odd) */ +- buf[state->xsize-1] = (UINT8) packets; ++ local_buf[state->xsize-1] = (UINT8) packets; + } ++ ERR_IF_DATA_OOB(2) + packets = I16(data); data += 2; + } + for (p = x = 0; p < packets; p++) { ++ ERR_IF_DATA_OOB(2) + x += data[0]; /* pixel skip */ + if (data[1] >= 128) { ++ ERR_IF_DATA_OOB(4) + i = 256-data[1]; /* run */ + if (x + i + i > state->xsize) + break; + for (j = 0; j < i; j++) { +- buf[x++] = data[2]; +- buf[x++] = data[3]; ++ local_buf[x++] = data[2]; ++ local_buf[x++] = data[3]; + } + data += 2 + 2; + } else { + i = 2 * (int) data[1]; /* chunk */ + if (x + i > state->xsize) + break; +- memcpy(buf + x, data + 2, i); ++ ERR_IF_DATA_OOB(2+i) ++ memcpy(local_buf + x, data + 2, i); + data += 2 + i; + x += i; + } +@@ -126,22 +137,26 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + break; + case 12: + /* FLI LC chunk (byte delta) */ ++ /* OOB Check ok, we have 10 bytes here */ + y = I16(data); ymax = y + I16(data+2); data += 4; + for (; y < ymax && y < state->ysize; y++) { + UINT8* out = (UINT8*) im->image[y]; + int p, packets = *data++; + for (p = x = 0; p < packets; p++, x += i) { ++ ERR_IF_DATA_OOB(2) + x += data[0]; /* skip pixels */ + if (data[1] & 0x80) { + i = 256-data[1]; /* run */ + if (x + i > state->xsize) + break; ++ ERR_IF_DATA_OOB(3) + memset(out + x, data[2], i); + data += 3; + } else { + i = data[1]; /* chunk */ + if (x + i > state->xsize) + break; ++ ERR_IF_DATA_OOB(2+i) + memcpy(out + x, data + 2, i); + data += i + 2; + } +@@ -162,14 +177,20 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + break; + case 15: + /* FLI BRUN chunk */ ++ /* data = ptr + 6 */ + for (y = 0; y < state->ysize; y++) { + UINT8* out = (UINT8*) im->image[y]; + data += 1; /* ignore packetcount byte */ + for (x = 0; x < state->xsize; x += i) { ++ /* Out of Bounds Read issue, guaranteed to try to read 2 from data */ ++ ERR_IF_DATA_OOB(2) + if (data[0] & 0x80) { + i = 256 - data[0]; +- if (x + i > state->xsize) ++ if (x + i > state->xsize){ + break; /* safety first */ ++ } ++ /* Out of Bounds read issue */ ++ ERR_IF_DATA_OOB(i+1) + memcpy(out + x, data + 1, i); + data += i + 1; + } else { +@@ -189,9 +210,13 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + break; + case 16: + /* COPY chunk */ ++ if (state->xsize > bytes/state->ysize) { ++ /* not enough data for frame */ ++ return ptr - buf; /* bytes consumed */ ++ } + for (y = 0; y < state->ysize; y++) { +- UINT8* buf = (UINT8*) im->image[y]; +- memcpy(buf, data, state->xsize); ++ UINT8* local_buf = (UINT8*) im->image[y]; ++ memcpy(local_buf, data, state->xsize); + data += state->xsize; + } + break; +@@ -205,6 +230,10 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + return -1; + } + advance = I32(ptr); ++ if (advance < 0 || advance > bytes) { ++ state->errcode = IMAGING_CODEC_OVERRUN; ++ return -1; ++ } + ptr += advance; + bytes -= advance; + } diff --git a/CVE-2020-10378.patch b/CVE-2020-10378.patch new file mode 100644 index 0000000000000000000000000000000000000000..2d41cc5ab2401c86cce3f1d688e4defd38bb7311 --- /dev/null +++ b/CVE-2020-10378.patch @@ -0,0 +1,22 @@ +From 6a83e4324738bb0452fbe8074a995b1c73f08de7 Mon Sep 17 00:00:00 2001 +From: Eric Soroos +Date: Mon, 9 Mar 2020 20:22:06 +0000 +Subject: [PATCH] Fix OOB Access on PcxDecode.c + +--- + src/libImaging/PcxDecode.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/src/libImaging/PcxDecode.c b/src/libImaging/PcxDecode.c +index 51de069..bf0eb00 100644 +--- a/src/libImaging/PcxDecode.c ++++ b/src/libImaging/PcxDecode.c +@@ -22,7 +22,7 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + UINT8 n; + UINT8* ptr; + +- if (strcmp(im->mode, "1") == 0 && state->xsize > state->bytes * 8) { ++ if ((state->xsize * state->bits + 7) / 8 > state->bytes) { + state->errcode = IMAGING_CODEC_OVERRUN; + return -1; + } diff --git a/CVE-2020-10994.patch b/CVE-2020-10994.patch new file mode 100644 index 0000000000000000000000000000000000000000..4874323f683f2c17e4f9708937c1c5fa724d9a76 --- /dev/null +++ b/CVE-2020-10994.patch @@ -0,0 +1,109 @@ +From cf6da6b79080a8c16984102fdc85f7ce28dca613 Mon Sep 17 00:00:00 2001 +From: Eric Soroos +Date: Mon, 9 Mar 2020 22:09:49 +0000 +Subject: [PATCH 1/4] Fix for OOB Read in DecodeJpeg2k + +--- + src/libImaging/Jpeg2KDecode.c | 60 +++++++++++++++++++++++++---------- + 1 file changed, 43 insertions(+), 17 deletions(-) + +diff --git a/src/libImaging/Jpeg2KDecode.c b/src/libImaging/Jpeg2KDecode.c +index 9140e00..8c231c1 100644 +--- a/src/libImaging/Jpeg2KDecode.c ++++ b/src/libImaging/Jpeg2KDecode.c +@@ -110,6 +110,7 @@ j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, + if (shift < 0) + offset += 1 << (-shift - 1); + ++ /* csiz*h*w + offset = tileinfo.datasize */ + switch (csiz) { + case 1: + for (y = 0; y < h; ++y) { +@@ -557,8 +558,10 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) + opj_dparameters_t params; + OPJ_COLOR_SPACE color_space; + j2k_unpacker_t unpack = NULL; +- size_t buffer_size = 0; +- unsigned n; ++ size_t buffer_size = 0, tile_bytes = 0; ++ unsigned n, tile_height, tile_width; ++ int components; ++ + + stream = opj_stream_create(BUFFER_SIZE, OPJ_TRUE); + +@@ -703,8 +706,44 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) + tile_info.x1 = (tile_info.x1 + correction) >> context->reduce; + tile_info.y1 = (tile_info.y1 + correction) >> context->reduce; + ++ /* Check the tile bounds; if the tile is outside the image area, ++ or if it has a negative width or height (i.e. the coordinates are ++ swapped), bail. */ ++ if (tile_info.x0 >= tile_info.x1 ++ || tile_info.y0 >= tile_info.y1 ++ || tile_info.x0 < image->x0 ++ || tile_info.y0 < image->y0 ++ || tile_info.x1 - image->x0 > im->xsize ++ || tile_info.y1 - image->y0 > im->ysize) { ++ state->errcode = IMAGING_CODEC_BROKEN; ++ state->state = J2K_STATE_FAILED; ++ goto quick_exit; ++ } ++ ++ /* Sometimes the tile_info.datasize we get back from openjpeg ++ is less than numcomps*w*h, and we overflow in the ++ shuffle stage */ ++ ++ tile_width = tile_info.x1 - tile_info.x0; ++ tile_height = tile_info.y1 - tile_info.y0; ++ components = tile_info.nb_comps == 3 ? 4 : tile_info.nb_comps; ++ if (( tile_width > UINT_MAX / components ) || ++ ( tile_height > UINT_MAX / components ) || ++ ( tile_width > UINT_MAX / (tile_height * components )) || ++ ( tile_height > UINT_MAX / (tile_width * components ))) { ++ state->errcode = IMAGING_CODEC_BROKEN; ++ state->state = J2K_STATE_FAILED; ++ goto quick_exit; ++ } ++ ++ tile_bytes = tile_width * tile_height * components; ++ ++ if (tile_bytes > tile_info.data_size) { ++ tile_info.data_size = tile_bytes; ++ } ++ + if (buffer_size < tile_info.data_size) { +- /* malloc check ok, tile_info.data_size from openjpeg */ ++ /* malloc check ok, overflow and tile size sanity check above */ + UINT8 *new = realloc (state->buffer, tile_info.data_size); + if (!new) { + state->errcode = IMAGING_CODEC_MEMORY; +@@ -715,6 +754,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) + buffer_size = tile_info.data_size; + } + ++ + if (!opj_decode_tile_data(codec, + tile_info.tile_index, + (OPJ_BYTE *)state->buffer, +@@ -725,20 +765,6 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) + goto quick_exit; + } + +- /* Check the tile bounds; if the tile is outside the image area, +- or if it has a negative width or height (i.e. the coordinates are +- swapped), bail. */ +- if (tile_info.x0 >= tile_info.x1 +- || tile_info.y0 >= tile_info.y1 +- || tile_info.x0 < image->x0 +- || tile_info.y0 < image->y0 +- || tile_info.x1 - image->x0 > im->xsize +- || tile_info.y1 - image->y0 > im->ysize) { +- state->errcode = IMAGING_CODEC_BROKEN; +- state->state = J2K_STATE_FAILED; +- goto quick_exit; +- } +- + unpack(image, &tile_info, state->buffer, im); + } + diff --git a/python-pillow.spec b/python-pillow.spec index 3f3c5171135b261c9e0e9ff7362ebefe74adf953..d2592b130c8bcb26dd455ff7dbda2d216b835e8a 100644 --- a/python-pillow.spec +++ b/python-pillow.spec @@ -5,7 +5,7 @@ Name: python-pillow Version: 5.3.0 -Release: 5 +Release: 6 Summary: Python image processing library License: MIT URL: http://python-pillow.github.io/ @@ -15,6 +15,9 @@ Patch0000: 0000-CVE-2019-16865-1.patch Patch0001: 0001-CVE-2019-16865-2.patch Patch0002: 0002-CVE-2019-16865-3.patch Patch0003: 0003-CVE-2019-16865-4.patch +Patch0004: CVE-2020-10378.patch +Patch0005: CVE-2020-10177.patch +Patch0006: CVE-2020-10994.patch BuildRequires: freetype-devel ghostscript lcms2-devel libimagequant-devel libjpeg-devel BuildRequires: libtiff-devel libwebp-devel openjpeg2-devel tk-devel zlib-devel @@ -168,6 +171,12 @@ popd %doc docs/_build_py3/html %changelog +* Sat Sep 12 2020 shixuantong - 5.3.0-6 +- Type:cves +- ID:CVE-2020-10378 CVE-2020-10177 CVE-2020-10994 +- SUG:NA +- DESC:fix CVE-2020-10378 CVE-2020-10177 CVE-2020-10994 + * Fri Aug 21 2020 shixuantong - 5.3.0-5 - add release version for rebuild