changeset 6443:e3adb7e96812 libavcodec

Detect and prevent reading over the end of counts_*. We pass the error through a context variable as this is simpler and i think also faster, but the return value of functions could be used instead of course. The code also ensures as a side effect that the AC decoder state does not become invalid. This fixes all known crashes. And outputs nothing in case of an error instead of random noise.
author michael
date Tue, 04 Mar 2008 21:58:34 +0000
parents 28e45bf84973
children 3572cc5bc8ff
files apedec.c
diffstat 1 files changed, 17 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/apedec.c	Tue Mar 04 21:39:21 2008 +0000
+++ b/apedec.c	Tue Mar 04 21:58:34 2008 +0000
@@ -156,6 +156,8 @@
     uint8_t *data_end;                       ///< frame data end
     const uint8_t *ptr;                      ///< current position in frame data
     const uint8_t *last_ptr;                 ///< position where last 4608-sample block ended
+
+    int error;
 } APEContext;
 
 // TODO: dsputilize
@@ -382,6 +384,13 @@
 
     cf = range_decode_culshift(ctx, 16);
 
+    if(cf > 65492){
+        symbol= cf - 65535 + 63;
+        range_decode_update(ctx, 1, cf);
+        if(cf > 65535)
+            ctx->error=1;
+        return symbol;
+    }
     /* figure out the symbol inefficiently; a binary search would be much better */
     for (symbol = 0; counts[symbol + 1] <= cf; symbol++);
 
@@ -894,11 +903,19 @@
     nblocks = s->samples;
     blockstodecode = FFMIN(BLOCKS_PER_LOOP, nblocks);
 
+    s->error=0;
+
     if ((s->channels == 1) || (s->frameflags & APE_FRAMECODE_PSEUDO_STEREO))
         ape_unpack_mono(s, blockstodecode);
     else
         ape_unpack_stereo(s, blockstodecode);
 
+    if(s->error || s->ptr > s->data_end){
+        s->samples=0;
+        av_log(avctx, AV_LOG_ERROR, "Error decoding frame\n");
+        return -1;
+    }
+
     for (i = 0; i < blockstodecode; i++) {
         *samples++ = s->decoded0[i];
         if(s->channels == 2)