From a58727c1a3cfef4101700e546a6a661c6a299d97 Mon Sep 17 00:00:00 2001
From: Alex Tutubalin <lexa@lexa.ru>
Date: Thu, 12 Mar 2026 20:34:53 +0300
Subject: [PATCH] Fix for TALOS-2026-2363: avoid integer overflow in allocation
 size calculation. Also: check for EOF in read loop

---
 src/decoders/fp_dng.cpp | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 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
@@ -636,12 +636,17 @@ void LibRaw::uncompressed_fp_dng_load_ra
     tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data, libraw_internal_data.unpacker_data.order,
         libraw_internal_data.internal_data.input);
 
+	// 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)) * INT64(MAX(bytesps,4)) * INT64(ifd->samples);
+	if(rowbytes > (1LL << 22))
+      throw LIBRAW_EXCEPTION_TOOBIG;
+
 	INT64 allocsz = INT64(tiles.tileCnt) * INT64(tiles.tileWidth) * INT64(tiles.tileHeight) * INT64(ifd->samples) * INT64(sizeof(float));
 	if (allocsz > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
 		throw LIBRAW_EXCEPTION_TOOBIG;
 
     if (ifd->sample_format == 3)
-        float_raw_image = (float *)calloc(tiles.tileCnt * tiles.tileWidth * tiles.tileHeight *ifd->samples, sizeof(float));
+        float_raw_image = (float *)calloc(allocsz,1);
     else
         throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float supported
 
@@ -658,6 +663,7 @@ void LibRaw::uncompressed_fp_dng_load_ra
             size_t rowsInTile = y + tiles.tileHeight > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : tiles.tileHeight;
             size_t colsInTile = x + tiles.tileWidth > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : tiles.tileWidth;
 
+			// inrowbytes is less then 2^22 (see above) so conversion to int is safe
             size_t inrowbytes = colsInTile * bytesps * ifd->samples;
             int fullrowbytes = tiles.tileWidth *bytesps * ifd->samples;
             size_t outrowbytes = colsInTile * sizeof(float) * ifd->samples;
@@ -667,7 +673,9 @@ void LibRaw::uncompressed_fp_dng_load_ra
                 unsigned char *dst = fullrowbytes > inrowbytes ? rowbuf.data(): // last tile in row, use buffer
                     (unsigned char *)&float_raw_image
                     [((y + row) * imgdata.sizes.raw_width + x) * ifd->samples];
-                libraw_internal_data.internal_data.input->read(dst, 1, fullrowbytes);
+                int bytesread = libraw_internal_data.internal_data.input->read(dst, 1, fullrowbytes);
+				if (bytesread < fullrowbytes)
+					derror();
                 if (bytesps == 2 && difford)
                     libraw_swab(dst, fullrowbytes);
                 else if (bytesps == 3 && (libraw_internal_data.unpacker_data.order == 0x4949)) // II-16bit
