diff --git a/src/libImaging/FliDecode.c b/src/libImaging/FliDecode.c index 600528e..2d63bea 100644 --- a/src/libImaging/FliDecode.c +++ b/src/libImaging/FliDecode.c @@ -24,6 +24,11 @@ #define I32(ptr)\ ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) +#define ERR_IF_DATA_OOB(offset) \ + if ((data + (offset)) > ptr + bytes) {\ + state->errcode = IMAGING_CODEC_OVERRUN; \ + return -1; \ + } int ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) @@ -75,10 +80,12 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) break; /* ignored; handled by Python code */ case 7: /* FLI SS2 chunk (word delta) */ + /* OOB ok, we've got 4 bytes min on entry */ lines = I16(data); data += 2; for (l = y = 0; l < lines && y < state->ysize; l++, y++) { - UINT8* buf = (UINT8*) im->image[y]; + UINT8* local_buf = (UINT8*) im->image[y]; int p, packets; + ERR_IF_DATA_OOB(2) packets = I16(data); data += 2; while (packets & 0x8000) { /* flag word */ @@ -88,29 +95,33 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) state->errcode = IMAGING_CODEC_OVERRUN; return -1; } - buf = (UINT8*) im->image[y]; + local_buf = (UINT8*) im->image[y]; } else { /* store last byte (used if line width is odd) */ - buf[state->xsize-1] = (UINT8) packets; + local_buf[state->xsize-1] = (UINT8) packets; } + ERR_IF_DATA_OOB(2) packets = I16(data); data += 2; } for (p = x = 0; p < packets; p++) { + ERR_IF_DATA_OOB(2) x += data[0]; /* pixel skip */ if (data[1] >= 128) { + ERR_IF_DATA_OOB(4) i = 256-data[1]; /* run */ if (x + i + i > state->xsize) break; for (j = 0; j < i; j++) { - buf[x++] = data[2]; - buf[x++] = data[3]; + local_buf[x++] = data[2]; + local_buf[x++] = data[3]; } data += 2 + 2; } else { i = 2 * (int) data[1]; /* chunk */ if (x + i > state->xsize) break; - memcpy(buf + x, data + 2, i); + ERR_IF_DATA_OOB(2+i) + memcpy(local_buf + x, data + 2, i); data += 2 + i; x += i; } @@ -126,22 +137,26 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) break; case 12: /* FLI LC chunk (byte delta) */ + /* OOB Check ok, we have 10 bytes here */ y = I16(data); ymax = y + I16(data+2); data += 4; for (; y < ymax && y < state->ysize; y++) { UINT8* out = (UINT8*) im->image[y]; int p, packets = *data++; for (p = x = 0; p < packets; p++, x += i) { + ERR_IF_DATA_OOB(2) x += data[0]; /* skip pixels */ if (data[1] & 0x80) { i = 256-data[1]; /* run */ if (x + i > state->xsize) break; + ERR_IF_DATA_OOB(3) memset(out + x, data[2], i); data += 3; } else { i = data[1]; /* chunk */ if (x + i > state->xsize) break; + ERR_IF_DATA_OOB(2+i) memcpy(out + x, data + 2, i); data += i + 2; } @@ -162,14 +177,20 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) break; case 15: /* FLI BRUN chunk */ + /* data = ptr + 6 */ for (y = 0; y < state->ysize; y++) { UINT8* out = (UINT8*) im->image[y]; data += 1; /* ignore packetcount byte */ for (x = 0; x < state->xsize; x += i) { + /* Out of Bounds Read issue, guaranteed to try to read 2 from data */ + ERR_IF_DATA_OOB(2) if (data[0] & 0x80) { i = 256 - data[0]; - if (x + i > state->xsize) + if (x + i > state->xsize){ break; /* safety first */ + } + /* Out of Bounds read issue */ + ERR_IF_DATA_OOB(i+1) memcpy(out + x, data + 1, i); data += i + 1; } else { @@ -189,9 +210,13 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) break; case 16: /* COPY chunk */ + if (state->xsize > bytes/state->ysize) { + /* not enough data for frame */ + return ptr - buf; /* bytes consumed */ + } for (y = 0; y < state->ysize; y++) { - UINT8* buf = (UINT8*) im->image[y]; - memcpy(buf, data, state->xsize); + UINT8* local_buf = (UINT8*) im->image[y]; + memcpy(local_buf, data, state->xsize); data += state->xsize; } break; @@ -205,6 +230,10 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) return -1; } advance = I32(ptr); + if (advance < 0 || advance > bytes) { + state->errcode = IMAGING_CODEC_OVERRUN; + return -1; + } ptr += advance; bytes -= advance; }