From 4bada07dc6c24319edd1eb76f1dd28d968d58207 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 18 Feb 2026 22:24:03 +1100 Subject: [PATCH] Avoid overflow by not adding extents together --- Tests/images/psd-oob-write-overflow.psd | Bin 0 -> 496 bytes Tests/test_file_psd.py | 2 ++ src/decode.c | 13 ++++++------- src/encode.c | 12 +++++------- 4 files changed, 13 insertions(+), 14 deletions(-) create mode 100644 Tests/images/psd-oob-write-overflow.psd diff --git a/Tests/images/psd-oob-write-overflow.psd b/Tests/images/psd-oob-write-overflow.psd new file mode 100644 index 0000000000000000000000000000000000000000..c2bb10d614ed8a2130a28338f474b74f6e67d486 GIT binary patch literal 496 zcmcC;3J7LkWPkt=%>~9Ba4{g4F$IVd7?>c6z$8Q!L|>YPlc#T9eo^j!gaWWk1BA~7 bHETJhx&}G`21d@^a4>k8z_6l2U^D;#tMlDs literal 0 HcmV?d00001 diff --git a/Tests/test_file_psd.py b/Tests/test_file_psd.py index 3b145b139..9964a68e1 100644 --- a/Tests/test_file_psd.py +++ b/Tests/test_file_psd.py @@ -195,11 +195,13 @@ def test_layer_crashes(test_file: str) -> None: "Tests/images/psd-oob-write.psd", "Tests/images/psd-oob-write-x.psd", "Tests/images/psd-oob-write-y.psd", + "Tests/images/psd-oob-write-overflow.psd", ], ) def test_bounds_crash(test_file: str) -> None: with Image.open(test_file) as im: assert isinstance(im, PsdImagePlugin.PsdImageFile) + im.load() im.seek(im.n_frames) with pytest.raises(ValueError): diff --git a/src/decode.c b/src/decode.c index cda4ce702..2268b3533 100644 --- a/src/decode.c +++ b/src/decode.c @@ -171,6 +171,12 @@ _setimage(ImagingDecoderObject *decoder, PyObject *args) { return NULL; } + if (x0 < 0 || y0 < 0 || x1 <= x0 || y1 <= y0 || x1 > (int)im->xsize || + y1 > (int)im->ysize) { + PyErr_SetString(PyExc_ValueError, "tile cannot extend outside image"); + return NULL; + } + decoder->im = im; state = &decoder->state; @@ -181,13 +187,6 @@ _setimage(ImagingDecoderObject *decoder, PyObject *args) { state->xsize = x1 - x0; state->ysize = y1 - y0; - if (state->xoff < 0 || state->xsize <= 0 || - state->xsize + state->xoff > (int)im->xsize || state->yoff < 0 || - state->ysize <= 0 || state->ysize + state->yoff > (int)im->ysize) { - PyErr_SetString(PyExc_ValueError, "tile cannot extend outside image"); - return NULL; - } - /* Allocate memory buffer (if bits field is set) */ if (state->bits > 0) { if (!state->bytes) { diff --git a/src/encode.c b/src/encode.c index 1fc31404d..02356d564 100644 --- a/src/encode.c +++ b/src/encode.c @@ -244,6 +244,11 @@ _setimage(ImagingEncoderObject *encoder, PyObject *args) { return NULL; } + if (x0 < 0 || y0 < 0 || x1 <= x0 || y1 <= y0 || x1 > im->xsize || y1 > im->ysize) { + PyErr_SetString(PyExc_SystemError, "tile cannot extend outside image"); + return NULL; + } + encoder->im = im; state = &encoder->state; @@ -253,13 +258,6 @@ _setimage(ImagingEncoderObject *encoder, PyObject *args) { state->xsize = x1 - x0; state->ysize = y1 - y0; - if (state->xoff < 0 || state->xsize <= 0 || - state->xsize + state->xoff > im->xsize || state->yoff < 0 || - state->ysize <= 0 || state->ysize + state->yoff > im->ysize) { - PyErr_SetString(PyExc_SystemError, "tile cannot extend outside image"); - return NULL; - } - /* Allocate memory buffer (if bits field is set) */ if (state->bits > 0) { if (state->xsize > ((INT_MAX / state->bits) - 7)) {