SDL_image: Fixed out of bounds read in XCF image loader (thanks @Sebasteuo!) (fa9ff)

From fa9ffb8cced56aba2a2ab27d7c4388278e6b70c0 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 2 Apr 2026 08:41:46 -0700
Subject: [PATCH] Fixed out of bounds read in XCF image loader (thanks
 @Sebasteuo!)

(cherry picked from commit f55d589ba5de11c724afcdcae80b56bf26d91d15)
(cherry picked from commit a1a06276a51ca7e6e63908b200df8a278d8c5039)
---
 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 95c1526c4..a1683ece5 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: