diff options
author | Jesse Yurkovich <jesse.y@gmail.com> | 2022-01-12 07:48:32 +0300 |
---|---|---|
committer | Philipp Oeser <info@graphics-engineer.com> | 2022-02-21 12:54:40 +0300 |
commit | 1ee4e6bf31ff32f87f9cd1eafa548d6811794380 (patch) | |
tree | 89977a4e9a623d8727349986ce4ad037055193e6 /source/blender | |
parent | 87b77a97b947a3d799fc5aa6ac7d2c5e5606109b (diff) |
Fix T89542: Crash when loading certain .hdr files
The direct cause of the bug in question was passing in the raw memory
buffer to sscanf. It should be called with a null-terminated buffer;
which isn't guaranteed when blindly trusting the file data.
When attempting to fuzz this code path, a variety of other crashes were
discovered and fixed.
Differential Revision: https://developer.blender.org/D11952
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/imbuf/intern/radiance_hdr.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 94b2a62aa26..90972da7da1 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -77,7 +77,7 @@ static const unsigned char *oldreadcolrs(RGBE *scan, scan[0][BLU] = *mem++; scan[0][EXP] = *mem++; if (scan[0][RED] == 1 && scan[0][GRN] == 1 && scan[0][BLU] == 1) { - for (i = scan[0][EXP] << rshift; i > 0; i--) { + for (i = scan[0][EXP] << rshift; i > 0 && len > 0; i--) { COPY_RGBE(scan[-1], scan[0]); scan++; len--; @@ -227,7 +227,7 @@ struct ImBuf *imb_loadhdr(const unsigned char *mem, int found = 0; int width = 0, height = 0; const unsigned char *ptr, *mem_eof = mem + size; - char oriY[80], oriX[80]; + char oriY[3], oriX[3]; if (!imb_is_a_hdr(mem, size)) { return NULL; @@ -244,13 +244,19 @@ struct ImBuf *imb_loadhdr(const unsigned char *mem, } } - if ((found && (x < (size + 2))) == 0) { + if ((found && (x < (size - 1))) == 0) { /* Data not found! */ return NULL; } - if (sscanf((const char *)&mem[x + 1], - "%79s %d %79s %d", + x++; + + /* sscanf requires a null-terminated buffer argument */ + char buf[32] = {0}; + memcpy(buf, &mem[x], MIN2(sizeof(buf) - 1, size - x)); + + if (sscanf(buf, + "%2s %d %2s %d", (char *)&oriY, &height, (char *)&oriX, @@ -258,8 +264,18 @@ struct ImBuf *imb_loadhdr(const unsigned char *mem, return NULL; } + if (width < 1 || height < 1) { + return NULL; + } + + /* Checking that width x height does not extend past mem_eof is not easily possible + * since the format uses RLE compression. Can cause excessive memory allocation to occur. */ + /* find end of this line, data right behind it */ - ptr = (const unsigned char *)strchr((const char *)&mem[x + 1], '\n'); + ptr = (const unsigned char *)strchr((const char *)&mem[x], '\n'); + if (ptr == NULL || ptr >= mem_eof) { + return NULL; + } ptr++; if (flags & IB_test) { |