diff options
author | Laurent Aimar <fenrir@videolan.org> | 2011-09-25 00:08:50 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-10-01 20:25:16 +0200 |
commit | 02bdeff1ef4915e1794a19184d567ef27e05c9c5 (patch) | |
tree | d6e3546902e705dd2d8bcd2794e1ca8816be18c6 | |
parent | 55efeba2b554f8f2ea134d3d82d01062e0343828 (diff) | |
download | ffmpeg-02bdeff1ef4915e1794a19184d567ef27e05c9c5.tar.gz |
Fix out of bound reads in rle_unpack() of vmd video decoder.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit 4749e074987d45cb98935a683a7ee8e1ee376d86)
-rw-r--r-- | libavcodec/vmdav.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c index eb2d208389..90cbab8b3d 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdav.c @@ -153,32 +153,39 @@ static void lz_unpack(const unsigned char *src, int src_len, } } -static int rle_unpack(const unsigned char *src, unsigned char *dest, - int src_len, int dest_len) +static int rle_unpack(const unsigned char *src, int src_len, int src_count, + unsigned char *dest, int dest_len) { const unsigned char *ps; + const unsigned char *ps_end; unsigned char *pd; int i, l; unsigned char *dest_end = dest + dest_len; ps = src; + ps_end = src + src_len; pd = dest; - if (src_len & 1) + if (src_count & 1) { + if (ps_end - ps < 1) + return 0; *pd++ = *ps++; + } - src_len >>= 1; + src_count >>= 1; i = 0; do { + if (ps_end - ps < 1) + break; l = *ps++; if (l & 0x80) { l = (l & 0x7F) * 2; - if (pd + l > dest_end) + if (pd + l > dest_end || ps_end - ps < l) return ps - src; memcpy(pd, ps, l); ps += l; pd += l; } else { - if (pd + i > dest_end) + if (pd + i > dest_end || ps_end - ps < 2) return ps - src; for (i = 0; i < l; i++) { *pd++ = ps[0]; @@ -187,7 +194,7 @@ static int rle_unpack(const unsigned char *src, unsigned char *dest, ps += 2; } i += l; - } while (i < src_len); + } while (i < src_count); return ps - src; } @@ -330,7 +337,7 @@ static void vmd_decode(VmdVideoContext *s) if (pb_end - pb < 1) return; if (*pb++ == 0xFF) - len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs); + len = rle_unpack(pb, pb_end - pb, len, &dp[ofs], frame_width - ofs); else { if (pb_end - pb < len) return; |