diff options
-rw-r--r-- | source/blender/imbuf/intern/dds/FlipDXT.cpp | 25 | ||||
-rw-r--r-- | source/blender/imbuf/intern/dds/FlipDXT.h | 15 | ||||
-rw-r--r-- | source/blender/imbuf/intern/dds/dds_api.cpp | 9 |
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 { |