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>2021-02-08 14:26:50 +0300
committerSergey Sharybin <sergey@blender.org>2021-02-15 12:30:43 +0300
commit7c864388fc0de1e92b8ad9394966d38ffea17daf (patch)
tree5be254bae150d6ccfbd687260ed5b6660055ce30 /source/blender/imbuf
parent2d3b29de4fc72d5e293deccd2317c001ede703e3 (diff)
Fix T71960: Malformed .bmp files lead to crash
Add a boundary check, avoiding access past actual data. Ideally would need to report error to the user somehow, but it doesn't seem to be easy to do. This is a minimal safe patch. The proper complete fix is being worked on by Jesse. Differential Revision: https://developer.blender.org/D10357
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r--source/blender/imbuf/intern/bmp.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c
index 58ce02f28ae..a5c558fc216 100644
--- a/source/blender/imbuf/intern/bmp.c
+++ b/source/blender/imbuf/intern/bmp.c
@@ -111,6 +111,14 @@ bool imb_is_a_bmp(const uchar *buf, size_t size)
return checkbmp(buf, size);
}
+static size_t imb_bmp_calc_row_size_in_bytes(size_t x, size_t depth)
+{
+ if (depth <= 8) {
+ return (depth * x + 31) / 32 * 4;
+ }
+ return (depth >> 3) * x;
+}
+
ImBuf *imb_bmp_decode(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
ImBuf *ibuf = NULL;
@@ -130,7 +138,8 @@ ImBuf *imb_bmp_decode(const uchar *mem, size_t size, int flags, char colorspace[
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
- bmp = mem + LITTLE_LONG(*(int *)(mem + 10));
+ const size_t pixel_data_offset = LITTLE_LONG(*(int *)(mem + 10));
+ bmp = mem + pixel_data_offset;
if (CHECK_HEADER_FIELD_BMP(mem)) {
/* skip fileheader */
@@ -150,6 +159,13 @@ ImBuf *imb_bmp_decode(const uchar *mem, size_t size, int flags, char colorspace[
xppm = LITTLE_LONG(bmi.biXPelsPerMeter);
yppm = LITTLE_LONG(bmi.biYPelsPerMeter);
+ const size_t row_size_in_bytes = imb_bmp_calc_row_size_in_bytes(x, depth);
+ const size_t num_expected_data_bytes = row_size_in_bytes * y;
+ const size_t num_actual_data_bytes = size - pixel_data_offset;
+ if (num_actual_data_bytes < num_expected_data_bytes) {
+ return NULL;
+ }
+
if (depth <= 8) {
ibuf_depth = 24;
}
@@ -179,7 +195,6 @@ ImBuf *imb_bmp_decode(const uchar *mem, size_t size, int flags, char colorspace[
rect = (uchar *)ibuf->rect;
if (depth <= 8) {
- const int rowsize = (depth * x + 31) / 32 * 4;
const char(*palette)[4] = (void *)(mem + skip);
const int startmask = ((1 << depth) - 1) << 8;
for (size_t i = y; i > 0; i--) {
@@ -212,7 +227,7 @@ ImBuf *imb_bmp_decode(const uchar *mem, size_t size, int flags, char colorspace[
}
}
/* Advance to the next row */
- bmp += (rowsize - nbytes);
+ bmp += (row_size_in_bytes - nbytes);
}
}
else if (depth == 16) {