Fix for data size calculation integer overflow in float/deflated DNG loader (TALOS...
authorAlex Tutubalin <lexa@lexa.ru>
Fri, 13 Mar 2026 14:43:47 +0000 (17:43 +0300)
committerGuilhem Moulin <guilhem@debian.org>
Wed, 29 Jul 2026 01:53:35 +0000 (03:53 +0200)
Origin: https://github.com/LibRaw/LibRaw/commit/aa4458eb511daeae90676c1ce5c587106e4aaec1
Bug: https://talosintelligence.com/vulnerability_reports/TALOS-2026-2364
Bug-Debian: https://bugs.debian.org/1133845
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-20884

Gbp-Pq: Topic CVE-2026-20884
Gbp-Pq: Name 03-aa4458eb5.patch

src/decoders/fp_dng.cpp

index b18ca337f136802cf9570ddebb451b799143ae56..c4603737c82f7ad6965dc5352baefa2e0db6597b 100644 (file)
@@ -349,14 +349,28 @@ 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)
   {
-    INT64 raw_bytes = 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(tiles.tileCnt * tiles.tileWidth * tiles.tileHeight * ifd->samples, sizeof(float));
-    if (!float_raw_image)
-      throw LIBRAW_EXCEPTION_ALLOC;
+    float_raw_image = (float *)calloc(raw_bytes, 1);
   }
   else
     throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float deflated supported
@@ -395,7 +409,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]);