From 54ba4db542ad3c7b918812a4e2d69c27735a3199 Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Wed, 11 Feb 2026 10:24:50 +1100 Subject: [PATCH] Fix OOB Write with invalid tile extents (#9427) Co-authored-by: Eric Soroos --- Tests/images/psd-oob-write-x.psd | Bin 0 -> 1126 bytes Tests/images/psd-oob-write-y.psd | Bin 0 -> 1126 bytes Tests/images/psd-oob-write.psd | Bin 0 -> 37212 bytes Tests/test_file_psd.py | 17 +++++++++++++++++ Tests/test_imagefile.py | 7 +++++++ docs/releasenotes/12.1.1.rst | 24 ++++++++++++++++++++++++ docs/releasenotes/index.rst | 1 + src/decode.c | 3 ++- src/encode.c | 3 ++- 9 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 Tests/images/psd-oob-write-x.psd create mode 100644 Tests/images/psd-oob-write-y.psd create mode 100644 Tests/images/psd-oob-write.psd create mode 100644 docs/releasenotes/12.1.1.rst diff --git a/Tests/images/psd-oob-write-x.psd b/Tests/images/psd-oob-write-x.psd new file mode 100644 index 0000000000000000000000000000000000000000..86359f4cb7e826a69a8e69a4b85947498ec18923 GIT binary patch literal 1126 zcma)5J!lkB5dL=WC-F>3z$=1SY;juU8Wp`VZp09|z;cO@XbSh|ZgXUJ@7TRX4pIuX z0SkW`qZT&S+FIBOg5VE`wTL!~HWJqFz0GA0$%PEez3@QFhrkNP zAuvV#TGJPoazEr{TAAgkKpC9EmzOT6P~@#DuSJ zUAwN0ePiq~9H(A1?WlXnFzSMFu>5&1Gvi%VuLMjIY_sPYVGiO`^5AHhE<`36}Q zS#8*4Tt){zOv#6s0b?jxZ==?^v(ltY=s@91lKeUijNJuxx0B@W<0RRA0^~jeuY!!< z*#T<5Y2VIll}EtTZQ#Z0%x2vKUfuy_K6TB|l>Z~PO>MP+pU;5FHQ>ZspmZbc8-2o$ zryqb7_Nx8{c<>N7<1+X9h9@HB$WwFjZhIlIc)`9T z6kgJL@)8%N^RTLn0liQ+`%UH?s%V)+x7mhM3JvQ>aRNJcNX=y?XE}2!cN#o<;Pc=tauOPS24s{WiA%d1_AHZ7(DiFOZT@ z1~9EBFYiTZJFF^Wz(S#J_M6N(Qqe4Z1=LwlA5GSi`m##ox9j~=340;B^S{69u$O-T DuU)5R literal 0 HcmV?d00001 diff --git a/Tests/images/psd-oob-write.psd b/Tests/images/psd-oob-write.psd new file mode 100644 index 0000000000000000000000000000000000000000..65a4472cf263a94277952c06903709afb0c8213f GIT binary patch literal 37212 zcmeI!I|{-;5CG8e2f;Js6jo_XXCVk)LDH$<2|S2L%6V+#=3`?OM1sW|nCvc@* zMR_>JEc#fa;nZao?RL4W`O0t5&U7$GptyKKZoln@|5fB*pk1ildPmiYor z3jqQI2oNCfHv$oNL4W`O0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ t009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+0D&I~yZ}A8uQLDu literal 0 HcmV?d00001 diff --git a/Tests/test_file_psd.py b/Tests/test_file_psd.py index 8f2ca58a6..8a2636dfe 100644 --- a/Tests/test_file_psd.py +++ b/Tests/test_file_psd.py @@ -182,3 +182,20 @@ def test_layer_crashes(test_file: str) -> None: assert isinstance(im, PsdImagePlugin.PsdImageFile) with pytest.raises(SyntaxError): im.layers + + +@pytest.mark.parametrize( + "test_file", + [ + "Tests/images/psd-oob-write.psd", + "Tests/images/psd-oob-write-x.psd", + "Tests/images/psd-oob-write-y.psd", + ], +) +def test_bounds_crash(test_file: str) -> None: + with Image.open(test_file) as im: + assert isinstance(im, PsdImagePlugin.PsdImageFile) + im.seek(im.n_frames) + + with pytest.raises(ValueError): + im.load() diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py index 8a0abbd39..6656ee506 100644 --- a/Tests/test_imagefile.py +++ b/Tests/test_imagefile.py @@ -163,6 +163,13 @@ class TestImageFile: with pytest.raises(ValueError, match="Tile offset cannot be negative"): im.load() + @pytest.mark.parametrize("xy", ((-1, 0), (0, -1))) + def test_negative_tile_extents(self, xy: tuple[int, int]) -> None: + im = Image.new("1", (1, 1)) + fp = BytesIO() + with pytest.raises(SystemError, match="tile cannot extend outside image"): + ImageFile._save(im, fp, [ImageFile._Tile("raw", xy + (1, 1), 0, "1")]) + def test_no_format(self) -> None: buf = BytesIO(b"\x00" * 255) diff --git a/docs/releasenotes/12.1.1.rst b/docs/releasenotes/12.1.1.rst new file mode 100644 index 000000000..9c119ceb8 --- /dev/null +++ b/docs/releasenotes/12.1.1.rst @@ -0,0 +1,24 @@ +12.1.1 +------ + +Security +======== + +:cve:`2021-25289`: Fix OOB write with invalid tile extents +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Check that tile extents do not use negative x or y offsets when decoding or encoding, +and raise an error if they do, rather than allowing an OOB write. + +An out-of-bounds write may be triggered when opening a specially crafted PSD image. +This only affects Pillow >= 10.3.0. Reported by +`Yarden Porat `__. + +Other changes +============= + +Patch libavif for svt-av1 4.0 compatibility +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A patch has been added to ``depends/install_libavif.sh``, to allow libavif 1.3.0 to be +compatible with the recently released svt-av1 4.0.0. diff --git a/docs/releasenotes/index.rst b/docs/releasenotes/index.rst index 4b25bb6a2..690be2072 100644 --- a/docs/releasenotes/index.rst +++ b/docs/releasenotes/index.rst @@ -15,6 +15,7 @@ expected to be backported to earlier versions. :maxdepth: 2 versioning + 12.1.1 12.1.0 12.0.0 11.3.0 diff --git a/src/decode.c b/src/decode.c index 051623ed4..7ec461c0e 100644 --- a/src/decode.c +++ b/src/decode.c @@ -186,7 +186,8 @@ _setimage(ImagingDecoderObject *decoder, PyObject *args) { state->ysize = y1 - y0; } - if (state->xsize <= 0 || state->xsize + state->xoff > (int)im->xsize || + 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; diff --git a/src/encode.c b/src/encode.c index 513309c8d..06e4a0893 100644 --- a/src/encode.c +++ b/src/encode.c @@ -254,7 +254,8 @@ _setimage(ImagingEncoderObject *encoder, PyObject *args) { state->ysize = y1 - y0; } - if (state->xsize <= 0 || state->xsize + state->xoff > im->xsize || + 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;