From 042e27792026460badbe49664c02fe181e95cb2b Mon Sep 17 00:00:00 2001
From: Gyorgy Sarvari <skandigraun@gmail.com>
Date: Wed, 12 Nov 2025 13:25:44 +0000
Subject: [PATCH] plug-ins: Mitigate ZDI-CAN-28248 for JP2 images

From: Alx Sa <cmyk.student@gmail.com>

Resolves #15285
Per the report, it's possible to exceed the size of the pixel buffer
with a high precision_scaled value, as we size it to the width * bpp.
This patch includes precision_scaled in the allocation calculation.
It also adds a g_size_checked_mul () check to ensure there's no
overflow, and moves the pixel and buffer memory freeing to occur
in the out section so that it always runs even on failure.

CVE: CVE-2025-14425
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/gimp/-/commit/cd1c88a0364ad1444c06536731972a99bd8643fd]
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
---
 plug-ins/common/file-jp2-load.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/plug-ins/common/file-jp2-load.c b/plug-ins/common/file-jp2-load.c
index 064b616..604313a 100644
--- a/plug-ins/common/file-jp2-load.c
+++ b/plug-ins/common/file-jp2-load.c
@@ -1045,14 +1045,15 @@ load_image (GimpProcedure     *procedure,
   GimpColorProfile    *profile    = NULL;
   GimpImage           *gimp_image = NULL;
   GimpLayer           *layer;
+  GeglBuffer          *buffer     = NULL;
+  guchar              *pixels     = NULL;
+  gsize                pixels_size;
   GimpImageType        image_type;
   GimpImageBaseType    base_type;
   gint                 width;
   gint                 height;
   gint                 num_components;
-  GeglBuffer          *buffer;
   gint                 i, j, k, it;
-  guchar              *pixels;
   const Babl          *file_format;
   gint                 bpp;
   GimpPrecision        image_precision;
@@ -1318,7 +1319,15 @@ load_image (GimpProcedure     *procedure,
   bpp = babl_format_get_bytes_per_pixel (file_format);
 
   buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
-  pixels = g_new0 (guchar, width * bpp);
+
+  if (! g_size_checked_mul (&pixels_size, width, (bpp * (precision_scaled / 8))))
+    {
+      g_set_error (error, GIMP_PLUG_IN_ERROR, 0,
+                   _("Defined row size is too large in JP2 image '%s'."),
+                   gimp_file_get_utf8_name (file));
+      goto out;
+    }
+  pixels = g_new0 (guchar, pixels_size);
 
   for (i = 0; i < height; i++)
     {
@@ -1344,13 +1353,13 @@ load_image (GimpProcedure     *procedure,
         gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i, width, 1), 0,
                          file_format, pixels, GEGL_AUTO_ROWSTRIDE);
     }
-
-  g_free (pixels);
-
-  g_object_unref (buffer);
   gimp_progress_update (1.0);
 
  out:
+  if (pixels)
+    g_free (pixels);
+  if (buffer)
+    g_object_unref (buffer);
   if (profile)
     g_object_unref (profile);
   if (image)
