diff options
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r-- | source/blender/imbuf/intern/dds/FlipDXT.cpp | 22 | ||||
-rw-r--r-- | source/blender/imbuf/intern/dds/FlipDXT.h | 9 | ||||
-rw-r--r-- | source/blender/imbuf/intern/dds/dds_api.cpp | 9 |
3 files changed, 34 insertions, 6 deletions
diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp index 359d6f30cdc..6686d56e9d1 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.cpp +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -168,9 +168,16 @@ static void FlipDXT5BlockHalf(uint8_t *block) FlipDXT1BlockHalf(block + 8); } -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; @@ -204,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 b4f71e4eca7..f9d3ce6112e 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.h +++ b/source/blender/imbuf/intern/dds/FlipDXT.h @@ -23,5 +23,10 @@ * * 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 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 1729a9a64f8..f576209ff62 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 { |