diff options
author | Reimar Döffinger | 2011-03-29 21:14:55 +0200 |
---|---|---|
committer | Anton Khirnov | 2011-05-13 07:38:54 +0200 |
commit | 2c9a5172d328259c5d76e588f2ddc12f439ffcd0 (patch) | |
tree | 2fc53a6a24602a0360b41caff75709c191d6a0fa /libavcodec/dfa.c | |
parent | 7e19a6e86814b08073b4b8873598ef5d94e6345d (diff) |
dfa: fix buffer overflow checks to avoid integer overflows.
Signed-off-by: Anton Khirnov <anton@khirnov.net>
Diffstat (limited to 'libavcodec/dfa.c')
-rw-r--r-- | libavcodec/dfa.c | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index b149791136..1556bc7acb 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -62,12 +62,14 @@ static int decode_tsw1(uint8_t *frame, int width, int height, const uint8_t *frame_start = frame; const uint8_t *frame_end = frame + width * height; int mask = 0x10000, bitbuf = 0; - int v, offset, count, segments; + int v, count, segments; + unsigned offset; segments = bytestream_get_le32(&src); - frame += bytestream_get_le32(&src); - if (frame < frame_start || frame > frame_end) + offset = bytestream_get_le32(&src); + if (frame_end - frame <= offset) return -1; + frame += offset; while (segments--) { if (mask == 0x10000) { if (src >= src_end) @@ -189,11 +191,11 @@ static int decode_bdlt(uint8_t *frame, int width, int height, int count, lines, segments; count = bytestream_get_le16(&src); - if (count >= height || width * count < 0) + if (count >= height) return -1; frame += width * count; lines = bytestream_get_le16(&src); - if (frame + lines * width > frame_end || src >= src_end) + if (count + lines > height || src >= src_end) return -1; while (lines--) { @@ -203,17 +205,17 @@ static int decode_bdlt(uint8_t *frame, int width, int height, while (segments--) { if (src_end - src < 3) return -1; - line_ptr += *src++; - if (line_ptr >= frame) + if (frame - line_ptr <= *src) return -1; + line_ptr += *src++; count = (int8_t)*src++; if (count >= 0) { - if (line_ptr + count > frame || src_end - src < count) + if (frame - line_ptr < count || src_end - src < count) return -1; bytestream_get_buffer(&src, line_ptr, count); } else { count = -count; - if (line_ptr + count > frame || src >= src_end) + if (frame - line_ptr < count || src >= src_end) return -1; memset(line_ptr, *src++, count); } @@ -232,15 +234,16 @@ static int decode_wdlt(uint8_t *frame, int width, int height, int count, i, v, lines, segments; lines = bytestream_get_le16(&src); - if (frame + lines * width > frame_end || src >= src_end) + if (lines > height || src >= src_end) return -1; while (lines--) { segments = bytestream_get_le16(&src); while ((segments & 0xC000) == 0xC000) { - frame -= (int16_t)segments * width; - if (frame >= frame_end) + unsigned delta = -((int16_t)segments * width); + if (frame_end - frame <= delta) return -1; + frame += delta; segments = bytestream_get_le16(&src); } if (segments & 0x8000) { @@ -252,18 +255,18 @@ static int decode_wdlt(uint8_t *frame, int width, int height, while (segments--) { if (src_end - src < 2) return -1; - line_ptr += *src++; - if (line_ptr >= frame) + if (frame - line_ptr <= *src) return -1; + line_ptr += *src++; count = (int8_t)*src++; if (count >= 0) { - if (line_ptr + count*2 > frame || src_end - src < count*2) + if (frame - line_ptr < count*2 || src_end - src < count*2) return -1; bytestream_get_buffer(&src, line_ptr, count*2); line_ptr += count * 2; } else { count = -count; - if (line_ptr + count*2 > frame || src_end - src < 2) + if (frame - line_ptr < count*2 || src_end - src < 2) return -1; v = bytestream_get_le16(&src); for (i = 0; i < count; i++) |