summaryrefslogtreecommitdiff
path: root/libavcodec/vmdav.c
diff options
context:
space:
mode:
authorLaurent Aimar <fenrir@videolan.org>2011-09-25 00:08:50 +0200
committerMichael Niedermayer <michaelni@gmx.at>2011-09-25 00:42:06 +0200
commit4749e074987d45cb98935a683a7ee8e1ee376d86 (patch)
treeec6728a6ef0f1112e38dddc04a58dc38301919b9 /libavcodec/vmdav.c
parente07377e7366d038d6f28792c46745463a0542650 (diff)
Fix out of bound reads in rle_unpack() of vmd video decoder.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/vmdav.c')
-rw-r--r--libavcodec/vmdav.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c
index ab73508d70..98bd485c3e 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;