From 978191b608fff42d5ee8c031bead08c2d4b19726 Mon Sep 17 00:00:00 2001 From: Frederick Price Date: Tue, 18 Apr 2023 17:56:08 -0400 Subject: [PATCH] BE-159-cve-2020-10994 CVE fixes from: https://github.com/python-pillow/Pillow/pull/4505 Tests for jp2 overflow (cherry picked from commit 30443d39bd932159bbb66f88df9f34fec2100a4f) Format with Black (cherry picked from commit 6e86d235c8fc995d4cca9e4a79044e82810465a3) Add documentation --- CHANGES.rst | 3 +++ Tests/check_jp2_overflow.py | 26 ++++++++++++++++++++++++++ Tests/images/00r0_gray_l.jp2 | Bin 0 -> 614 bytes Tests/images/00r1_graya_la.jp2 | Bin 0 -> 335 bytes docs/releasenotes/6.2.2.5.rst | 1 + src/libImaging/Jpeg2KDecode.c | 19 ++++--------------- 6 files changed, 34 insertions(+), 15 deletions(-) create mode 100755 Tests/check_jp2_overflow.py create mode 100644 Tests/images/00r0_gray_l.jp2 create mode 100644 Tests/images/00r1_graya_la.jp2 diff --git a/CHANGES.rst b/CHANGES.rst index 0fb6a8a92..e34772eec 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -19,6 +19,9 @@ Changelog (Pillow) - Fix CVE-2021-28675: Fix DOS in PsdImagePlugin [rickprice] +- Fix CVE-2020-10994: In libImaging/Jpeg2KDecode.c in Pillow before 7.1.0, there are multiple out-of-bounds reads via a crafted JP2 file. + [rickprice] + 6.2.2.4 (2023-03-29) ------------------ diff --git a/Tests/check_jp2_overflow.py b/Tests/check_jp2_overflow.py new file mode 100755 index 000000000..a7a343c98 --- /dev/null +++ b/Tests/check_jp2_overflow.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +# Reproductions/tests for OOB read errors in FliDecode.c + +# When run in python, all of these images should fail for +# one reason or another, either as a buffer overrun, +# unrecognized datastream, or truncated image file. +# There shouldn't be any segfaults. +# +# if run like +# `valgrind --tool=memcheck python check_jp2_overflow.py 2>&1 | grep Decode.c` +# the output should be empty. There may be python issues +# in the valgrind especially if run in a debug python +# version. + + +from PIL import Image + +repro = ("00r0_gray_l.jp2", "00r1_graya_la.jp2") + +for path in repro: + im = Image.open(path) + try: + im.load() + except Exception as msg: + print(msg) diff --git a/Tests/images/00r0_gray_l.jp2 b/Tests/images/00r0_gray_l.jp2 new file mode 100644 index 0000000000000000000000000000000000000000..28612238a9cae1a8eca050d3df28f4119624a876 GIT binary patch literal 614 zcmZQzVBpCLP*C9IYUg5LU=T?wsVvAUFj4@r8KAT-kj?;d#WFKeihwjP5c@DNva>S+ z84Uc%`8h?53_3;W#R@>KP*G}einmw;0|>LQKtv>ykww@+1}Fdb{~ySp36uvJ1~C-O z;Xva9E#hVTAH=`|lx1XK1sVB2hCx}WT&|pbhw7 z2D@tNM;pZ%nrT6Vd^D0OOJ?Ln6PlM4?kqYC#d0hz;(MCCPJSWIA#-*h!V zfBW(725#SZL1z~y>k3@z*m#hY`{c~y{fpfA_MGpu`O$NHCQtE-O)H=2HBL4&$^Uj( z?q-J8WoNt2jen*qTgH6sD_1-D_|PA#wJCc3$6pAncj{1lZ+Ib=V}r)BRWUo|-G1^5 z3O}9O>~QGhalX{^#(R`l{Iw!?9LZW_*ZuVPmWbC6M1P(<`g>}U%K1rxmZgz5d6Mh0 z%hNA=AL()Jc(`z%`|G@f_Wve%o7Nx7n$f@g##ZMaGHMdqa!Up7{7z;$`)!Frr~c7H oye`)!t6uyOq2cINvQ6RbT=6iylrom<_X^UMt&U@A-249~0D?o$$^ZZW literal 0 HcmV?d00001 diff --git a/Tests/images/00r1_graya_la.jp2 b/Tests/images/00r1_graya_la.jp2 new file mode 100644 index 0000000000000000000000000000000000000000..f3f840a08e378fbdaf8cdc5b231ea6862f68ec06 GIT binary patch literal 335 zcmZQzVBpCLP*C9IYUg5LU=T?wsVvAUFj4@r8KAT?kj?;d#WFKeih#5N7&Ec6GXfb5 z{K@$_MPL?#AdoAToRXTxzyy*30!APN1E3Mf|NZ|5GU$N03P2KsVL$=M0AUDVVsB(* zXJq^z#J~d-U}RurVPRnWAHyK5;1LiI0Yd>E9s&PTfR-|PCuS$6lKW-7{-3}A z@(2S%4N%YI<5yT1X8;L~faMQZ*gl^>z`_$>WlejaJCOIozHBX{G&^n;(f8O#>WT$jAqG~@M=OACIoFwC8{l95GQ Z;KspEJPh&6k9REK-H`Btt@iQ%n*b)BSDpX> literal 0 HcmV?d00001 diff --git a/docs/releasenotes/6.2.2.5.rst b/docs/releasenotes/6.2.2.5.rst index 4374eed0e..2e8402ded 100644 --- a/docs/releasenotes/6.2.2.5.rst +++ b/docs/releasenotes/6.2.2.5.rst @@ -21,3 +21,4 @@ This release addresses several critical CVEs. :cve:`CVE-2022-22816`: Fixed ImagePath.Path array handling +:cve:`CVE-2020-10994`: In libImaging/Jpeg2KDecode.c in Pillow before 7.1.0, there are multiple out-of-bounds reads via a crafted JP2 file. diff --git a/src/libImaging/Jpeg2KDecode.c b/src/libImaging/Jpeg2KDecode.c index 0e61663a5..f981d57da 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) { @@ -561,6 +562,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) unsigned n, tile_height, tile_width; int total_component_width = 0; + stream = opj_stream_create(BUFFER_SIZE, OPJ_TRUE); if (!stream) { @@ -758,7 +760,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) } 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; @@ -769,6 +771,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, @@ -779,20 +782,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); }