[FFmpeg-cvslog] ws_snd: add some checks to prevent buffer overread or overwrite.

Justin Ruggles git at videolan.org
Tue Sep 27 02:25:30 CEST 2011


ffmpeg | branch: master | Justin Ruggles <justin.ruggles at gmail.com> | Mon Sep 12 09:41:06 2011 -0400| [417364ce1f979031ef6fee661fc15e1869bdb1b4] | committer: Justin Ruggles

ws_snd: add some checks to prevent buffer overread or overwrite.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=417364ce1f979031ef6fee661fc15e1869bdb1b4
---

 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 5c61a18..0459128 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;
 }
 



More information about the ffmpeg-cvslog mailing list