From 341de8db495fea7b94a007bdc02d4ee4a8919f69 Mon Sep 17 00:00:00 2001 From: yeah_wang Date: Thu, 1 Apr 2021 20:03:35 +0800 Subject: [PATCH] fix CVE-2021-25290 CVE-2021-25292 CVE-2021-25293 --- backport-0001-CVE-2021-25290.patch | 34 +++++ backport-0002-CVE-2021-25290.patch | 34 +++++ backport-0003-CVE-2021-25290.patch | 27 ++++ backport-CVE-2021-25292.patch | 27 ++++ backport-CVE-2021-25293.patch | 209 +++++++++++++++++++++++++++++ python-pillow.spec | 13 +- 6 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 backport-0001-CVE-2021-25290.patch create mode 100644 backport-0002-CVE-2021-25290.patch create mode 100644 backport-0003-CVE-2021-25290.patch create mode 100644 backport-CVE-2021-25292.patch create mode 100644 backport-CVE-2021-25293.patch diff --git a/backport-0001-CVE-2021-25290.patch b/backport-0001-CVE-2021-25290.patch new file mode 100644 index 0000000..6745698 --- /dev/null +++ b/backport-0001-CVE-2021-25290.patch @@ -0,0 +1,34 @@ +From 86f02f7c70862a0954bfe8133736d352db978eaa Mon Sep 17 00:00:00 2001 +From: Eric Soroos +Date: Fri, 8 Jan 2021 18:45:42 +0100 +Subject: [PATCH] Fix negative size read in TiffDecode.c + +* Caught by oss-fuzz runs +* CVE-2021-25290 + +Conflict:NA +Reference:https://github.com/python-pillow/Pillow/commit/86f02f7c70862a0954bfe8133736d352db978eaa +--- + src/libImaging/TiffDecode.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/libImaging/TiffDecode.c b/src/libImaging/TiffDecode.c +index 1f505ff..d6b5cf5 100644 +--- a/src/libImaging/TiffDecode.c ++++ b/src/libImaging/TiffDecode.c +@@ -35,7 +35,11 @@ tsize_t _tiffReadProc(thandle_t hdata, tdata_t buf, tsize_t size) { + + TRACE(("_tiffReadProc: %d \n", (int)size)); + dump_state(state); +- ++ ++ if (state->loc > state->eof) { ++ TIFFError("_tiffReadProc", "Invalid Read at loc %d, eof: %d", state->loc, state->eof); ++ return 0; ++ } + to_read = min(size, min(state->size, (tsize_t)state->eof) - (tsize_t)state->loc); + TRACE(("to_read: %d\n", (int)to_read)); + +-- +2.23.0 + diff --git a/backport-0002-CVE-2021-25290.patch b/backport-0002-CVE-2021-25290.patch new file mode 100644 index 0000000..d2c561f --- /dev/null +++ b/backport-0002-CVE-2021-25290.patch @@ -0,0 +1,34 @@ +From 852fd170f8f3bb45cb0a7709d62bbc52b568d8bc Mon Sep 17 00:00:00 2001 +From: Luke Granger-Brown +Date: Wed, 3 Mar 2021 13:30:28 +0000 +Subject: [PATCH] Fix -Wformat error in TiffDecode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +src/libImaging/TiffDecode.c: In function ‘_tiffReadProc’: +src/libImaging/TiffDecode.c:59:58: error: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘toff_t’ {aka ‘long unsigned int’} [-Werror=format=] +src/libImaging/TiffDecode.c:59:67: error: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘toff_t’ {aka ‘long unsigned int’} [-Werror=format=] + +Conflict:NA +Reference:https://github.com/python-pillow/Pillow/commit/852fd170f8f3bb45cb0a7709d62bbc52b568d8bc +--- + src/libImaging/TiffDecode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libImaging/TiffDecode.c b/src/libImaging/TiffDecode.c +index d6b5cf5..5178ce8 100644 +--- a/src/libImaging/TiffDecode.c ++++ b/src/libImaging/TiffDecode.c +@@ -37,7 +37,7 @@ tsize_t _tiffReadProc(thandle_t hdata, tdata_t buf, tsize_t size) { + dump_state(state); + + if (state->loc > state->eof) { +- TIFFError("_tiffReadProc", "Invalid Read at loc %d, eof: %d", state->loc, state->eof); ++ TIFFError("_tiffReadProc", "Invalid Read at loc %lu, eof: %lu", state->loc, state->eof); + return 0; + } + to_read = min(size, min(state->size, (tsize_t)state->eof) - (tsize_t)state->loc); +-- +2.23.0 + diff --git a/backport-0003-CVE-2021-25290.patch b/backport-0003-CVE-2021-25290.patch new file mode 100644 index 0000000..14bf9d4 --- /dev/null +++ b/backport-0003-CVE-2021-25290.patch @@ -0,0 +1,27 @@ +From 68b655f3f014c6beb13f4c9a6fa53f1ebff527c2 Mon Sep 17 00:00:00 2001 +From: Andrew Murray <3112309+radarhere@users.noreply.github.com> +Date: Wed, 10 Mar 2021 20:43:16 +1100 +Subject: [PATCH] Updated format specifiers + +Conflict:NA +Reference:https://github.com/python-pillow/Pillow/commit/68b655f3f014c6beb13f4c9a6fa53f1ebff527c2 +--- + src/libImaging/TiffDecode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libImaging/TiffDecode.c b/src/libImaging/TiffDecode.c +index 5178ce8..48647a6 100644 +--- a/src/libImaging/TiffDecode.c ++++ b/src/libImaging/TiffDecode.c +@@ -37,7 +37,7 @@ tsize_t _tiffReadProc(thandle_t hdata, tdata_t buf, tsize_t size) { + dump_state(state); + + if (state->loc > state->eof) { +- TIFFError("_tiffReadProc", "Invalid Read at loc %lu, eof: %lu", state->loc, state->eof); ++ TIFFError("_tiffReadProc", "Invalid Read at loc %llu, eof: %llu", state->loc, state->eof); + return 0; + } + to_read = min(size, min(state->size, (tsize_t)state->eof) - (tsize_t)state->loc); +-- +2.23.0 + diff --git a/backport-CVE-2021-25292.patch b/backport-CVE-2021-25292.patch new file mode 100644 index 0000000..63e4670 --- /dev/null +++ b/backport-CVE-2021-25292.patch @@ -0,0 +1,27 @@ +From 3bce145966374dd39ce58a6fc0083f8d1890719c Mon Sep 17 00:00:00 2001 +From: Hugo van Kemenade +Date: Sat, 9 Jan 2021 15:53:09 +0200 +Subject: [PATCH] Use more specific regex chars to prevent ReDoS + +* CVE-2021-25292 +--- + src/PIL/PdfParser.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py +index 231651e..b0ab383 100644 +--- a/src/PIL/PdfParser.py ++++ b/src/PIL/PdfParser.py +@@ -611,8 +611,9 @@ class PdfParser: + whitespace_or_hex = br"[\000\011\012\014\015\0400-9a-fA-F]" + whitespace_optional = whitespace + b"*" + whitespace_mandatory = whitespace + b"+" ++ whitespace_optional_no_nl = br"[\000\011\014\015\040]*" # no "\012" aka "\n" + newline_only = br"[\r\n]+" +- newline = whitespace_optional + newline_only + whitespace_optional ++ newline = whitespace_optional_no_nl + newline_only + whitespace_optional_no_nl + re_trailer_end = re.compile( + whitespace_mandatory + br"trailer" + whitespace_optional + + br"\<\<(.*\>\>)" + newline + br"startxref" + newline + br"([0-9]+)" + +-- +2.23.0 diff --git a/backport-CVE-2021-25293.patch b/backport-CVE-2021-25293.patch new file mode 100644 index 0000000..fcedef9 --- /dev/null +++ b/backport-CVE-2021-25293.patch @@ -0,0 +1,209 @@ +From 4853e522bddbec66022c0915b9a56255d0188bf9 Mon Sep 17 00:00:00 2001 +From: Eric Soroos +Date: Sat, 2 Jan 2021 16:07:36 +0100 +Subject: [PATCH] Fix OOB read in SgiRleDecode.c + +* From Pillow 4.3.0->8.1.0 +* CVE-2021-25293 +--- + src/libImaging/SgiRleDecode.c | 88 +++++++++++++++++++++++++++++------ + 1 file changed, 74 insertions(+), 14 deletions(-) + +diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c +index 5062285..0dcb422 100644 +--- a/src/libImaging/SgiRleDecode.c ++++ b/src/libImaging/SgiRleDecode.c +@@ -25,13 +25,59 @@ static void read4B(UINT32* dest, UINT8* buf) + *dest = (UINT32)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); + } + +-static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) ++/* ++ SgiRleDecoding is done in a single channel row oriented set of RLE chunks. ++ ++ * The file is arranged as ++ - SGI Header ++ - Rle Offset Table ++ - Rle Length Table ++ - Scanline Data ++ ++ * Each RLE atom is c->bpc bytes wide (1 or 2) ++ ++ * Each RLE Chunk is [specifier atom] [ 1 or n data atoms ] ++ ++ * Copy Atoms are a byte with the high bit set, and the low 7 are ++ the number of bytes to copy from the source to the ++ destination. e.g. ++ ++ CBBBBBBBB or 0CHLHLHLHLHLHL (B=byte, H/L = Hi low bytes) ++ ++ * Run atoms do not have the high bit set, and the low 7 bits are ++ the number of copies of the next atom to copy to the ++ destination. e.g.: ++ ++ RB -> BBBBB or RHL -> HLHLHLHLHL ++ ++ The upshot of this is, there is no way to determine the required ++ length of the input buffer from reloffset and rlelength without ++ going through the data at that scan line. ++ ++ Furthermore, there's no requirement that individual scan lines ++ pointed to from the rleoffset table are in any sort of order or ++ used only once, or even disjoint. There's also no requirement that ++ all of the data in the scan line area of the image file be used ++ ++ */ ++static int expandrow(UINT8 *dest, UINT8 *src, int n, int z, int xsize, UINT8 *end_of_buffer) + { ++ /* ++ * n here is the number of rlechunks ++ * z is the number of channels, for calculating the interleave ++ * offset to go to RGBA style pixels ++ * xsize is the row width ++ * end_of_buffer is the address of the end of the input buffer ++ */ ++ + UINT8 pixel, count; + int x = 0; + + for (;n > 0; n--) + { ++ if (src > end_of_buffer) { ++ return -1; ++ } + pixel = *src++; + if (n == 1 && pixel != 0) + return n; +@@ -43,6 +89,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + } + x += count; + if (pixel & RLE_COPY_FLAG) { ++ if (src + count > end_of_buffer) { ++ return -1; ++ } + while(count--) { + *dest = *src++; + dest += z; +@@ -50,6 +99,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + + } + else { ++ if (src > end_of_buffer) { ++ return -1; ++ } + pixel = *src++; + while (count--) { + *dest = pixel; +@@ -61,14 +113,16 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + return 0; + } + +-static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize) ++static int expandrow2(UINT8 *dest, const UINT8 *src, int n, int z, int xsize, UINT8 *end_of_buffer) + { + UINT8 pixel, count; +- + int x = 0; + + for (;n > 0; n--) + { ++ if (src + 1 > end_of_buffer) { ++ return -1; ++ } + pixel = src[1]; + src+=2; + if (n == 1 && pixel != 0) +@@ -81,6 +135,9 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize) + } + x += count; + if (pixel & RLE_COPY_FLAG) { ++ if (src + 2 * count > end_of_buffer) { ++ return -1; ++ } + while(count--) { + memcpy(dest, src, 2); + src += 2; +@@ -88,6 +145,9 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize) + } + } + else { ++ if (src + 2 > end_of_buffer) { ++ return -1; ++ } + while (count--) { + memcpy(dest, src, 2); + dest += z * 2; +@@ -137,7 +197,10 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + return -1; + } + _imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET); +- _imaging_read_pyFd(state->fd, (char*)ptr, c->bufsize); ++ if (_imaging_read_pyFd(state->fd, (char *)ptr, c->bufsize) != c->bufsize) { ++ state->errcode = IMAGING_CODEC_UNKNOWN; ++ return -1; ++ } + + + /* decoder initialization */ +@@ -169,8 +232,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + for (c->tabindex = 0, c->bufindex = c->tablen * sizeof(UINT32); c->tabindex < c->tablen; c->tabindex++, c->bufindex+=4) + read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]); + +- state->count += c->tablen * sizeof(UINT32) * 2; +- + /* read compressed rows */ + for (c->rowno = 0; c->rowno < im->ysize; c->rowno++, state->y += state->ystep) + { +@@ -178,19 +239,21 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + { + c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize]; + c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize]; +- c->rleoffset -= SGI_HEADER_SIZE; + +- if (c->rleoffset + c->rlelength > c->bufsize) { ++ // Check for underflow of rleoffset-SGI_HEADER_SIZE ++ if (c->rleoffset < SGI_HEADER_SIZE) { + state->errcode = IMAGING_CODEC_OVERRUN; + goto sgi_finish_decode; + } + ++ c->rleoffset -= SGI_HEADER_SIZE; ++ + /* row decompression */ + if (c->bpc ==1) { +- status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); ++ status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize, &ptr[c->bufsize-1]); + } + else { +- status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); ++ status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize, &ptr[c->bufsize-1]); + } + if (status == -1) { + state->errcode = IMAGING_CODEC_OVERRUN; +@@ -199,7 +262,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + goto sgi_finish_decode; + } + +- state->count += c->rlelength; + } + + /* store decompressed data in image */ +@@ -207,8 +269,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + + } + +- c->bufsize++; +- + sgi_finish_decode: ; + + free(c->starttab); +@@ -218,5 +278,5 @@ sgi_finish_decode: ; + state->errcode=err; + return -1; + } +- return state->count - c->bufsize; ++ return 0; + } +-- +2.23.0 + diff --git a/python-pillow.spec b/python-pillow.spec index 5803ee1..0280277 100644 --- a/python-pillow.spec +++ b/python-pillow.spec @@ -5,7 +5,7 @@ Name: python-pillow Version: 5.3.0 -Release: 13 +Release: 14 Summary: Python image processing library License: MIT URL: http://python-pillow.github.io/ @@ -29,6 +29,11 @@ Patch0019: CVE-2020-5313.patch Patch0020: backport-CVE-2020-35653.patch Patch6000: backport-CVE-2020-35655.patch Patch6001: backport-CVE-2021-27921_CVE-2021-27922_CVE-2021-27923.patch +Patch6002: backport-0001-CVE-2021-25290.patch +Patch6003: backport-0002-CVE-2021-25290.patch +Patch6004: backport-0003-CVE-2021-25290.patch +Patch6005: backport-CVE-2021-25292.patch +Patch6006: backport-CVE-2021-25293.patch BuildRequires: freetype-devel ghostscript lcms2-devel libimagequant-devel libjpeg-devel BuildRequires: libtiff-devel libwebp-devel openjpeg2-devel tk-devel zlib-devel @@ -182,6 +187,12 @@ popd %doc docs/_build_py3/html %changelog +* Thu Apr 1 2021 yanglu - 5.3.0-14 +- Type:cves +- ID:CVE-2021-25290 CVE-2021-25292 CVE-2021-25293 +- SUG:NA +- DESC:fix CVE-2021-25290 CVE-2021-25292 CVE-2021-25293 + * Mon Mar 15 2021 wangye - 5.3.0-13 - Type:cves - ID:CVE-2021-27921 CVE-2021-27922 CVE-2021-27923 -- Gitee