File 012-Fix-bounds-overflow-in-JPEG-2000-decoding.patch of Package python-Pillow
From cf6da6b79080a8c16984102fdc85f7ce28dca613 Mon Sep 17 00:00:00 2001
From: Eric Soroos <eric-github@soroos.net>
Date: Mon, 9 Mar 2020 22:09:49 +0000
Subject: [PATCH 1/4] Fix for OOB Read in DecodeJpeg2k
---
libImaging/Jpeg2KDecode.c | 60 +++++++++++++++++++++++++----------
1 file changed, 43 insertions(+), 17 deletions(-)
diff --git a/libImaging/Jpeg2KDecode.c b/libImaging/Jpeg2KDecode.c
index f2e437dda2..6cf8b8e9c5 100644
--- a/libImaging/Jpeg2KDecode.c
+++ b/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 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);
}
From 30443d39bd932159bbb66f88df9f34fec2100a4f Mon Sep 17 00:00:00 2001
From: Eric Soroos <eric-github@soroos.net>
Date: Mon, 9 Mar 2020 22:12:00 +0000
Subject: [PATCH 2/4] Tests for jp2 overflow
---
Tests/check_jp2_overflow.py | 29 +++++++++++++++++++++++++++++
3 files changed, 29 insertions(+)
create mode 100755 Tests/check_jp2_overflow.py
diff --git a/Tests/check_jp2_overflow.py b/Tests/check_jp2_overflow.py
new file mode 100755
index 0000000000..920474c817
--- /dev/null
+++ b/Tests/check_jp2_overflow.py
@@ -0,0 +1,29 @@
+#!/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)
+
+
From 6e86d235c8fc995d4cca9e4a79044e82810465a3 Mon Sep 17 00:00:00 2001
From: Hugo <hugovk@users.noreply.github.com>
Date: Thu, 26 Mar 2020 21:41:06 +0200
Subject: [PATCH 3/4] Format with Black
---
Tests/check_jp2_overflow.py | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/Tests/check_jp2_overflow.py b/Tests/check_jp2_overflow.py
index 920474c817..a7a343c98e 100755
--- a/Tests/check_jp2_overflow.py
+++ b/Tests/check_jp2_overflow.py
@@ -11,13 +11,12 @@
# `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.
+# version.
from PIL import Image
-repro = ('00r0_gray_l.jp2', '00r1_graya_la.jp2'
- )
+repro = ("00r0_gray_l.jp2", "00r1_graya_la.jp2")
for path in repro:
im = Image.open(path)
@@ -25,5 +24,3 @@
im.load()
except Exception as msg:
print(msg)
-
-
From c5e9de15b1b5e082626c68d443098ded36a15fc8 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Tue, 31 Mar 2020 11:09:32 +0300
Subject: [PATCH 4/4] Fix typo
---
libImaging/Jpeg2KDecode.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libImaging/Jpeg2KDecode.c b/libImaging/Jpeg2KDecode.c
index 6cf8b8e9c5..d304511d1a 100644
--- a/libImaging/Jpeg2KDecode.c
+++ b/libImaging/Jpeg2KDecode.c
@@ -721,7 +721,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
}
/* Sometimes the tile_info.datasize we get back from openjpeg
- is is less than numcomps*w*h, and we overflow in the
+ is less than numcomps*w*h, and we overflow in the
shuffle stage */
tile_width = tile_info.x1 - tile_info.x0;