[FFmpeg-cvslog] Fixed invalid access in wavpack decoder on corrupted bitstream.

Laurent Aimar git at videolan.org
Fri Sep 9 00:16:37 CEST 2011


ffmpeg | branch: release/0.8 | Laurent Aimar <fenrir at videolan.org> | Wed Sep  7 22:02:55 2011 +0200| [e1baba3ddb8aa042f1a3a0d7bf74bb89a9c58f36] | committer: Michael Niedermayer

Fixed invalid access in wavpack decoder on corrupted bitstream.

Signed-off-by: Martin Storsjö <martin at martin.st>
(cherry picked from commit 55354b7de21e7bb4bbeb1c12ff55ea17f807c70c)

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

 libavcodec/wavpack.c |   49 +++++++++++++++++++++++++++++++++++--------------
 1 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c
index a01795a..0ab05ac 100644
--- a/libavcodec/wavpack.c
+++ b/libavcodec/wavpack.c
@@ -292,7 +292,14 @@ static int wv_get_value(WavpackFrameContext *ctx, GetBitContext *gb, int channel
             }
         }else{
             t = get_unary_0_33(gb);
-            if(t >= 2) t = get_bits(gb, t - 1) | (1 << (t-1));
+            if(t >= 2){
+                if(get_bits_left(gb) < t-1)
+                    goto error;
+                t = get_bits(gb, t - 1) | (1 << (t-1));
+            }else{
+                if(get_bits_left(gb) < 0)
+                    goto error;
+            }
             ctx->zeroes = t;
             if(ctx->zeroes){
                 memset(ctx->ch[0].median, 0, sizeof(ctx->ch[0].median));
@@ -303,24 +310,24 @@ static int wv_get_value(WavpackFrameContext *ctx, GetBitContext *gb, int channel
         }
     }
 
-    if(get_bits_count(gb) >= ctx->data_size){
-        *last = 1;
-        return 0;
-    }
-
     if(ctx->zero){
         t = 0;
         ctx->zero = 0;
     }else{
         t = get_unary_0_33(gb);
-        if(get_bits_count(gb) >= ctx->data_size){
-            *last = 1;
-            return 0;
-        }
+        if(get_bits_left(gb) < 0)
+            goto error;
         if(t == 16) {
             t2 = get_unary_0_33(gb);
-            if(t2 < 2) t += t2;
-            else t += get_bits(gb, t2 - 1) | (1 << (t2 - 1));
+            if(t2 < 2){
+                if(get_bits_left(gb) < 0)
+                    goto error;
+                t += t2;
+            }else{
+                if(get_bits_left(gb) < t2 - 1)
+                    goto error;
+                t += get_bits(gb, t2 - 1) | (1 << (t2 - 1));
+            }
         }
 
         if(ctx->one){
@@ -360,9 +367,13 @@ static int wv_get_value(WavpackFrameContext *ctx, GetBitContext *gb, int channel
     }
     if(!c->error_limit){
         ret = base + get_tail(gb, add);
+        if (get_bits_left(gb) <= 0)
+            goto error;
     }else{
         int mid = (base*2 + add + 1) >> 1;
         while(add > c->error_limit){
+            if(get_bits_left(gb) <= 0)
+                goto error;
             if(get_bits1(gb)){
                 add -= (mid - base);
                 base = mid;
@@ -376,6 +387,10 @@ static int wv_get_value(WavpackFrameContext *ctx, GetBitContext *gb, int channel
     if(ctx->hybrid_bitrate)
         c->slow_level += wp_log2(ret) - LEVEL_DECAY(c->slow_level);
     return sign ? ~ret : ret;
+
+error:
+    *last = 1;
+    return 0;
 }
 
 static inline int wv_get_value_integer(WavpackFrameContext *s, uint32_t *crc, int S)
@@ -580,7 +595,10 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, vo
         count++;
     }while(!last && count < s->max_samples);
 
-    s->samples_left -= count;
+    if (last)
+        s->samples_left = 0;
+    else
+        s->samples_left -= count;
     if(!s->samples_left){
         if(crc != s->CRC){
             av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
@@ -658,7 +676,10 @@ static inline int wv_unpack_mono(WavpackFrameContext *s, GetBitContext *gb, void
         count++;
     }while(!last && count < s->max_samples);
 
-    s->samples_left -= count;
+    if (last)
+        s->samples_left = 0;
+    else
+        s->samples_left -= count;
     if(!s->samples_left){
         if(crc != s->CRC){
             av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");



More information about the ffmpeg-cvslog mailing list