74 lines
3.2 KiB
Diff
74 lines
3.2 KiB
Diff
From a2ea43a6a1d265c89f203cbad9adafa7d5ba5b4d Mon Sep 17 00:00:00 2001
|
|
From: Jacob Boerema <jgboerema@gmail.com>
|
|
Date: Wed, 22 Apr 2026 11:09:36 -0400
|
|
Subject: [PATCH] plug-ins: Fix #16205 PSP File Parsing Heap Buffer Overflow
|
|
|
|
A heap buffer overflow write vulnerability exists in GIMP's PSP file
|
|
format parser. When parsing a specially crafted .psp file, the
|
|
read_channel_data() function in file-psp.c writes beyond the bounds of
|
|
a heap-allocated buffer due to an inconsistency between the buffer
|
|
allocation size (line_width) and the read size (width). Opening a
|
|
crafted PSP file causes memory corruption during parsing.
|
|
|
|
The first part of the fix corrects the computation of the line_width,
|
|
which was incorrect for 1-bit per pixel. Since it needs to be on a
|
|
4 byte boundary, always add 3 instead of depending on bit depth.
|
|
|
|
Second, use the line_width instead of width to determine the number
|
|
of bytes to read and process because that is the correct number to use.
|
|
---
|
|
plug-ins/common/file-psp.c | 15 ++++++++++-----
|
|
1 file changed, 10 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/plug-ins/common/file-psp.c b/plug-ins/common/file-psp.c
|
|
index 0dd6ff27a1..61259e1e76 100644
|
|
--- a/plug-ins/common/file-psp.c
|
|
+++ b/plug-ins/common/file-psp.c
|
|
@@ -1530,7 +1530,7 @@ upscale_indexed_sub_8 (FILE *f,
|
|
guchar *tmpbuf, *buf_start, *src;
|
|
|
|
/* Scanlines for 1 and 4 bit only end on a 4-byte boundary. */
|
|
- line_width = (((width * bpp + 7) / 8) + bpp_zero_based) / 4 * 4;
|
|
+ line_width = (((width * bpp + 7) / 8) + 3) / 4 * 4;
|
|
buf_start = g_malloc0 (width * height);
|
|
tmpbuf = buf_start;
|
|
|
|
@@ -1576,7 +1576,7 @@ read_channel_data (FILE *f,
|
|
if (ia->depth < 8)
|
|
{
|
|
/* Scanlines for 1 and 4 bit only end on a 4-byte boundary. */
|
|
- line_width = (((width * ia->depth + 7) / 8) + ia->depth - 1) / 4 * 4;
|
|
+ line_width = ((width * ia->depth + 7) / 8 + 3) / 4 * 4;
|
|
}
|
|
else
|
|
{
|
|
@@ -1599,12 +1599,17 @@ read_channel_data (FILE *f,
|
|
{
|
|
guchar *p, *q;
|
|
|
|
- fread (buf, width, 1, f);
|
|
+ if (fread (buf, 1, line_width, f) != line_width)
|
|
+ {
|
|
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
+ _("Error reading data. Most likely unexpected end of file."));
|
|
+ return -1;
|
|
+ }
|
|
/* Contrary to what the PSP specification seems to suggest
|
|
scanlines are not stored on a 4-byte boundary. */
|
|
p = buf;
|
|
q = pixels[y] + offset;
|
|
- for (i = 0; i < width; i++)
|
|
+ for (i = 0; i < line_width; i++)
|
|
{
|
|
*q = *p++;
|
|
q += bytespp;
|
|
@@ -2097,7 +2102,7 @@ read_layer_block (FILE *f,
|
|
|
|
if (ia->depth < 8)
|
|
{
|
|
- gint min_line_width = (((width * ia->depth + 7) / 8) + (ia->depth - 1)) / 4 * 4;
|
|
+ gint min_line_width = (((width * ia->depth + 7) / 8) + 3) / 4 * 4;
|
|
|
|
/* For small widths, when depth is 1, or 4, the number of bytes
|
|
* used can be larger than the width * bytespp. Adjust for that. */
|