diff options
author | Laurent Aimar <fenrir@videolan.org> | 2011-09-25 00:08:49 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-09-25 00:34:39 +0200 |
commit | e07377e7366d038d6f28792c46745463a0542650 (patch) | |
tree | 9944c5f8dcf851f6887154351547e46ef079791d /libavcodec | |
parent | 3b26daedd8271286967481a499b061b0ba8aa9a6 (diff) | |
download | ffmpeg-e07377e7366d038d6f28792c46745463a0542650.tar.gz |
Check for out of bound reads in vmd_decode() of vmd video decoder.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/vmdav.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c index 14a41f40e8..ab73508d70 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdav.c @@ -203,6 +203,7 @@ static void vmd_decode(VmdVideoContext *s) const unsigned char *p_end = s->buf + s->size; const unsigned char *pb; + const unsigned char *pb_end; unsigned char meth; unsigned char *dp; /* pointer to current frame */ unsigned char *pp; /* pointer to previous frame */ @@ -248,6 +249,8 @@ static void vmd_decode(VmdVideoContext *s) /* check if there is a new palette */ if (s->buf[15] & 0x02) { + if (p_end - p < 2 + 3 * PALETTE_COUNT) + return; p += 2; palette32 = (unsigned int *)s->palette; for (i = 0; i < PALETTE_COUNT; i++) { @@ -256,16 +259,17 @@ static void vmd_decode(VmdVideoContext *s) b = *p++ * 4; palette32[i] = (r << 16) | (g << 8) | (b); } - s->size -= (256 * 3 + 2); } - if (s->size >= 0) { + if (p < p_end) { /* originally UnpackFrame in VAG's code */ pb = p; + pb_end = p_end; meth = *pb++; if (meth & 0x80) { lz_unpack(pb, p_end - pb, s->unpack_buffer, s->unpack_buffer_size); meth &= 0x7F; pb = s->unpack_buffer; + pb_end = s->unpack_buffer + s->unpack_buffer_size; } dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x]; @@ -275,10 +279,12 @@ static void vmd_decode(VmdVideoContext *s) for (i = 0; i < frame_height; i++) { ofs = 0; do { + if (pb_end - pb < 1) + return; len = *pb++; if (len & 0x80) { len = (len & 0x7F) + 1; - if (ofs + len > frame_width) + if (ofs + len > frame_width || pb_end - pb < len) return; memcpy(&dp[ofs], pb, len); pb += len; @@ -303,6 +309,8 @@ static void vmd_decode(VmdVideoContext *s) case 2: for (i = 0; i < frame_height; i++) { + if (pb_end -pb < frame_width) + return; memcpy(dp, pb, frame_width); pb += frame_width; dp += s->frame.linesize[0]; @@ -314,13 +322,20 @@ static void vmd_decode(VmdVideoContext *s) for (i = 0; i < frame_height; i++) { ofs = 0; do { + if (pb_end - pb < 1) + return; len = *pb++; if (len & 0x80) { len = (len & 0x7F) + 1; + if (pb_end - pb < 1) + return; if (*pb++ == 0xFF) len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs); - else + else { + if (pb_end - pb < len) + return; memcpy(&dp[ofs], pb, len); + } pb += len; ofs += len; } else { |