From 946f6260c9b3720d7393c3fed06548d96af86b5b Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 29 Sep 2026 15:30:31 +1000 Subject: [PATCH 1/3] Add decompression bomb check to grabclipboard() on Windows --- src/PIL/ImageGrab.py | 12 ++---------- src/display.c | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/PIL/ImageGrab.py b/src/PIL/ImageGrab.py index 1ab34ad5791..547d66f11c8 100644 --- a/src/PIL/ImageGrab.py +++ b/src/PIL/ImageGrab.py @@ -180,16 +180,8 @@ def grabclipboard() -> Image.Image | list[str] | None: else: files = data[o:].decode("utf-16le").split("\0") return files[: files.index("")] - if isinstance(data, bytes): - data = io.BytesIO(data) - if fmt == "png": - from . import PngImagePlugin - - return PngImagePlugin.PngImageFile(data) - elif fmt == "DIB": - from . import BmpImagePlugin - - return BmpImagePlugin.DibImageFile(data) + if fmt in {"DIB", "PNG"}: + return Image.open(io.BytesIO(data), formats=[fmt]) return None else: if os.getenv("WAYLAND_DISPLAY"): diff --git a/src/display.c b/src/display.c index 32b3408d83c..449596978d0 100644 --- a/src/display.c +++ b/src/display.c @@ -462,7 +462,7 @@ PyImaging_GrabClipboardWin32(PyObject *self, PyObject *args) { PyObject *result; UINT format; UINT formats[] = {CF_DIB, CF_DIBV5, CF_HDROP, RegisterClipboardFormatA("PNG"), 0}; - LPCSTR format_names[] = {"DIB", "DIB", "file", "png", NULL}; + LPCSTR format_names[] = {"DIB", "DIB", "file", "PNG", NULL}; if (!OpenClipboard(NULL)) { // Maybe the clipboard is temporarily in use by another process. From 2a9e3f0386daac3a47417671ea03e1917642526c Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Tue, 29 Sep 2026 17:31:13 +1000 Subject: [PATCH 2/3] Add comment Co-authored-by: Aarni Koskela --- src/display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/display.c b/src/display.c index 449596978d0..c71f0745460 100644 --- a/src/display.c +++ b/src/display.c @@ -461,6 +461,7 @@ PyImaging_GrabClipboardWin32(PyObject *self, PyObject *args) { void *data; PyObject *result; UINT format; + // Windows clipboard format identifiers UINT formats[] = {CF_DIB, CF_DIBV5, CF_HDROP, RegisterClipboardFormatA("PNG"), 0}; LPCSTR format_names[] = {"DIB", "DIB", "file", "PNG", NULL}; From 428350527a2516cee227b04e742bb3ce6227db76 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 29 Sep 2026 17:34:24 +1000 Subject: [PATCH 3/3] Clarify link to ImageGrab --- src/PIL/ImageGrab.py | 8 ++++---- src/display.c | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/PIL/ImageGrab.py b/src/PIL/ImageGrab.py index 547d66f11c8..36e53fa9ee9 100644 --- a/src/PIL/ImageGrab.py +++ b/src/PIL/ImageGrab.py @@ -170,8 +170,8 @@ def grabclipboard() -> Image.Image | list[str] | None: data = io.BytesIO(binascii.unhexlify(p.stdout[11:-3])) return Image.open(data) elif sys.platform == "win32": - fmt, data = Image.core.grabclipboard_win32() - if fmt == "file": # CF_HDROP + format_name, data = Image.core.grabclipboard_win32() + if format_name == "file": # CF_HDROP import struct o = struct.unpack_from("I", data)[0] @@ -180,8 +180,8 @@ def grabclipboard() -> Image.Image | list[str] | None: else: files = data[o:].decode("utf-16le").split("\0") return files[: files.index("")] - if fmt in {"DIB", "PNG"}: - return Image.open(io.BytesIO(data), formats=[fmt]) + if format_name in {"DIB", "PNG"}: + return Image.open(io.BytesIO(data), formats=[format_name]) return None else: if os.getenv("WAYLAND_DISPLAY"): diff --git a/src/display.c b/src/display.c index c71f0745460..195142d465e 100644 --- a/src/display.c +++ b/src/display.c @@ -463,6 +463,7 @@ PyImaging_GrabClipboardWin32(PyObject *self, PyObject *args) { UINT format; // Windows clipboard format identifiers UINT formats[] = {CF_DIB, CF_DIBV5, CF_HDROP, RegisterClipboardFormatA("PNG"), 0}; + // For format_name in ImageGrab.py, in the same order as the formats above LPCSTR format_names[] = {"DIB", "DIB", "file", "PNG", NULL}; if (!OpenClipboard(NULL)) {