aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/ws-snd1.c
diff options
context:
space:
mode:
authorJustin Ruggles <justin.ruggles@gmail.com>2011-09-12 09:41:06 -0400
committerJustin Ruggles <justin.ruggles@gmail.com>2011-09-26 15:49:50 -0400
commit417364ce1f979031ef6fee661fc15e1869bdb1b4 (patch)
treed1c88eec2b23615f086e3bfe8244556cefdbe704 /libavcodec/ws-snd1.c
parent2322ced8da990835717a176b8d2c32961cfecd3e (diff)
downloadffmpeg-417364ce1f979031ef6fee661fc15e1869bdb1b4.tar.gz
ws_snd: add some checks to prevent buffer overread or overwrite.
Diffstat (limited to 'libavcodec/ws-snd1.c')
-rw-r--r--libavcodec/ws-snd1.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/libavcodec/ws-snd1.c b/libavcodec/ws-snd1.c
index 5c61a180c5..0459128ed3 100644
--- a/libavcodec/ws-snd1.c
+++ b/libavcodec/ws-snd1.c
@@ -61,6 +61,11 @@ static int ws_snd_decode_frame(AVCodecContext *avctx,
if (!buf_size)
return 0;
+ if (buf_size < 4) {
+ av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
+ return AVERROR(EINVAL);
+ }
+
out_size = AV_RL16(&buf[0]);
in_size = AV_RL16(&buf[2]);
buf += 4;
@@ -74,20 +79,37 @@ static int ws_snd_decode_frame(AVCodecContext *avctx,
return -1;
}
- *data_size = out_size;
-
if (in_size == out_size) {
for (i = 0; i < out_size; i++)
*samples++ = *buf++;
+ *data_size = out_size;
return buf_size;
}
- while (out_size > 0) {
- int code;
+ while (out_size > 0 && buf - avpkt->data < buf_size) {
+ int code, smp, size;
uint8_t count;
code = (*buf) >> 6;
count = (*buf) & 0x3F;
buf++;
+
+ /* make sure we don't write more than out_size samples */
+ switch (code) {
+ case 0: smp = 4; break;
+ case 1: smp = 2; break;
+ case 2: smp = (count & 0x20) ? 1 : count + 1; break;
+ default: smp = count + 1; break;
+ }
+ if (out_size < smp) {
+ out_size = 0;
+ break;
+ }
+
+ /* make sure we don't read past the input buffer */
+ size = ((code == 2 && (count & 0x20)) || code == 3) ? 0 : count + 1;
+ if ((buf - avpkt->data) + size > buf_size)
+ break;
+
switch(code) {
case 0: /* ADPCM 2-bit */
for (count++; count > 0; count--) {
@@ -144,6 +166,8 @@ static int ws_snd_decode_frame(AVCodecContext *avctx,
}
}
+ *data_size = samples - (uint8_t *)data;
+
return buf_size;
}