From 691785113a1b5dc8cd42818fbd7bf29e8d6ed814 Mon Sep 17 00:00:00 2001 From: Gabriele Barbero Date: Fri, 3 Apr 2026 19:32:16 +0200 Subject: [PATCH] plug-ins: validate fcTL frame dimensions... ...against IHDR bounds in APNG loader The pixel buffer is allocated using base image dimensions from the IHDR chunk, but row write offsets were computed using the per-frame dimensions from the fcTL chunk with no bounds check. A crafted APNG file with fcTL.width > IHDR.width or fcTL.height > IHDR.height would cause out-of-bounds writes into the heap on every row after row 0. Reject fcTL frames whose dimensions or offsets extend beyond the base image dimensions before proceeding with decoding. --- plug-ins/common/file-png.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/plug-ins/common/file-png.c b/plug-ins/common/file-png.c index 0dc8b072ed..ca3e8ed0a2 100644 --- a/plug-ins/common/file-png.c +++ b/plug-ins/common/file-png.c @@ -1448,6 +1448,9 @@ load_apng_image (GFile *file, { while (! feof (fp)) { + guint region_width; + guint region_height; + png_id = read_apng_chunk (fp, &chunk); if (! png_id) { @@ -1509,6 +1512,23 @@ load_apng_image (GFile *file, apng_frame.delay_num = png_get_uint_16 (chunk.data + 28); apng_frame.delay_den = png_get_uint_16 (chunk.data + 30); + region_width = apng_frame.offset_x + apng_frame.width; + region_height = apng_frame.offset_y + apng_frame.height; + + if (region_width > (guint) gimp_image_get_width (image) || + region_height > (guint) gimp_image_get_height (image)) + { + fclose (fp); + g_free (apng_frame.pixels); + g_free (prior_pixels); + + g_set_error (error, GIMP_PLUG_IN_ERROR, 0, + _("Invalid APNG: fcTL frame dimensions " + "exceed IHDR allocation")); + + return FALSE; + } + dispose_op = chunk.data[32]; blend_op = chunk.data[33];