Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey@blender.org>2022-01-06 18:08:40 +0300
committerPhilipp Oeser <info@graphics-engineer.com>2022-01-18 12:05:59 +0300
commit0b2ea1d69bdc2c4c3b35bb9430bf3659888fe5d4 (patch)
treeab202f666531da8de56a7b9e262bfdb0eeaf27b1
parent63fdcbb5889e31b5f07d8d5c8e923cc57900fe1b (diff)
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
-rw-r--r--source/blender/imbuf/intern/dds/FlipDXT.cpp25
-rw-r--r--source/blender/imbuf/intern/dds/FlipDXT.h15
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp9
3 files changed, 40 insertions, 9 deletions
diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp
index f5c937654b3..1d65ef743ab 100644
--- a/source/blender/imbuf/intern/dds/FlipDXT.cpp
+++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp
@@ -168,11 +168,17 @@ 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)
{
- // must have valid dimensions
+ *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 b7056742430..0c046865f33 100644
--- a/source/blender/imbuf/intern/dds/FlipDXT.h
+++ b/source/blender/imbuf/intern/dds/FlipDXT.h
@@ -19,8 +19,17 @@
#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);
#endif
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index 832b380bbc2..9bd365747cb 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -185,8 +185,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 {