On Sun, 23 Aug 2026 at 14:56:33 +0100, Simon McVittie wrote:
Fix CVE-2026-35444 and various other out-of-bounds accesses when parsing
malformed/crafted image files
Related to https://bugs.debian.org/1134510 for libsdl2-image, an older
branch of the same codebase.
debdiff attached, also in
<https://people.debian.org/~smcv/13.7/libsdl3-image/>.
A functionally-equivalent test build (differing only in the changelog)
is in <https://people.debian.org/~smcv/13.7/libsdl3-image/testbuild/>.
smcv
diffstat for libsdl3-image-3.2.4+ds libsdl3-image-3.2.4+ds
debian/changelog | 34 +++
debian/control | 2
debian/gbp.conf | 2
debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-RLE-decoder-CWE-122.patch | 49 +++++
debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-do_layer_surface-CWE.patch | 33 +++
debian/patches/Fix-heap-buffer-overflow-WRITE-in-LBM-palette-CWE-122.patch | 33 +++
debian/patches/Fix-heap-underflow-WRITE-in-XCF-read_string-CWE-787.patch | 32 +++
debian/patches/Fixed-out-of-bound-read-in-GIF-decoder.patch | 29 +++
debian/patches/Fixed-out-of-bounds-read-in-XCF-image-loader-thanks-Sebas.patch | 88 ++++++++++
debian/patches/IMG_xcf.c-read_string-add-back-the-positive-string-size-c.patch | 24 ++
debian/patches/series | 11 +
debian/patches/tga-reject-images-with-zero-width-or-height.patch | 39 ++++
debian/patches/xcf-Added-an-SDL_SetError-when-rejecting-out-of-bounds-ti.patch | 23 ++
debian/patches/xcf-fix-null-pointer-dereference-when-read_xcf_hierarchy-.patch | 38 ++++
debian/patches/xpm-Remove-QUICK_COLORHASH-replace-it-with-inline-code-th.patch | 44 +++++
src/IMG_gif.c | 6
src/IMG_lbm.c | 7
src/IMG_tga.c | 4
src/IMG_xcf.c | 84 +++++++--
src/IMG_xpm.c | 11 -
20 files changed, 562 insertions(+), 31 deletions(-)
diff -Nru libsdl3-image-3.2.4+ds/debian/changelog libsdl3-image-3.2.4+ds/debian/changelog
--- libsdl3-image-3.2.4+ds/debian/changelog 2025-03-04 10:00:27.000000000 +0000
+++ libsdl3-image-3.2.4+ds/debian/changelog 2026-08-23 14:44:26.000000000 +0100
@@ -1,3 +1,37 @@
+libsdl3-image (3.2.4+ds-1+deb13u1) trixie; urgency=medium
+
+ * d/control, d/gbp.conf: Branch for trixie
+ * d/patches: Add a malformed-image parser robustness fix from 3.4.2:
+ - d/p/Fixed-out-of-bounds-read-in-XCF-image-loader-thanks-Sebas.patch:
+ Avoid an out-of-bounds read when loading invalid XCF images
+ (CVE-2026-35444, same issue as #1133010 in libsdl2-image)
+ * d/patches: Add selected upstream malformed-image parser robustness
+ fixes from 3.4.4:
+ - d/p/xpm-Remove-QUICK_COLORHASH-replace-it-with-inline-code-th.patch:
+ Check XPM colour hash entries before use
+ - d/p/Fix-heap-buffer-overflow-WRITE-in-LBM-palette-CWE-122.patch
+ Avoid an out-of-bounds write when parsing LBM images
+ - d/p/Fix-heap-underflow-WRITE-in-XCF-read_string-CWE-787.patch
+ Avoid an out-of-bounds write if XCF files contain a zero-length string
+ - d/p/Fix-heap-buffer-overflow-READ-in-XCF-do_layer_surface-CWE.patch,
+ d/p/xcf-Added-an-SDL_SetError-when-rejecting-out-of-bounds-ti.patch:
+ Avoid an out-of-bounds read when parsing XCF file tile data, and
+ report the resulting error correctly
+ - d/p/Fix-heap-buffer-overflow-READ-in-XCF-RLE-decoder-CWE-122.patch:
+ Avoid an out-of-bounds read when parsing XCF files with RLE encoding
+ - d/p/xcf-fix-null-pointer-dereference-when-read_xcf_hierarchy-.patch:
+ Check XCF hierarchy read failures before dereferencing
+ - d/p/tga-reject-images-with-zero-width-or-height.patch:
+ Reject zero-sized TGA images as invalid
+ - d/p/Fixed-out-of-bound-read-in-GIF-decoder.patch:
+ Avoid out-of-bounds reads in the GIF decoder
+ * d/patches: Add an additional parser robustness fix from upstream git:
+ - d/p/IMG_xcf.c-read_string-add-back-the-positive-string-size-c.patch
+ Harden XCF parsing against extremely long strings
+ * Thanks to Aquila Macedo Costa
+
+ -- Simon McVittie <[email protected]> Sun, 23 Aug 2026 14:44:26 +0100
+
libsdl3-image (3.2.4+ds-1) unstable; urgency=medium
* New upstream stable release
diff -Nru libsdl3-image-3.2.4+ds/debian/control libsdl3-image-3.2.4+ds/debian/control
--- libsdl3-image-3.2.4+ds/debian/control 2025-03-04 10:00:27.000000000 +0000
+++ libsdl3-image-3.2.4+ds/debian/control 2026-08-23 14:44:26.000000000 +0100
@@ -17,7 +17,7 @@
Standards-Version: 4.7.2
Homepage: https://github.com/libsdl-org/SDL_image
Vcs-Browser: https://salsa.debian.org/sdl-team/libsdl3-image
-Vcs-Git: https://salsa.debian.org/sdl-team/libsdl3-image.git
+Vcs-Git: https://salsa.debian.org/sdl-team/libsdl3-image.git -b debian/trixie
Package: libsdl3-image0
Architecture: any
diff -Nru libsdl3-image-3.2.4+ds/debian/gbp.conf libsdl3-image-3.2.4+ds/debian/gbp.conf
--- libsdl3-image-3.2.4+ds/debian/gbp.conf 2025-03-04 10:00:27.000000000 +0000
+++ libsdl3-image-3.2.4+ds/debian/gbp.conf 2026-08-23 14:44:26.000000000 +0100
@@ -1,4 +1,4 @@
[DEFAULT]
pristine-tar = True
-debian-branch = debian/latest
+debian-branch = debian/trixie
upstream-branch = upstream/latest
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/Fixed-out-of-bound-read-in-GIF-decoder.patch libsdl3-image-3.2.4+ds/debian/patches/Fixed-out-of-bound-read-in-GIF-decoder.patch
--- libsdl3-image-3.2.4+ds/debian/patches/Fixed-out-of-bound-read-in-GIF-decoder.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/Fixed-out-of-bound-read-in-GIF-decoder.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,29 @@
+From: Sam Lantinga <[email protected]>
+Date: Wed, 29 Apr 2026 08:18:09 -0700
+Subject: Fixed out of bound read in GIF decoder
+
+(cherry picked from commit e2b258927d11438cbf4ee55a5c4ff059a6e32d08)
+
+Bug: https://github.com/libsdl-org/SDL_image/issues/724
+Origin: upstream, 3.4.4, commit:377d1fbb2ec4ea73e0b99fb926b38cee8e1afea1
+---
+ src/IMG_gif.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/IMG_gif.c b/src/IMG_gif.c
+index 7775ca5..0124f0f 100644
+--- a/src/IMG_gif.c
++++ b/src/IMG_gif.c
+@@ -466,8 +466,10 @@ GetCode(SDL_IOStream *src, int code_size, int flag, State_t * state)
+ RWSetMsg("ran off the end of my bits");
+ return -1;
+ }
+- state->buf[0] = state->buf[state->last_byte - 2];
+- state->buf[1] = state->buf[state->last_byte - 1];
++ if (state->last_byte > 2) {
++ state->buf[0] = state->buf[state->last_byte - 2];
++ state->buf[1] = state->buf[state->last_byte - 1];
++ }
+
+ if ((ret = GetDataBlock(src, &state->buf[2], state)) > 0)
+ count = (unsigned char) ret;
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/Fixed-out-of-bounds-read-in-XCF-image-loader-thanks-Sebas.patch libsdl3-image-3.2.4+ds/debian/patches/Fixed-out-of-bounds-read-in-XCF-image-loader-thanks-Sebas.patch
--- libsdl3-image-3.2.4+ds/debian/patches/Fixed-out-of-bounds-read-in-XCF-image-loader-thanks-Sebas.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/Fixed-out-of-bounds-read-in-XCF-image-loader-thanks-Sebas.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,88 @@
+From: Sam Lantinga <[email protected]>
+Date: Thu, 2 Apr 2026 08:41:46 -0700
+Subject: Fixed out of bounds read in XCF image loader (thanks @Sebasteuo!)
+
+(cherry picked from commit f55d589ba5de11c724afcdcae80b56bf26d91d15)
+
+Origin: upstream, 3.4.2, commit:c3f6f82d44e416f5d7e31e2692b9ff452c2b183a
+Bug-CVE: https://security-tracker.debian.org/tracker/CVE-2026-35444
+---
+ src/IMG_xcf.c | 50 ++++++++++++++++++++++++++++++--------------------
+ 1 file changed, 30 insertions(+), 20 deletions(-)
+
+diff --git a/src/IMG_xcf.c b/src/IMG_xcf.c
+index dd991cf..df1df2d 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -808,20 +808,26 @@ do_layer_surface(SDL_Surface *surface, SDL_IOStream *src, xcf_header *head, xcf_
+ switch (head->image_type) {
+ case IMAGE_INDEXED:
+ for (x = tx; x < tx + ox; x++) {
+- *row = ((Uint32)(head->cm_map[*p8 * 3]) << 16);
+- *row |= ((Uint32)(head->cm_map[*p8 * 3 + 1]) << 8);
+- *row |= ((Uint32)(head->cm_map[*p8++ * 3 + 2]) << 0);
+- *row |= ((Uint32)*p8++ << 24);
+- row++;
++ Uint8 c = *p8++;
++ Uint8 a = *p8++;
++ if (c < head->cm_num) {
++ *row++ = ((Uint32)(head->cm_map[c * 3]) << 16) |
++ ((Uint32)(head->cm_map[c * 3 + 1]) << 8) |
++ ((Uint32)(head->cm_map[c * 3 + 2]) << 0) |
++ ((Uint32)a << 24);
++ } else {
++ *row++ = 0;
++ }
+ }
+ break;
+ case IMAGE_GREYSCALE:
+ for (x = tx; x < tx + ox; x++) {
+- *row = ((Uint32)*p8 << 16);
+- *row |= ((Uint32)*p8 << 8);
+- *row |= ((Uint32)*p8++ << 0);
+- *row |= ((Uint32)*p8++ << 24);
+- row++;
++ Uint8 c = *p8++;
++ Uint8 a = *p8++;
++ *row++ = ((Uint32)c << 16) |
++ ((Uint32)c << 8) |
++ ((Uint32)c << 0) |
++ ((Uint32)a << 24);
+ }
+ break;
+ default:
+@@ -839,20 +845,24 @@ do_layer_surface(SDL_Surface *surface, SDL_IOStream *src, xcf_header *head, xcf_
+ switch (head->image_type) {
+ case IMAGE_INDEXED:
+ for (x = tx; x < tx + ox; x++) {
+- *row++ = 0xFF000000
+- | ((Uint32)(head->cm_map[*p8 * 3]) << 16)
+- | ((Uint32)(head->cm_map[*p8 * 3 + 1]) << 8)
+- | ((Uint32)(head->cm_map[*p8 * 3 + 2]) << 0);
+- p8++;
++ Uint8 c = *p8++;
++ if (c < head->cm_num) {
++ *row++ = 0xFF000000 |
++ ((Uint32)(head->cm_map[c * 3]) << 16) |
++ ((Uint32)(head->cm_map[c * 3 + 1]) << 8) |
++ ((Uint32)(head->cm_map[c * 3 + 2]) << 0);
++ } else {
++ *row++ = 0;
++ }
+ }
+ break;
+ case IMAGE_GREYSCALE:
+ for (x = tx; x < tx + ox; x++) {
+- *row++ = 0xFF000000
+- | (((Uint32)(*p8)) << 16)
+- | (((Uint32)(*p8)) << 8)
+- | (((Uint32)(*p8)) << 0);
+- ++p8;
++ Uint8 c = *p8++;
++ *row++ = 0xFF000000 |
++ (((Uint32)c) << 16) |
++ (((Uint32)c) << 8) |
++ (((Uint32)c) << 0);
+ }
+ break;
+ default:
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-do_layer_surface-CWE.patch libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-do_layer_surface-CWE.patch
--- libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-do_layer_surface-CWE.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-do_layer_surface-CWE.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,33 @@
+From: Jorge Barredo Ferreira <[email protected]>
+Date: Mon, 6 Apr 2026 19:30:53 +0200
+Subject: Fix heap-buffer-overflow READ in XCF do_layer_surface (CWE-122)
+
+Add bounds check for tile buffer access in do_layer_surface.
+
+(cherry picked from commit 5b0d414cae99b2e162a1e46ecba4fcd7ac8c5d85)
+
+Origin: upstream, 3.4.4, commit:cc81c460428b5032e190445910eae786a433231e
+---
+ src/IMG_xcf.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/IMG_xcf.c b/src/IMG_xcf.c
+index ef1136a..3fe4c7a 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -791,6 +791,15 @@ do_layer_surface(SDL_Surface *surface, SDL_IOStream *src, xcf_header *head, xcf_
+
+ p8 = tile;
+ p = (Uint32 *) p8;
++
++ /* Bounds check: reject layer if tile data exceeds buffer */
++ if ((Uint64)ox * oy * hierarchy->bpp > (Uint64)(hierarchy->width * hierarchy->height * hierarchy->bpp)) {
++ free_xcf_tile(tile);
++ free_xcf_level(level);
++ free_xcf_hierarchy(hierarchy);
++ return 1;
++ }
++
+ for (y = ty; y < ty + oy; y++) {
+ if ((y >= (Uint32)surface->h) || ((tx+ox) > (Uint32)surface->w)) {
+ break;
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-RLE-decoder-CWE-122.patch libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-RLE-decoder-CWE-122.patch
--- libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-RLE-decoder-CWE-122.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-READ-in-XCF-RLE-decoder-CWE-122.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,49 @@
+From: Jorge Barredo Ferreira <[email protected]>
+Date: Mon, 6 Apr 2026 19:31:36 +0200
+Subject: Fix heap-buffer-overflow READ in XCF RLE decoder (CWE-122)
+
+Add destination pointer bounds check in load_xcf_tile_rle.
+
+(cherry picked from commit 6c804082117c95c24b3d3af886319e8c21fcd8e0)
+
+Origin: upstream, 3.4.4, commit:2c9d2d84b000a6a6892fefbd6effaf3452a4609d
+---
+ src/IMG_xcf.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/src/IMG_xcf.c b/src/IMG_xcf.c
+index b65061e..482c2a5 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -640,6 +640,11 @@ static unsigned char *load_xcf_tile_rle(SDL_IOStream *src, size_t len, int bpp,
+ }
+
+ data = (unsigned char *)SDL_calloc(1, x*y*bpp);
++ if (!data) {
++ SDL_free(load);
++ return NULL;
++ }
++ unsigned char *data_end = data + x*y*bpp;
+ for (i = 0; i < bpp; i++) {
+ d = data + i;
+ size = x*y;
+@@ -664,6 +669,9 @@ static unsigned char *load_xcf_tile_rle(SDL_IOStream *src, size_t len, int bpp,
+ size -= length;
+
+ while (length-- > 0) {
++ if (d >= data_end) {
++ break;
++ }
+ *d = *t++;
+ d += bpp;
+ }
+@@ -685,6 +693,9 @@ static unsigned char *load_xcf_tile_rle(SDL_IOStream *src, size_t len, int bpp,
+ val = *t++;
+
+ for (j = 0; j < length; j++) {
++ if (d >= data_end) {
++ break;
++ }
+ *d = val;
+ d += bpp;
+ }
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-WRITE-in-LBM-palette-CWE-122.patch libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-WRITE-in-LBM-palette-CWE-122.patch
--- libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-WRITE-in-LBM-palette-CWE-122.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-buffer-overflow-WRITE-in-LBM-palette-CWE-122.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,33 @@
+From: Jorge Barredo Ferreira <[email protected]>
+Date: Mon, 6 Apr 2026 19:29:38 +0200
+Subject: Fix heap-buffer-overflow WRITE in LBM palette (CWE-122)
+
+When nbplanes > 8 without HAM flag, nbrcolorsfinal exceeds 256,
+causing writes past the palette buffer. Reject nbplanes > 8 for
+paletted images.
+
+(cherry picked from commit 2fe0746733c9f280d2c344bce231dd70fdf3bdb8)
+
+Origin: upstream, 3.4.4, commit:20a4b7686bfeda6551c739f4a4f1feaf63979375
+---
+ src/IMG_lbm.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/IMG_lbm.c b/src/IMG_lbm.c
+index 577ca19..af6ba78 100644
+--- a/src/IMG_lbm.c
++++ b/src/IMG_lbm.c
+@@ -234,6 +234,13 @@ SDL_Surface *IMG_LoadLBM_IO(SDL_IOStream *src )
+
+ nbplanes = bmhd.planes;
+
++ /* Sanity check: nbplanes must not exceed 8 for paletted images.
++ Higher values cause 1<<nbplanes to exceed the 256-entry palette. */
++ if ( !pbm && nbplanes > 8 && nbplanes != 24 && flagHAM == 0 ) {
++ SDL_SetError("LBM: invalid number of bitplanes (%u)", nbplanes);
++ goto done;
++ }
++
+ if ( pbm ) /* File format : 'Packed Bitmap' */
+ {
+ bytesperline *= 8;
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-underflow-WRITE-in-XCF-read_string-CWE-787.patch libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-underflow-WRITE-in-XCF-read_string-CWE-787.patch
--- libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-underflow-WRITE-in-XCF-read_string-CWE-787.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/Fix-heap-underflow-WRITE-in-XCF-read_string-CWE-787.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,32 @@
+From: Jorge Barredo Ferreira <[email protected]>
+Date: Mon, 6 Apr 2026 19:30:06 +0200
+Subject: Fix heap underflow WRITE in XCF read_string (CWE-787)
+
+When string length is 0, data[-1] writes before heap allocation.
+Guard tmp == 0 before the null-terminator write.
+
+(cherry picked from commit becd2b6fb242ba9ac60c66a4f3f77d1849aa2a02)
+
+Origin: upstream, 3.4.4, commit:bfaefe1bcdf8731c8e343b3bbcb15e2a445ea318
+---
+ src/IMG_xcf.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/IMG_xcf.c b/src/IMG_xcf.c
+index df1df2d..ef1136a 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -237,6 +237,13 @@ static char *read_string(SDL_IOStream *src)
+ char *data = NULL;
+
+ if (SDL_ReadU32BE(src, &tmp)) {
++ if (tmp == 0) {
++ data = (char *) SDL_malloc(1);
++ if (data) {
++ data[0] = 0;
++ }
++ return data;
++ }
+ remaining = SDL_GetIOSize(src) - SDL_TellIO(src);
+ if (tmp <= remaining) {
+ data = (char *)SDL_malloc(tmp);
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/IMG_xcf.c-read_string-add-back-the-positive-string-size-c.patch libsdl3-image-3.2.4+ds/debian/patches/IMG_xcf.c-read_string-add-back-the-positive-string-size-c.patch
--- libsdl3-image-3.2.4+ds/debian/patches/IMG_xcf.c-read_string-add-back-the-positive-string-size-c.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/IMG_xcf.c-read_string-add-back-the-positive-string-size-c.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,24 @@
+From: Ozkan Sezer <[email protected]>
+Date: Wed, 13 May 2026 14:51:28 +0300
+Subject: IMG_xcf.c (read_string): add back the positive string size check
+
+(cherry picked from commit 2eda043e2c4cabd565f7d8e04893fb53efd857ef)
+
+Origin: upstream, 3.4.6, commit:15cb42b7fd270aa5dc12d097f964d24c33d7f18b
+---
+ src/IMG_xcf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/IMG_xcf.c b/src/IMG_xcf.c
+index e0360f9..9ea21ec 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -245,7 +245,7 @@ static char *read_string(SDL_IOStream *src)
+ return data;
+ }
+ remaining = SDL_GetIOSize(src) - SDL_TellIO(src);
+- if (tmp <= remaining) {
++ if ((Sint32)tmp > 0 && tmp <= remaining) {
+ data = (char *)SDL_malloc(tmp);
+ if (data) {
+ if (SDL_ReadIO(src, data, tmp) == tmp) {
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/series libsdl3-image-3.2.4+ds/debian/patches/series
--- libsdl3-image-3.2.4+ds/debian/patches/series 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/series 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,11 @@
+Fixed-out-of-bounds-read-in-XCF-image-loader-thanks-Sebas.patch
+xpm-Remove-QUICK_COLORHASH-replace-it-with-inline-code-th.patch
+Fix-heap-buffer-overflow-WRITE-in-LBM-palette-CWE-122.patch
+Fix-heap-underflow-WRITE-in-XCF-read_string-CWE-787.patch
+Fix-heap-buffer-overflow-READ-in-XCF-do_layer_surface-CWE.patch
+xcf-Added-an-SDL_SetError-when-rejecting-out-of-bounds-ti.patch
+Fix-heap-buffer-overflow-READ-in-XCF-RLE-decoder-CWE-122.patch
+xcf-fix-null-pointer-dereference-when-read_xcf_hierarchy-.patch
+tga-reject-images-with-zero-width-or-height.patch
+Fixed-out-of-bound-read-in-GIF-decoder.patch
+IMG_xcf.c-read_string-add-back-the-positive-string-size-c.patch
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/tga-reject-images-with-zero-width-or-height.patch libsdl3-image-3.2.4+ds/debian/patches/tga-reject-images-with-zero-width-or-height.patch
--- libsdl3-image-3.2.4+ds/debian/patches/tga-reject-images-with-zero-width-or-height.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/tga-reject-images-with-zero-width-or-height.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,39 @@
+From: Jorge Barredo Ferreira <[email protected]>
+Date: Thu, 23 Apr 2026 11:20:40 -0700
+Subject: tga: reject images with zero width or height
+
+When SDL_CreateSurface() is called with w=0 or h=0 it may return a
+non-NULL surface but with a NULL pixels pointer (zero-size allocation).
+Subsequent code at IMG_LoadTGA_IO accesses img->pixels unconditionally,
+resulting in undefined behavior: UBSan reports "applying zero offset to
+null pointer" for the expression (Uint8*)img->pixels + (h-1)*img->pitch
+when pitch is 0.
+
+Reject zero-dimension images early before creating the surface.
+
+CWE-476 (NULL Pointer Dereference)
+Found by: NORAI fuzzer (libFuzzer + UBSan)
+PoC: poc_sdl007_tga_null_pixels.tga
+
+(cherry picked from commit 4ba58feebaf87ad80b8ab3971ea8f82132884c54)
+
+Origin: upstream, 3.4.4, commit:f5c0968ec14318ab489740877f1e66d32b014fbc
+---
+ src/IMG_tga.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/IMG_tga.c b/src/IMG_tga.c
+index 92ace3d..1593cdb 100644
+--- a/src/IMG_tga.c
++++ b/src/IMG_tga.c
+@@ -178,6 +178,10 @@ SDL_Surface *IMG_LoadTGA_IO(SDL_IOStream *src)
+
+ w = LE16(hdr.width);
+ h = LE16(hdr.height);
++ if (w == 0 || h == 0) {
++ error = "TGA image with zero width or height";
++ goto error;
++ }
+ img = SDL_CreateSurface(w, h, format);
+ if (img == NULL) {
+ error = "Out of memory";
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/xcf-Added-an-SDL_SetError-when-rejecting-out-of-bounds-ti.patch libsdl3-image-3.2.4+ds/debian/patches/xcf-Added-an-SDL_SetError-when-rejecting-out-of-bounds-ti.patch
--- libsdl3-image-3.2.4+ds/debian/patches/xcf-Added-an-SDL_SetError-when-rejecting-out-of-bounds-ti.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/xcf-Added-an-SDL_SetError-when-rejecting-out-of-bounds-ti.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,23 @@
+From: "Ryan C. Gordon" <[email protected]>
+Date: Mon, 6 Apr 2026 14:58:56 -0400
+Subject: xcf: Added an SDL_SetError when rejecting out-of-bounds tile data.
+
+(cherry picked from commit 1aedddcbd205c4e1ea0f99fdb2c785acc8e2489b)
+
+Origin: upstream, 3.4.4, commit:58133e6df69a0107e1ab34e8e564a1ab8706edb8
+---
+ src/IMG_xcf.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/IMG_xcf.c b/src/IMG_xcf.c
+index 3fe4c7a..b65061e 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -794,6 +794,7 @@ do_layer_surface(SDL_Surface *surface, SDL_IOStream *src, xcf_header *head, xcf_
+
+ /* Bounds check: reject layer if tile data exceeds buffer */
+ if ((Uint64)ox * oy * hierarchy->bpp > (Uint64)(hierarchy->width * hierarchy->height * hierarchy->bpp)) {
++ SDL_SetError("Gimp image invalid tile");
+ free_xcf_tile(tile);
+ free_xcf_level(level);
+ free_xcf_hierarchy(hierarchy);
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/xcf-fix-null-pointer-dereference-when-read_xcf_hierarchy-.patch libsdl3-image-3.2.4+ds/debian/patches/xcf-fix-null-pointer-dereference-when-read_xcf_hierarchy-.patch
--- libsdl3-image-3.2.4+ds/debian/patches/xcf-fix-null-pointer-dereference-when-read_xcf_hierarchy-.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/xcf-fix-null-pointer-dereference-when-read_xcf_hierarchy-.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,38 @@
+From: Jorge Barredo Ferreira <[email protected]>
+Date: Tue, 7 Apr 2026 17:16:58 +0200
+Subject: xcf: fix null pointer dereference when read_xcf_hierarchy() fails
+
+read_xcf_hierarchy() can return NULL when SDL_calloc() fails or when
+SDL_ReadU32BE() fails to read the width/height/bpp fields. The return
+value was not checked before dereferencing hierarchy->bpp at line 755
+in do_layer_surface(), leading to a null pointer dereference.
+
+Add a NULL check immediately after the call to return early with an
+error in that case.
+
+CWE-476 (NULL Pointer Dereference)
+Found by: NORAI fuzzer (libFuzzer + ASan/UBSan)
+PoC: poc_sdl006_xcf_hierarchy_null.xcf
+
+(cherry picked from commit 336fb104494815984250c40f8ee6bd1325b7ba1e)
+
+Origin: upstream, 3.4.4, commit:1e81a7f9618a244964387bc18f1451c759841931
+---
+ src/IMG_xcf.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/IMG_xcf.c b/src/IMG_xcf.c
+index 482c2a5..e0360f9 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -753,6 +753,10 @@ do_layer_surface(SDL_Surface *surface, SDL_IOStream *src, xcf_header *head, xcf_
+ return 1;
+ }
+ hierarchy = read_xcf_hierarchy(src, head);
++ if (!hierarchy) {
++ SDL_SetError("Failed to read XCF image hierarchy");
++ return 1;
++ }
+
+ if (hierarchy->bpp > 4) { /* unsupported. */
+ SDL_SetError("Unknown Gimp image bpp (%u)", (unsigned int) hierarchy->bpp);
diff -Nru libsdl3-image-3.2.4+ds/debian/patches/xpm-Remove-QUICK_COLORHASH-replace-it-with-inline-code-th.patch libsdl3-image-3.2.4+ds/debian/patches/xpm-Remove-QUICK_COLORHASH-replace-it-with-inline-code-th.patch
--- libsdl3-image-3.2.4+ds/debian/patches/xpm-Remove-QUICK_COLORHASH-replace-it-with-inline-code-th.patch 1970-01-01 01:00:00.000000000 +0100
+++ libsdl3-image-3.2.4+ds/debian/patches/xpm-Remove-QUICK_COLORHASH-replace-it-with-inline-code-th.patch 2026-08-23 14:44:26.000000000 +0100
@@ -0,0 +1,44 @@
+From: "Ryan C. Gordon" <[email protected]>
+Date: Mon, 6 Apr 2026 14:24:56 -0400
+Subject: xpm: Remove QUICK_COLORHASH,
+ replace it with inline code that checks for NULL.
+
+Closes #721.
+
+(cherry picked from commit bc17bc7c6a2767e342ebb6d3fd37c8e323c8dd70)
+
+Origin: upstream, 3.4.4, commit:8ffec045db5cd309f89b07edb7196815b3ba4a08
+Bug: https://github.com/libsdl-org/SDL_image/pull/721
+---
+ src/IMG_xpm.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/src/IMG_xpm.c b/src/IMG_xpm.c
+index 8b67f59..47a56f1 100644
+--- a/src/IMG_xpm.c
++++ b/src/IMG_xpm.c
+@@ -159,9 +159,6 @@ static int add_colorhash(struct color_hash *hash,
+ return 1;
+ }
+
+-/* fast lookup that works if cpp == 1 */
+-#define QUICK_COLORHASH(hash, key) ((hash)->table[*(Uint8 *)(key)]->color)
+-
+ static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp)
+ {
+ struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
+@@ -1144,9 +1141,11 @@ static SDL_Surface *load_xpm(char **xpm, SDL_IOStream *src, bool force_32bit)
+ if (indexed) {
+ /* optimization for some common cases */
+ if (cpp == 1)
+- for (x = 0; x < w; x++)
+- dst[x] = (Uint8)QUICK_COLORHASH(colors,
+- line + x);
++ for (x = 0; x < w; x++) {
++ /* fast lookup that works if cpp == 1 */
++ const struct hash_entry *entry = colors->table[*(Uint8 *)(line + x)];
++ dst[x] = entry ? (Uint8) entry->color : 0;
++ }
+ else
+ for (x = 0; x < w; x++)
+ dst[x] = (Uint8)get_colorhash(colors,
diff -Nru libsdl3-image-3.2.4+ds/src/IMG_gif.c libsdl3-image-3.2.4+ds/src/IMG_gif.c
--- libsdl3-image-3.2.4+ds/src/IMG_gif.c 2025-01-01 15:38:05.000000000 +0000
+++ libsdl3-image-3.2.4+ds/src/IMG_gif.c 2026-08-23 14:49:29.000000000 +0100
@@ -466,8 +466,10 @@
RWSetMsg("ran off the end of my bits");
return -1;
}
- state->buf[0] = state->buf[state->last_byte - 2];
- state->buf[1] = state->buf[state->last_byte - 1];
+ if (state->last_byte > 2) {
+ state->buf[0] = state->buf[state->last_byte - 2];
+ state->buf[1] = state->buf[state->last_byte - 1];
+ }
if ((ret = GetDataBlock(src, &state->buf[2], state)) > 0)
count = (unsigned char) ret;
diff -Nru libsdl3-image-3.2.4+ds/src/IMG_lbm.c libsdl3-image-3.2.4+ds/src/IMG_lbm.c
--- libsdl3-image-3.2.4+ds/src/IMG_lbm.c 2025-01-01 15:38:05.000000000 +0000
+++ libsdl3-image-3.2.4+ds/src/IMG_lbm.c 2026-08-23 14:49:29.000000000 +0100
@@ -234,6 +234,13 @@
nbplanes = bmhd.planes;
+ /* Sanity check: nbplanes must not exceed 8 for paletted images.
+ Higher values cause 1<<nbplanes to exceed the 256-entry palette. */
+ if ( !pbm && nbplanes > 8 && nbplanes != 24 && flagHAM == 0 ) {
+ SDL_SetError("LBM: invalid number of bitplanes (%u)", nbplanes);
+ goto done;
+ }
+
if ( pbm ) /* File format : 'Packed Bitmap' */
{
bytesperline *= 8;
diff -Nru libsdl3-image-3.2.4+ds/src/IMG_tga.c libsdl3-image-3.2.4+ds/src/IMG_tga.c
--- libsdl3-image-3.2.4+ds/src/IMG_tga.c 2025-01-01 15:38:05.000000000 +0000
+++ libsdl3-image-3.2.4+ds/src/IMG_tga.c 2026-08-23 14:49:29.000000000 +0100
@@ -178,6 +178,10 @@
w = LE16(hdr.width);
h = LE16(hdr.height);
+ if (w == 0 || h == 0) {
+ error = "TGA image with zero width or height";
+ goto error;
+ }
img = SDL_CreateSurface(w, h, format);
if (img == NULL) {
error = "Out of memory";
diff -Nru libsdl3-image-3.2.4+ds/src/IMG_xcf.c libsdl3-image-3.2.4+ds/src/IMG_xcf.c
--- libsdl3-image-3.2.4+ds/src/IMG_xcf.c 2025-01-01 15:38:05.000000000 +0000
+++ libsdl3-image-3.2.4+ds/src/IMG_xcf.c 2026-08-23 14:49:29.000000000 +0100
@@ -237,8 +237,15 @@
char *data = NULL;
if (SDL_ReadU32BE(src, &tmp)) {
+ if (tmp == 0) {
+ data = (char *) SDL_malloc(1);
+ if (data) {
+ data[0] = 0;
+ }
+ return data;
+ }
remaining = SDL_GetIOSize(src) - SDL_TellIO(src);
- if (tmp <= remaining) {
+ if ((Sint32)tmp > 0 && tmp <= remaining) {
data = (char *)SDL_malloc(tmp);
if (data) {
if (SDL_ReadIO(src, data, tmp) == tmp) {
@@ -633,6 +640,11 @@
}
data = (unsigned char *)SDL_calloc(1, x*y*bpp);
+ if (!data) {
+ SDL_free(load);
+ return NULL;
+ }
+ unsigned char *data_end = data + x*y*bpp;
for (i = 0; i < bpp; i++) {
d = data + i;
size = x*y;
@@ -657,6 +669,9 @@
size -= length;
while (length-- > 0) {
+ if (d >= data_end) {
+ break;
+ }
*d = *t++;
d += bpp;
}
@@ -678,6 +693,9 @@
val = *t++;
for (j = 0; j < length; j++) {
+ if (d >= data_end) {
+ break;
+ }
*d = val;
d += bpp;
}
@@ -735,6 +753,10 @@
return 1;
}
hierarchy = read_xcf_hierarchy(src, head);
+ if (!hierarchy) {
+ SDL_SetError("Failed to read XCF image hierarchy");
+ return 1;
+ }
if (hierarchy->bpp > 4) { /* unsupported. */
SDL_SetError("Unknown Gimp image bpp (%u)", (unsigned int) hierarchy->bpp);
@@ -784,6 +806,16 @@
p8 = tile;
p = (Uint32 *) p8;
+
+ /* Bounds check: reject layer if tile data exceeds buffer */
+ if ((Uint64)ox * oy * hierarchy->bpp > (Uint64)(hierarchy->width * hierarchy->height * hierarchy->bpp)) {
+ SDL_SetError("Gimp image invalid tile");
+ free_xcf_tile(tile);
+ free_xcf_level(level);
+ free_xcf_hierarchy(hierarchy);
+ return 1;
+ }
+
for (y = ty; y < ty + oy; y++) {
if ((y >= (Uint32)surface->h) || ((tx+ox) > (Uint32)surface->w)) {
break;
@@ -808,20 +840,26 @@
switch (head->image_type) {
case IMAGE_INDEXED:
for (x = tx; x < tx + ox; x++) {
- *row = ((Uint32)(head->cm_map[*p8 * 3]) << 16);
- *row |= ((Uint32)(head->cm_map[*p8 * 3 + 1]) << 8);
- *row |= ((Uint32)(head->cm_map[*p8++ * 3 + 2]) << 0);
- *row |= ((Uint32)*p8++ << 24);
- row++;
+ Uint8 c = *p8++;
+ Uint8 a = *p8++;
+ if (c < head->cm_num) {
+ *row++ = ((Uint32)(head->cm_map[c * 3]) << 16) |
+ ((Uint32)(head->cm_map[c * 3 + 1]) << 8) |
+ ((Uint32)(head->cm_map[c * 3 + 2]) << 0) |
+ ((Uint32)a << 24);
+ } else {
+ *row++ = 0;
+ }
}
break;
case IMAGE_GREYSCALE:
for (x = tx; x < tx + ox; x++) {
- *row = ((Uint32)*p8 << 16);
- *row |= ((Uint32)*p8 << 8);
- *row |= ((Uint32)*p8++ << 0);
- *row |= ((Uint32)*p8++ << 24);
- row++;
+ Uint8 c = *p8++;
+ Uint8 a = *p8++;
+ *row++ = ((Uint32)c << 16) |
+ ((Uint32)c << 8) |
+ ((Uint32)c << 0) |
+ ((Uint32)a << 24);
}
break;
default:
@@ -839,20 +877,24 @@
switch (head->image_type) {
case IMAGE_INDEXED:
for (x = tx; x < tx + ox; x++) {
- *row++ = 0xFF000000
- | ((Uint32)(head->cm_map[*p8 * 3]) << 16)
- | ((Uint32)(head->cm_map[*p8 * 3 + 1]) << 8)
- | ((Uint32)(head->cm_map[*p8 * 3 + 2]) << 0);
- p8++;
+ Uint8 c = *p8++;
+ if (c < head->cm_num) {
+ *row++ = 0xFF000000 |
+ ((Uint32)(head->cm_map[c * 3]) << 16) |
+ ((Uint32)(head->cm_map[c * 3 + 1]) << 8) |
+ ((Uint32)(head->cm_map[c * 3 + 2]) << 0);
+ } else {
+ *row++ = 0;
+ }
}
break;
case IMAGE_GREYSCALE:
for (x = tx; x < tx + ox; x++) {
- *row++ = 0xFF000000
- | (((Uint32)(*p8)) << 16)
- | (((Uint32)(*p8)) << 8)
- | (((Uint32)(*p8)) << 0);
- ++p8;
+ Uint8 c = *p8++;
+ *row++ = 0xFF000000 |
+ (((Uint32)c) << 16) |
+ (((Uint32)c) << 8) |
+ (((Uint32)c) << 0);
}
break;
default:
diff -Nru libsdl3-image-3.2.4+ds/src/IMG_xpm.c libsdl3-image-3.2.4+ds/src/IMG_xpm.c
--- libsdl3-image-3.2.4+ds/src/IMG_xpm.c 2025-01-01 15:38:05.000000000 +0000
+++ libsdl3-image-3.2.4+ds/src/IMG_xpm.c 2026-08-23 14:49:29.000000000 +0100
@@ -159,9 +159,6 @@
return 1;
}
-/* fast lookup that works if cpp == 1 */
-#define QUICK_COLORHASH(hash, key) ((hash)->table[*(Uint8 *)(key)]->color)
-
static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp)
{
struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
@@ -1144,9 +1141,11 @@
if (indexed) {
/* optimization for some common cases */
if (cpp == 1)
- for (x = 0; x < w; x++)
- dst[x] = (Uint8)QUICK_COLORHASH(colors,
- line + x);
+ for (x = 0; x < w; x++) {
+ /* fast lookup that works if cpp == 1 */
+ const struct hash_entry *entry = colors->table[*(Uint8 *)(line + x)];
+ dst[x] = entry ? (Uint8) entry->color : 0;
+ }
else
for (x = 0; x < w; x++)
dst[x] = (Uint8)get_colorhash(colors,