From 39873163faa29ed5dfc3bb5aab1b46ed807b210f Mon Sep 17 00:00:00 2001
From: Alex Tutubalin <lexa@lexa.ru>
Date: Fri, 13 Mar 2026 17:43:47 +0300
Subject: [PATCH] Fix for data size calculation integer overflow in
 float/deflated DNG loader (TALOS-2026-2364); Check for read results

---
 src/decoders/fp_dng.cpp | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

Index: LibRaw-0.21.4/src/decoders/fp_dng.cpp
===================================================================
--- LibRaw-0.21.4.orig/src/decoders/fp_dng.cpp
+++ LibRaw-0.21.4/src/decoders/fp_dng.cpp
@@ -349,8 +349,31 @@ void LibRaw::deflate_dng_load_raw()
   tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data, libraw_internal_data.unpacker_data.order,
       libraw_internal_data.internal_data.input);
 
+  if (tiles.tBytes.size() < 1)
+         throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+  // Ensure less then 2GB per compressed tile
+  INT64 maxcomprlen = tiles.tBytes[0];
+  for (int i = 1; i < tiles.tBytes.size(); i++)
+         maxcomprlen = MAX(maxcomprlen, tiles.tBytes[i]);
+
+  if(maxcomprlen >= (1LL << 31) || maxcomprlen < 0)
+         throw LIBRAW_EXCEPTION_TOOBIG;
+
+  // Max bytes: 2^16 raw width * 2^2 bytes/pixel * 2^2 channels = 2^20, so check against 2^22
+  INT64 rowbytes = INT64(MAX(tiles.tileWidth, imgdata.sizes.raw_width)) * 4ULL * INT64(ifd->samples);
+  if (rowbytes > (1LL << 22))
+    throw LIBRAW_EXCEPTION_TOOBIG;
+
   if (ifd->sample_format == 3)
-      float_raw_image = (float *)calloc(tiles.tileCnt * tiles.tileWidth * tiles.tileHeight *ifd->samples, sizeof(float));
+  {
+    INT64 raw_bytes = INT64(tiles.tileCnt) * INT64(tiles.tileWidth) * INT64(tiles.tileHeight) * INT64(ifd->samples) * sizeof(float);
+    if (raw_bytes > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
+       throw LIBRAW_EXCEPTION_TOOBIG;
+    float_raw_image = (float *)calloc(raw_bytes, 1);
+    if (!float_raw_image)
+      throw LIBRAW_EXCEPTION_ALLOC;
+  }
   else
     throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float deflated supported
 
@@ -385,7 +408,9 @@ void LibRaw::deflate_dng_load_raw()
       for (size_t x = 0; x < imgdata.sizes.raw_width; x += tiles.tileWidth, ++t)
       {
         libraw_internal_data.internal_data.input->seek(tiles.tOffsets[t], SEEK_SET);
-        libraw_internal_data.internal_data.input->read(cBuffer.data(), 1, tiles.tBytes[t]);
+        int bytesread = libraw_internal_data.internal_data.input->read(cBuffer.data(), 1, tiles.tBytes[t]);
+		if (bytesread < tiles.tBytes[t])
+			derror();
         unsigned long dstLen = tileBytes;
         int err =
             uncompress(uBuffer.data() + tileRowBytes, &dstLen, cBuffer.data(), (unsigned long)tiles.tBytes[t]);
