Version in base suite: 11.1.0-5+deb13u2 Base version: pillow_11.1.0-5+deb13u2 Target version: pillow_11.1.0-5+deb13u3 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/pillow/pillow_11.1.0-5+deb13u2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/pillow/pillow_11.1.0-5+deb13u3.dsc changelog | 8 + patches/CVE-2026-42308.patch | 20 ++ patches/CVE-2026-42310.patch | 32 ++++ patches/CVE-2026-42311.patch | 327 +++++++++++++++++++++++++++++++++++++++++++ patches/series | 3 5 files changed, 390 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp89w6rcfc/pillow_11.1.0-5+deb13u2.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp89w6rcfc/pillow_11.1.0-5+deb13u3.dsc: no acceptable signature found diff -Nru pillow-11.1.0/debian/changelog pillow-11.1.0/debian/changelog --- pillow-11.1.0/debian/changelog 2026-04-16 22:02:02.000000000 +0000 +++ pillow-11.1.0/debian/changelog 2026-06-19 18:11:46.000000000 +0000 @@ -1,3 +1,11 @@ +pillow (11.1.0-5+deb13u3) trixie-security; urgency=medium + + * CVE-2026-42308 + * CVE-2026-42310 + * CVE-2026-42311 + + -- Moritz Mühlenhoff Fri, 19 Jun 2026 20:11:46 +0200 + pillow (11.1.0-5+deb13u2) trixie-security; urgency=medium * CVE-2026-40192 diff -Nru pillow-11.1.0/debian/patches/CVE-2026-42308.patch pillow-11.1.0/debian/patches/CVE-2026-42308.patch --- pillow-11.1.0/debian/patches/CVE-2026-42308.patch 1970-01-01 00:00:00.000000000 +0000 +++ pillow-11.1.0/debian/patches/CVE-2026-42308.patch 2026-06-19 15:59:16.000000000 +0000 @@ -0,0 +1,20 @@ +From ec8272044d2adfc97a5f4b6e921c1a908318d9cb Mon Sep 17 00:00:00 2001 +From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> +Date: Wed, 1 Apr 2026 00:52:09 +0300 +Subject: [PATCH] Use long for glyph position (#9518) + +--- pillow-11.1.0.orig/src/_imagingft.c ++++ pillow-11.1.0/src/_imagingft.c +@@ -583,9 +583,9 @@ bounding_box_and_anchors( + int *x_offset, + int *y_offset + ) { +- int position; /* pen position along primary axis, in 26.6 precision */ +- int advanced; /* pen position along primary axis, in pixels */ +- int px, py; /* position of current glyph, in pixels */ ++ long position; /* pen position along primary axis, in 26.6 precision */ ++ long advanced; /* pen position along primary axis, in pixels */ ++ int px, py; /* position of current glyph, in pixels */ + int x_min, x_max, y_min, y_max; /* text bounding box, in pixels */ + int x_anchor, y_anchor; /* offset of point drawn at (0, 0), in pixels */ + int error; diff -Nru pillow-11.1.0/debian/patches/CVE-2026-42310.patch pillow-11.1.0/debian/patches/CVE-2026-42310.patch --- pillow-11.1.0/debian/patches/CVE-2026-42310.patch 1970-01-01 00:00:00.000000000 +0000 +++ pillow-11.1.0/debian/patches/CVE-2026-42310.patch 2026-06-19 15:59:56.000000000 +0000 @@ -0,0 +1,32 @@ +From 3bf614e4b8615d0ce1d5039efaf6db447fe7c468 Mon Sep 17 00:00:00 2001 +From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> +Date: Wed, 1 Apr 2026 00:03:15 +0300 +Subject: [PATCH] Raise an error if the trailer chain loops back on itself + (#9519) + +--- pillow-11.1.0.orig/src/PIL/PdfParser.py ++++ pillow-11.1.0/src/PIL/PdfParser.py +@@ -683,7 +683,9 @@ class PdfParser: + if b"Prev" in self.trailer_dict: + self.read_prev_trailer(self.trailer_dict[b"Prev"]) + +- def read_prev_trailer(self, xref_section_offset: int) -> None: ++ def read_prev_trailer( ++ self, xref_section_offset: int, processed_offsets: list[int] = [] ++ ) -> None: + assert self.buf is not None + trailer_offset = self.read_xref_table(xref_section_offset=xref_section_offset) + m = self.re_trailer_prev.search( +@@ -698,7 +700,11 @@ class PdfParser: + ) + trailer_dict = self.interpret_trailer(trailer_data) + if b"Prev" in trailer_dict: +- self.read_prev_trailer(trailer_dict[b"Prev"]) ++ processed_offsets.append(xref_section_offset) ++ check_format_condition( ++ trailer_dict[b"Prev"] not in processed_offsets, "trailer loop found" ++ ) ++ self.read_prev_trailer(trailer_dict[b"Prev"], processed_offsets) + + re_whitespace_optional = re.compile(whitespace_optional) + re_name = re.compile( diff -Nru pillow-11.1.0/debian/patches/CVE-2026-42311.patch pillow-11.1.0/debian/patches/CVE-2026-42311.patch --- pillow-11.1.0/debian/patches/CVE-2026-42311.patch 1970-01-01 00:00:00.000000000 +0000 +++ pillow-11.1.0/debian/patches/CVE-2026-42311.patch 2026-06-19 16:04:19.000000000 +0000 @@ -0,0 +1,327 @@ +Based on backport done by Marc Deslauriers for Ubuntu + +--- pillow-11.1.0.orig/Tests/test_imagefile.py ++++ pillow-11.1.0/Tests/test_imagefile.py +@@ -156,6 +156,27 @@ class TestImageFile: + with pytest.raises(SystemError, match="tile cannot extend outside image"): + ImageFile._save(im, fp, [ImageFile._Tile("raw", xy + (1, 1), 0, "1")]) + ++ def test_extents_none(self) -> None: ++ with Image.open("Tests/images/hopper.jpg") as im: ++ im.tile = [im.tile[0]._replace(extents=None)] ++ im.load() ++ ++ for extents in ("invalid", (0,), ("0", "0", "0", "0")): ++ with Image.open("Tests/images/hopper.jpg") as im: ++ im.tile = [im.tile[0]._replace(extents=extents)] # type: ignore[arg-type] ++ with pytest.raises(ValueError, match="invalid extents"): ++ im.load() ++ ++ im2 = Image.new("L", (1, 1)) ++ fp = BytesIO() ++ tile = ImageFile._Tile("jpeg", None, 0, "L") ++ ImageFile._save(im2, fp, [tile]) ++ ++ for extents in ("invalid", (0,), ("0", "0", "0", "0")): ++ tile = tile._replace(extents=extents) # type: ignore[arg-type] ++ with pytest.raises(ValueError, match="invalid extents"): ++ ImageFile._save(im2, fp, [tile]) ++ + def test_no_format(self) -> None: + buf = BytesIO(b"\x00" * 255) + +@@ -299,7 +320,20 @@ class TestPyDecoder(CodecsTest): + assert MockPyDecoder.last.state.xsize == 200 + assert MockPyDecoder.last.state.ysize == 200 + +- def test_negsize(self) -> None: ++ def test_negative_offset(self) -> None: ++ buf = BytesIO(b"\x00" * 255) ++ ++ im = MockImageFile(buf) ++ im.tile = [ImageFile._Tile("MOCK", (-10, yoff, xsize, ysize), 32, None)] ++ ++ with pytest.raises(ValueError): ++ im.load() ++ ++ im.tile = [ImageFile._Tile("MOCK", (xoff, -10, xsize, ysize), 32, None)] ++ with pytest.raises(ValueError): ++ im.load() ++ ++ def test_negative_size(self) -> None: + buf = BytesIO(b"\x00" * 255) + + im = MockImageFile(buf) +@@ -377,7 +411,39 @@ class TestPyEncoder(CodecsTest): + assert MockPyEncoder.last.state.xsize == 200 + assert MockPyEncoder.last.state.ysize == 200 + +- def test_negsize(self) -> None: ++ def test_negative_offset(self) -> None: ++ buf = BytesIO(b"\x00" * 255) ++ ++ im = MockImageFile(buf) ++ ++ fp = BytesIO() ++ MockPyEncoder.last = None ++ with pytest.raises(ValueError): ++ ImageFile._save( ++ im, ++ fp, ++ [ ++ ImageFile._Tile( ++ "MOCK", (-10, yoff, xoff + xsize, yoff + ysize), 0, "RGB" ++ ) ++ ], ++ ) ++ last: MockPyEncoder | None = MockPyEncoder.last ++ assert last ++ assert last.cleanup_called ++ ++ with pytest.raises(ValueError): ++ ImageFile._save( ++ im, ++ fp, ++ [ ++ ImageFile._Tile( ++ "MOCK", (xoff, -10, xoff + xsize, yoff + ysize), 0, "RGB" ++ ) ++ ], ++ ) ++ ++ def test_negative_size(self) -> None: + buf = BytesIO(b"\x00" * 255) + + im = MockImageFile(buf) +--- pillow-11.1.0.orig/src/PIL/Image.py ++++ pillow-11.1.0/src/PIL/Image.py +@@ -800,7 +800,7 @@ class Image: + + # unpack data + e = _getencoder(self.mode, encoder_name, encoder_args) +- e.setimage(self.im) ++ e.setimage(self.im, (0, 0) + self.size) + + bufsize = max(65536, self.size[0] * 4) # see RawEncode.c + +@@ -869,7 +869,7 @@ class Image: + + # unpack data + d = _getdecoder(self.mode, decoder_name, decoder_args) +- d.setimage(self.im) ++ d.setimage(self.im, (0, 0) + self.size) + s = d.decode(data) + + if s[0] >= 0: +--- pillow-11.1.0.orig/src/PIL/ImageFile.py ++++ pillow-11.1.0/src/PIL/ImageFile.py +@@ -696,28 +696,22 @@ class PyCodec: + + if extents: + (x0, y0, x1, y1) = extents +- else: +- (x0, y0, x1, y1) = (0, 0, 0, 0) + +- if x0 == 0 and x1 == 0: +- self.state.xsize, self.state.ysize = self.im.size +- else: ++ if x0 < 0 or y0 < 0 or x1 > self.im.size[0] or y1 > self.im.size[1]: ++ msg = "Tile cannot extend outside image" ++ raise ValueError(msg) ++ + self.state.xoff = x0 + self.state.yoff = y0 + self.state.xsize = x1 - x0 + self.state.ysize = y1 - y0 ++ else: ++ self.state.xsize, self.state.ysize = self.im.size + + if self.state.xsize <= 0 or self.state.ysize <= 0: + msg = "Size cannot be negative" + raise ValueError(msg) + +- if ( +- self.state.xsize + self.state.xoff > self.im.size[0] +- or self.state.ysize + self.state.yoff > self.im.size[1] +- ): +- msg = "Tile cannot extend outside image" +- raise ValueError(msg) +- + + class PyDecoder(PyCodec): + """ +--- pillow-11.1.0.orig/src/decode.c ++++ pillow-11.1.0/src/decode.c +@@ -155,44 +155,65 @@ PyImaging_AsImaging(PyObject *op); + + static PyObject * + _setimage(ImagingDecoderObject *decoder, PyObject *args) { +- PyObject *op; ++ PyObject *op, *extents; + Imaging im; + ImagingCodecState state; + int x0, y0, x1, y1; + +- x0 = y0 = x1 = y1 = 0; +- + /* FIXME: should publish the ImagingType descriptor */ +- if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1)) { ++ if (!PyArg_ParseTuple(args, "OO", &op, &extents)) { + return NULL; + } + im = PyImaging_AsImaging(op); + if (!im) { + return NULL; + } +- +- decoder->im = im; +- +- state = &decoder->state; +- +- /* Setup decoding tile extent */ +- if (x0 == 0 && x1 == 0) { +- state->xsize = im->xsize; +- state->ysize = im->ysize; ++ if (extents == Py_None) { ++ x0 = 0; ++ y0 = 0; ++ x1 = im->xsize; ++ y1 = im->ysize; + } else { +- state->xoff = x0; +- state->yoff = y0; +- state->xsize = x1 - x0; +- state->ysize = y1 - y0; ++ if (!PyTuple_Check(extents) || PyTuple_GET_SIZE(extents) != 4) { ++ PyErr_SetString(PyExc_ValueError, "invalid extents"); ++ return NULL; ++ } ++ for (int i = 0; i < 4; i++) { ++ PyObject *extent = PyTuple_GetItem(extents, i); ++ if (!PyLong_Check(extent)) { ++ PyErr_SetString(PyExc_ValueError, "invalid extents"); ++ return NULL; ++ } ++ int e = (int)PyLong_AsLong(extent); ++ ++ if (i == 0) { ++ x0 = e; ++ } else if (i == 1) { ++ y0 = e; ++ } else if (i == 2) { ++ x1 = e; ++ } else { ++ y1 = e; ++ } ++ } + } + +- 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) { ++ 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; ++ ++ /* Setup decoding tile extent */ ++ state->xoff = x0; ++ state->yoff = y0; ++ state->xsize = x1 - x0; ++ state->ysize = y1 - y0; ++ + /* Allocate memory buffer (if bits field is set) */ + if (state->bits > 0) { + if (!state->bytes) { +--- pillow-11.1.0.orig/src/encode.c ++++ pillow-11.1.0/src/encode.c +@@ -221,45 +221,63 @@ PyImaging_AsImaging(PyObject *op); + + static PyObject * + _setimage(ImagingEncoderObject *encoder, PyObject *args) { +- PyObject *op; ++ PyObject *op, *extents; + Imaging im; + ImagingCodecState state; + Py_ssize_t x0, y0, x1, y1; + +- /* Define where image data should be stored */ +- +- x0 = y0 = x1 = y1 = 0; +- + /* FIXME: should publish the ImagingType descriptor */ +- if (!PyArg_ParseTuple(args, "O|(nnnn)", &op, &x0, &y0, &x1, &y1)) { ++ if (!PyArg_ParseTuple(args, "OO", &op, &extents)) { + return NULL; + } + im = PyImaging_AsImaging(op); + if (!im) { + return NULL; + } +- +- encoder->im = im; +- +- state = &encoder->state; +- +- if (x0 == 0 && x1 == 0) { +- state->xsize = im->xsize; +- state->ysize = im->ysize; ++ if (extents == Py_None) { ++ x0 = 0; ++ y0 = 0; ++ x1 = im->xsize; ++ y1 = im->ysize; + } else { +- state->xoff = x0; +- state->yoff = y0; +- state->xsize = x1 - x0; +- state->ysize = y1 - y0; ++ if (!PyTuple_Check(extents) || PyTuple_GET_SIZE(extents) != 4) { ++ PyErr_SetString(PyExc_ValueError, "invalid extents"); ++ return NULL; ++ } ++ for (int i = 0; i < 4; i++) { ++ PyObject *extent = PyTuple_GetItem(extents, i); ++ if (!PyLong_Check(extent)) { ++ PyErr_SetString(PyExc_ValueError, "invalid extents"); ++ return NULL; ++ } ++ Py_ssize_t e = (Py_ssize_t)PyLong_AsLong(extent); ++ ++ if (i == 0) { ++ x0 = e; ++ } else if (i == 1) { ++ y0 = e; ++ } else if (i == 2) { ++ x1 = e; ++ } else { ++ y1 = e; ++ } ++ } + } + +- 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) { ++ 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; ++ ++ state->xoff = x0; ++ state->yoff = y0; ++ state->xsize = x1 - x0; ++ state->ysize = y1 - y0; ++ + /* Allocate memory buffer (if bits field is set) */ + if (state->bits > 0) { + if (state->xsize > ((INT_MAX / state->bits) - 7)) { diff -Nru pillow-11.1.0/debian/patches/series pillow-11.1.0/debian/patches/series --- pillow-11.1.0/debian/patches/series 2026-04-16 22:02:02.000000000 +0000 +++ pillow-11.1.0/debian/patches/series 2026-06-19 16:03:34.000000000 +0000 @@ -7,3 +7,6 @@ intersphinx-local.diff CVE-2026-25990.patch CVE-2026-40192.patch +CVE-2026-42308.patch +CVE-2026-42310.patch +CVE-2026-42311.patch