diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2011-09-12 09:41:06 -0400 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2011-09-26 15:49:50 -0400 |
commit | 417364ce1f979031ef6fee661fc15e1869bdb1b4 (patch) | |
tree | d1c88eec2b23615f086e3bfe8244556cefdbe704 | |
parent | 2322ced8da990835717a176b8d2c32961cfecd3e (diff) | |
download | ffmpeg-417364ce1f979031ef6fee661fc15e1869bdb1b4.tar.gz |
ws_snd: add some checks to prevent buffer overread or overwrite.
-rw-r--r-- | libavcodec/ws-snd1.c | 32 |
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; } |