Bug#1133010: prepare trixie pu for CVE-2026-35444 and related parser fixes

Aquila Macedo aquila at debian.org
Tue Apr 21 04:33:48 BST 2026


I initially prepared a minimal trixie update for CVE-2026-35444 and sent 
it to the Security Team for review.

Following the discussion with the Security Team and maintainers, this 
does not appear to warrant a DSA, so I have reworked it as a trixie 
stable-proposed-updates update instead.

The update is based on 2.8.8+dfsg-1 and includes:
  - the fix for CVE-2026-35444
  - the related upstream XCF bounds-check fixes discussed during review
  - the small upstream LBM parser hardening fix


I validated the update in Salsa CI: 
https://salsa.debian.org/aquila/libsdl2-image/-/pipelines/1070508

I am filing a trixie-pu request against release.debian.org and am 
attaching the debdiff here as well for coordination/review.
-------------- next part --------------
diff -Nru libsdl2-image-2.8.8+dfsg/debian/changelog libsdl2-image-2.8.8+dfsg/debian/changelog
--- libsdl2-image-2.8.8+dfsg/debian/changelog	2025-03-04 06:59:59.000000000 -0300
+++ libsdl2-image-2.8.8+dfsg/debian/changelog	2026-04-20 23:10:27.000000000 -0300
@@ -1,3 +1,14 @@
+libsdl2-image (2.8.8+dfsg-1+deb13u1) trixie; urgency=medium
+
+  * Non-maintainer upload to stable-proposed-updates.
+  * d/patches:
+    - Import upstream patch for CVE-2026-35444
+    - Add upstream fix for LBM palette overflow
+    - Add XCF RLE decoder bounds-check fix
+    - Add XCF do_layer_surface bounds-check fix
+
+ -- Aquila Macedo Costa <aquila at debian.org>  Mon, 20 Apr 2026 23:10:27 -0300
+
 libsdl2-image (2.8.8+dfsg-1) unstable; urgency=medium
 
   * New upstream stable release
diff -Nru libsdl2-image-2.8.8+dfsg/debian/patches/CVE-2026-35444.patch libsdl2-image-2.8.8+dfsg/debian/patches/CVE-2026-35444.patch
--- libsdl2-image-2.8.8+dfsg/debian/patches/CVE-2026-35444.patch	1969-12-31 21:00:00.000000000 -0300
+++ libsdl2-image-2.8.8+dfsg/debian/patches/CVE-2026-35444.patch	2026-04-20 23:08:34.000000000 -0300
@@ -0,0 +1,85 @@
+From: Sam Lantinga <slouken at libsdl.org>
+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)
+---
+ 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 95c1526..a1683ec 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -716,20 +716,26 @@ do_layer_surface(SDL_Surface * surface, SDL_RWops * 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:
+@@ -747,20 +753,24 @@ do_layer_surface(SDL_Surface * surface, SDL_RWops * 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 libsdl2-image-2.8.8+dfsg/debian/patches/lbm-fix-heap-buffer-overflow-write-in-LBM-palette.patch libsdl2-image-2.8.8+dfsg/debian/patches/lbm-fix-heap-buffer-overflow-write-in-LBM-palette.patch
--- libsdl2-image-2.8.8+dfsg/debian/patches/lbm-fix-heap-buffer-overflow-write-in-LBM-palette.patch	1969-12-31 21:00:00.000000000 -0300
+++ libsdl2-image-2.8.8+dfsg/debian/patches/lbm-fix-heap-buffer-overflow-write-in-LBM-palette.patch	2026-04-20 23:08:34.000000000 -0300
@@ -0,0 +1,31 @@
+From: Jorge Barredo Ferreira <jorgebarredo14 at gmail.com>
+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)
+---
+ src/IMG_lbm.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/IMG_lbm.c b/src/IMG_lbm.c
+index 66215e6..bb10f90 100644
+--- a/src/IMG_lbm.c
++++ b/src/IMG_lbm.c
+@@ -232,6 +232,13 @@ SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *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 libsdl2-image-2.8.8+dfsg/debian/patches/series libsdl2-image-2.8.8+dfsg/debian/patches/series
--- libsdl2-image-2.8.8+dfsg/debian/patches/series	1969-12-31 21:00:00.000000000 -0300
+++ libsdl2-image-2.8.8+dfsg/debian/patches/series	2026-04-20 23:09:04.000000000 -0300
@@ -0,0 +1,4 @@
+CVE-2026-35444.patch
+lbm-fix-heap-buffer-overflow-write-in-LBM-palette.patch
+xcf-fix-heap-buffer-overflow-read-in-XCF-RLE-decoder.patch
+xcf-fix-heap-buffer-overflow-read-in-do_layer_surface.patch
diff -Nru libsdl2-image-2.8.8+dfsg/debian/patches/xcf-fix-heap-buffer-overflow-read-in-do_layer_surface.patch libsdl2-image-2.8.8+dfsg/debian/patches/xcf-fix-heap-buffer-overflow-read-in-do_layer_surface.patch
--- libsdl2-image-2.8.8+dfsg/debian/patches/xcf-fix-heap-buffer-overflow-read-in-do_layer_surface.patch	1969-12-31 21:00:00.000000000 -0300
+++ libsdl2-image-2.8.8+dfsg/debian/patches/xcf-fix-heap-buffer-overflow-read-in-do_layer_surface.patch	2026-04-20 23:08:34.000000000 -0300
@@ -0,0 +1,31 @@
+From: Jorge Barredo Ferreira <jorgebarredo14 at gmail.com>
+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)
+---
+ src/IMG_xcf.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/IMG_xcf.c b/src/IMG_xcf.c
+index 6b93d02..122b14f 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -703,6 +703,15 @@ do_layer_surface(SDL_Surface * surface, SDL_RWops * 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 libsdl2-image-2.8.8+dfsg/debian/patches/xcf-fix-heap-buffer-overflow-read-in-XCF-RLE-decoder.patch libsdl2-image-2.8.8+dfsg/debian/patches/xcf-fix-heap-buffer-overflow-read-in-XCF-RLE-decoder.patch
--- libsdl2-image-2.8.8+dfsg/debian/patches/xcf-fix-heap-buffer-overflow-read-in-XCF-RLE-decoder.patch	1969-12-31 21:00:00.000000000 -0300
+++ libsdl2-image-2.8.8+dfsg/debian/patches/xcf-fix-heap-buffer-overflow-read-in-XCF-RLE-decoder.patch	2026-04-20 23:08:34.000000000 -0300
@@ -0,0 +1,56 @@
+From: "Ryan C. Gordon" <icculus at icculus.org>
+Date: Mon, 6 Apr 2026 15:09:55 -0400
+Subject: xcf: Fix heap-buffer-overflow READ in XCF RLE decoder (CWE-122)
+
+Add destination pointer bounds check in load_xcf_tile_rle.
+
+This fix backported to SDL2 from 6c804082117c95c24b3d3af886319e8c21fcd8e0.
+---
+ src/IMG_xcf.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/src/IMG_xcf.c b/src/IMG_xcf.c
+index a1683ec..6b93d02 100644
+--- a/src/IMG_xcf.c
++++ b/src/IMG_xcf.c
+@@ -529,7 +529,7 @@ static unsigned char * load_xcf_tile_none (SDL_RWops * src, Uint64 len, int bpp,
+ }
+ 
+ static unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint64 len, int bpp, int x, int y) {
+-  unsigned char * load, * t, * data, * d;
++  unsigned char * load, * t, * data, * data_end, * d;
+   int i, size, count, j, length;
+   unsigned char val;
+ 
+@@ -544,6 +544,11 @@ static unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint64 len, int bpp,
+   SDL_RWread (src, t, 1, (size_t)len); /* reallen */
+ 
+   data = (unsigned char *) SDL_calloc (1, x*y*bpp);
++  if (!data) {
++    SDL_free(load);
++    return NULL;
++  }
++  data_end = data + x*y*bpp;
+   for (i = 0; i < bpp; i++) {
+     d    = data + i;
+     size = x*y;
+@@ -570,6 +575,9 @@ static unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint64 len, int bpp,
+         size -= length;
+ 
+         while (length-- > 0) {
++          if (d >= data_end) {
++            break;
++          }
+           *d = *t++;
+           d += bpp;
+         }
+@@ -592,6 +600,9 @@ static unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint64 len, int bpp,
+         val = *t++;
+ 
+         for (j = 0; j < length; j++) {
++          if (d >= data_end) {
++            break;
++          }
+           *d = val;
+           d += bpp;
+         }


More information about the Pkg-sdl-maintainers mailing list