[Bf-blender-cvs] [d294d19d214] blender-v2.93-release: Fix T86952: Buffer overflow reading specific DDS images

Sergey Sharybin noreply at git.blender.org
Tue Jan 11 16:00:23 CET 2022


Commit: d294d19d214342b995fd1974465a00b84cba86fd
Author: Sergey Sharybin
Date:   Thu Jan 6 16:08:40 2022 +0100
Branches: blender-v2.93-release
https://developer.blender.org/rBd294d19d214342b995fd1974465a00b84cba86fd

Fix T86952: Buffer overflow reading specific DDS images

Add a data boundary check in the flipping code.

This code now also communicates the number of mipmap levels
it processed with an intent to avoid GPU texture from using
more levels than there are in the DDS data.

Differential Revision: https://developer.blender.org/D13755

===================================================================

M	source/blender/imbuf/intern/dds/FlipDXT.cpp
M	source/blender/imbuf/intern/dds/FlipDXT.h
M	source/blender/imbuf/intern/dds/dds_api.cpp

===================================================================

diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp
index 2acf072556a..6686d56e9d1 100644
--- a/source/blender/imbuf/intern/dds/FlipDXT.cpp
+++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp
@@ -168,10 +168,16 @@ static void FlipDXT5BlockHalf(uint8_t *block)
   FlipDXT1BlockHalf(block + 8);
 }
 
-/* Flips a DXTC image, by flipping and swapping DXTC blocks as appropriate. */
-int FlipDXTCImage(
-    unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data)
+int FlipDXTCImage(unsigned int width,
+                  unsigned int height,
+                  unsigned int levels,
+                  int fourcc,
+                  uint8_t *data,
+                  int data_size,
+                  unsigned int *r_num_valid_levels)
 {
+  *r_num_valid_levels = 0;
+
   /* Must have valid dimensions. */
   if (width == 0 || height == 0) {
     return 0;
@@ -205,14 +211,25 @@ int FlipDXTCImage(
       return 0;
   }
 
+  *r_num_valid_levels = levels;
+
   unsigned int mip_width = width;
   unsigned int mip_height = height;
 
+  const uint8_t *data_end = data + data_size;
+
   for (unsigned int i = 0; i < levels; i++) {
     unsigned int blocks_per_row = (mip_width + 3) / 4;
     unsigned int blocks_per_col = (mip_height + 3) / 4;
     unsigned int blocks = blocks_per_row * blocks_per_col;
 
+    if (data + block_bytes * blocks > data_end) {
+      /* Stop flipping when running out of data to be modified, avoiding possible buffer overrun
+       * on a malformed files. */
+      *r_num_valid_levels = i;
+      break;
+    }
+
     if (mip_height == 1) {
       /* no flip to do, and we're done. */
       break;
diff --git a/source/blender/imbuf/intern/dds/FlipDXT.h b/source/blender/imbuf/intern/dds/FlipDXT.h
index d35157251bd..f9d3ce6112e 100644
--- a/source/blender/imbuf/intern/dds/FlipDXT.h
+++ b/source/blender/imbuf/intern/dds/FlipDXT.h
@@ -18,6 +18,15 @@
 
 #include "BLI_sys_types.h"
 
-/* flip compressed DXT image vertically to fit OpenGL convention */
-int FlipDXTCImage(
-    unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data);
+/**
+ * Flips a DXTC image, by flipping and swapping DXTC blocks as appropriate.
+ *
+ * Use to flip vertically to fit OpenGL convention.
+ */
+int FlipDXTCImage(unsigned int width,
+                  unsigned int height,
+                  unsigned int levels,
+                  int fourcc,
+                  uint8_t *data,
+                  int data_size,
+                  unsigned int *r_num_valid_levels);
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index e767cb14b1a..c484085fd35 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -186,8 +186,13 @@ struct ImBuf *imb_load_dds(const unsigned char *mem,
 
       /* flip compressed texture */
       if (ibuf->dds_data.data) {
-        FlipDXTCImage(
-            dds.width(), dds.height(), dds.mipmapCount(), dds.fourCC(), ibuf->dds_data.data);
+        FlipDXTCImage(dds.width(),
+                      dds.height(),
+                      ibuf->dds_data.nummipmaps,
+                      dds.fourCC(),
+                      ibuf->dds_data.data,
+                      ibuf->dds_data.size,
+                      &ibuf->dds_data.nummipmaps);
       }
     }
     else {



More information about the Bf-blender-cvs mailing list