From 657b68d20456eaeb9639976f328827195ff41383 Mon Sep 17 00:00:00 2001
From: Alex Tutubalin <lexa@lexa.ru>
Date: Sun, 1 Mar 2026 19:54:16 +0300
Subject: [PATCH] Fix for TALOS-2026-2358

---
 src/decoders/unpack_thumb.cpp |  2 ++
 src/x3f/x3f_parse_process.cpp | 20 ++++++++++++++++++--
 src/x3f/x3f_utils_patched.cpp |  7 +++++++
 3 files changed, 27 insertions(+), 2 deletions(-)

Index: LibRaw-0.21.4/src/decoders/unpack_thumb.cpp
===================================================================
--- LibRaw-0.21.4.orig/src/decoders/unpack_thumb.cpp
+++ LibRaw-0.21.4/src/decoders/unpack_thumb.cpp
@@ -387,6 +387,8 @@ int LibRaw::unpack_thumb(void)
       {
         x3f_thumb_loader();
         SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+		if (!T.twidth && !T.theight)
+			return LIBRAW_NO_THUMBNAIL;
         return 0;
       }
 #endif
Index: LibRaw-0.21.4/src/x3f/x3f_parse_process.cpp
===================================================================
--- LibRaw-0.21.4.orig/src/x3f/x3f_parse_process.cpp
+++ LibRaw-0.21.4/src/x3f/x3f_parse_process.cpp
@@ -322,6 +322,7 @@ void LibRaw::x3f_thumb_loader()
 {
   try
   {
+    INT64 checked_size = x3f_thumb_size(); // This value was checked at upper level?
     x3f_t *x3f = (x3f_t *)_x3f_data;
     if (!x3f)
       return; // No data pointer set
@@ -339,12 +340,24 @@ void LibRaw::x3f_thumb_loader()
     imgdata.thumbnail.tcolors = 3;
     if (imgdata.thumbnail.tformat == LIBRAW_THUMBNAIL_JPEG)
     {
-      imgdata.thumbnail.thumb = (char *)malloc(ID->data_size);
+	  INT64 alloc_size = ID->data_size;
+	  if ((alloc_size > 2 * checked_size) || (alloc_size > 1024LL * 1024LL * LIBRAW_MAX_THUMBNAIL_MB))
+		  throw LIBRAW_EXCEPTION_TOOBIG;
+	  if(alloc_size < 64LL)
+        throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+	  imgdata.thumbnail.thumb = (char *)malloc(ID->data_size);
       memmove(imgdata.thumbnail.thumb, ID->data, ID->data_size);
       imgdata.thumbnail.tlength = ID->data_size;
     }
     else if (imgdata.thumbnail.tformat == LIBRAW_THUMBNAIL_BITMAP)
     {
+      INT64 alloc_size = INT64(ID->columns) * INT64(ID->rows) * 3LL;
+	  if ((alloc_size > 2 * checked_size) ||
+          (alloc_size > 1024LL * 1024LL * LIBRAW_MAX_THUMBNAIL_MB)) throw LIBRAW_EXCEPTION_TOOBIG;
+      if (alloc_size < 64LL)
+        throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
       imgdata.thumbnail.tlength = ID->columns * ID->rows * 3;
       imgdata.thumbnail.thumb = (char *)malloc(ID->columns * ID->rows * 3);
       char *src0 = (char *)ID->data;
@@ -361,7 +374,10 @@ void LibRaw::x3f_thumb_loader()
   }
   catch (...)
   {
-    // do nothing
+    // no rethrow: handled at upper level
+    imgdata.thumbnail.twidth = 0;
+    imgdata.thumbnail.theight = 0;
+    imgdata.thumbnail.tcolors = 0;
   }
 }
 
Index: LibRaw-0.21.4/src/x3f/x3f_utils_patched.cpp
===================================================================
--- LibRaw-0.21.4.orig/src/x3f/x3f_utils_patched.cpp
+++ LibRaw-0.21.4/src/x3f/x3f_utils_patched.cpp
@@ -1221,7 +1221,14 @@ static uint32_t read_data_block(void **d
   if (fpos + size > I->input.file->size())
     throw LIBRAW_EXCEPTION_IO_CORRUPT;
 
+  // All known files from real cameras are many times smaller than 1 GB, so the hard limit is OK here.
+
+  if(size > 1024*1024*1024)
+    throw LIBRAW_EXCEPTION_ALLOC;
+
   *data = (void *)malloc(size);
+  if (!*data)
+	  throw LIBRAW_EXCEPTION_ALLOC;
 
   GETN(*data, size);
 
