gimp/SOURCES/gimp-CVE-2026-4887.patch
2026-06-24 01:32:16 -04:00

129 lines
4.4 KiB
Diff

From aabce89271a9943a43bda9225aa43fc524f1c8a4 Mon Sep 17 00:00:00 2001
From: Jacob Boerema <jgboerema@gmail.com>
Date: Sun, 8 Mar 2026 15:18:33 -0400
Subject: [PATCH] plug-ins:: fix #15960 PCX buffer overflow
A buffer overflow in the PCX reader was reported.
The +1 was added in commit da217088d0fab77b7a696e782f6e2fb3b597f48f
to allow loading where the images have an off by 1 value. However,
this leaves the problem that allocated buffers may be 1 byte too small.
Because we prefer to keep loading as many images as possible, we choose
not to return an error. Instead we allocate 1 extra byte for the
line buffers.
In addition to that, we add check for valid values of bpp and error
out early when invalid.
If the bytesperline value is off by more than 1, we output a warning
message and use the manually computed value instead.
Additionally add a comment that we need to fix a British English
word in a string after string freeze.
---
plug-ins/common/file-pcx.c | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/plug-ins/common/file-pcx.c b/plug-ins/common/file-pcx.c
index 3cf1070d2d4..276b568e78b 100644
--- a/plug-ins/common/file-pcx.c
+++ b/plug-ins/common/file-pcx.c
@@ -632,7 +632,7 @@ load_image (GimpProcedure *procedure,
GError **error)
{
GeglBuffer *buffer;
- guint16 offset_x, offset_y, bytesperline;
+ guint16 offset_x, offset_y, bytesperline, computed_bytesperline;
gint32 width, height;
guint16 resolution_x, resolution_y;
GimpImage *image;
@@ -681,13 +681,29 @@ load_image (GimpProcedure *procedure,
height);
return NULL;
}
- if ((bytesperline + 1) < ((width * pcx_header.bpp + 7) / 8) ||
- bytesperline == 0)
+
+ if (pcx_header.bpp != 1 && pcx_header.bpp != 2 && pcx_header.bpp != 4 &&
+ pcx_header.bpp != 8)
{
+ /* FIXME: After string freeze this should be changed to a more descriptive error. */
g_set_error (error, GIMP_PLUG_IN_ERROR, 0,
- _("Invalid number of bytes per line in PCX header"));
+ _("Unusual PCX flavour, giving up"));
return NULL;
}
+
+ /* Some legacy images have incorrect values for bytesperline, that are
+ * off by 1. To be able to load these, we will allow a difference of 1 here.
+ * However, that means we need to allocate 1 more byte than officially
+ * required to make sure we don't cause a buffer overrun.
+ * For larger differences we will compute the value of bytesperline.
+ */
+ computed_bytesperline = (width * pcx_header.bpp + 7) / 8;
+ if (bytesperline + 1 < computed_bytesperline || bytesperline == 0)
+ {
+ g_message (_("Invalid number of bytes per line in PCX header"));
+ bytesperline = (width * pcx_header.bpp + 7) / 8;
+ }
+
if ((resolution_x < 1) || (resolution_x > GIMP_MAX_RESOLUTION) ||
(resolution_y < 1) || (resolution_y > GIMP_MAX_RESOLUTION))
{
@@ -838,6 +854,7 @@ load_image (GimpProcedure *procedure,
}
else
{
+ /* FIXME: flavour is British English, should be flavor. */
g_set_error (error, GIMP_PLUG_IN_ERROR, 0,
_("Unusual PCX flavour, giving up"));
g_object_unref (buffer);
@@ -889,7 +906,7 @@ load_8 (FILE *fp,
guint16 bytes)
{
gint row;
- guchar *line = g_new (guchar, bytes);
+ guchar *line = g_new0 (guchar, bytes + 1);
for (row = 0; row < height; buf += width, ++row)
{
@@ -910,7 +927,7 @@ load_24 (FILE *fp,
guint8 planes)
{
gint x, y, c;
- guchar *line = g_new (guchar, bytes);
+ guchar *line = g_new0 (guchar, bytes + 1);
for (y = 0; y < height; buf += width * planes, ++y)
{
@@ -936,7 +953,7 @@ load_1 (FILE *fp,
guint16 bytes)
{
gint x, y;
- guchar *line = g_new (guchar, bytes);
+ guchar *line = g_new0 (guchar, bytes + 1);
for (y = 0; y < height; buf += width, ++y)
{
@@ -962,7 +979,7 @@ load_4 (FILE *fp,
guint16 bytes)
{
gint x, y, c;
- guchar *line = g_new (guchar, bytes);
+ guchar *line = g_new0 (guchar, bytes + 1);
for (y = 0; y < height; buf += width, ++y)
{
@@ -993,7 +1010,7 @@ load_sub_8 (FILE *fp,
guint16 bytes)
{
gint x, y, c, b;
- guchar *line = g_new (guchar, bytes);
+ guchar *line = g_new0 (guchar, bytes + 1);
gint real_bpp = bpp - 1;
gint current_bit = 0;
--
GitLab