tags 514674 patch
thanks

I have added some error handling to apedec.c so that Audacious no longer
crashes when playing corrupted .ape files (or at least some of them).

John
--- apedec.0.c	2008-05-23 18:44:19.000000000 -0400
+++ apedec.c	2009-03-20 09:51:54.000000000 -0400
@@ -166,16 +166,15 @@
 }
 
 /** Perform normalization */
-static inline void range_dec_normalize(APEDecoderContext * ctx)
-{
+static inline char range_dec_normalize (APEDecoderContext * ctx) {
     while (ctx->rc.range <= BOTTOM_VALUE) {
-#ifdef DEBUG
-    assert(ctx->ptr < ctx->data_end);
-#endif
+        if (ctx->ptr + 1 > ctx->data_end)
+           return 0;
         ctx->rc.buffer = (ctx->rc.buffer << 8) | bytestream_get_byte(&ctx->ptr);
         ctx->rc.low    = (ctx->rc.low << 8)    | ((ctx->rc.buffer >> 1) & 0xFF);
         ctx->rc.range  <<= 8;
     }
+    return 1;
 }
 
 /**
@@ -183,22 +182,26 @@
  * @param tot_f is the total frequency or (code_value)1<<shift
  * @return the culmulative frequency
  */
-static inline int range_decode_culfreq(APEDecoderContext * ctx, int tot_f)
-{
-    range_dec_normalize(ctx);
+static inline char range_decode_culfreq (APEDecoderContext * ctx, int tot_f,
+ int * result) {
+    if (! range_dec_normalize (ctx))
+       return 0;
     ctx->rc.help = ctx->rc.range / tot_f;
-    return ctx->rc.low / ctx->rc.help;
+    * result = ctx->rc.low / ctx->rc.help;
+    return 1;
 }
 
 /**
  * Decode value with given size in bits
  * @param shift number of bits to decode
  */
-static inline int range_decode_culshift(APEDecoderContext * ctx, int shift)
-{
-    range_dec_normalize(ctx);
+static inline char range_decode_culshift (APEDecoderContext * ctx, int shift,
+ int * result) {
+    if (! range_dec_normalize (ctx))
+       return 0;
     ctx->rc.help = ctx->rc.range >> shift;
-    return ctx->rc.low / ctx->rc.help;
+    * result = ctx->rc.low / ctx->rc.help;
+    return 1;
 }
 
 
@@ -214,11 +217,12 @@
 }
 
 /** Decode n bits (n <= 16) without modelling */
-static inline int range_decode_bits(APEDecoderContext * ctx, int n)
-{
-    int sym = range_decode_culshift(ctx, n);
-    range_decode_update(ctx, 1, sym);
-    return sym;
+static inline char range_decode_bits (APEDecoderContext * ctx, int n,
+ int * result) {
+   if (! range_decode_culshift (ctx, n, result))
+      return 0;
+   range_decode_update (ctx, 1, * result);
+   return 1;
 }
 
 
@@ -287,20 +291,19 @@
  * @param counts probability range start position
  * @param count_diffs probability range widths
  */
-static inline int range_get_symbol(APEDecoderContext * ctx,
-                                   const uint32_t counts[],
-                                   const uint16_t counts_diff[])
-{
-    int symbol, cf;
-
-    cf = range_decode_culshift(ctx, 16);
+static inline char range_get_symbol (APEDecoderContext * ctx,
+ const uint32_t * counts, const uint16_t * counts_diff, int * result) {
+  int symbol, cf;
+    if (! range_decode_culshift (ctx, 16, & cf))
+       return 0;
 
     /* figure out the symbol inefficiently; a binary search would be much better */
     for (symbol = 0; counts[symbol + 1] <= cf; symbol++);
 
     range_decode_update(ctx, counts_diff[symbol], counts[symbol]);
 
-    return symbol;
+    * result = symbol;
+    return 1;
 }
 /** @} */ // group rangecoder
 
@@ -316,26 +319,32 @@
         rice->k++;
 }
 
-static inline int ape_decode_value(APEDecoderContext * ctx, APERice *rice)
-{
-    int x, overflow;
+static inline char ape_decode_value (APEDecoderContext * ctx, APERice * rice,
+ int * result) {
+  int x, overflow, or;
 
     if (ctx->fileversion < 3980) {
         int tmpk;
 
-        overflow = range_get_symbol(ctx, counts_3970, counts_diff_3970);
+        if (! range_get_symbol (ctx, counts_3970, counts_diff_3970, & overflow))
+           return 0;
 
         if (overflow == (MODEL_ELEMENTS - 1)) {
-            tmpk = range_decode_bits(ctx, 5);
+            if (! range_decode_bits (ctx, 5, & tmpk))
+               return 0;
             overflow = 0;
         } else
             tmpk = (rice->k < 1) ? 0 : rice->k - 1;
 
-        if (tmpk <= 16)
-            x = range_decode_bits(ctx, tmpk);
-        else {
-            x = range_decode_bits(ctx, 16);
-            x |= (range_decode_bits(ctx, tmpk - 16) << 16);
+        if (tmpk <= 16) {
+           if (! range_decode_bits (ctx, tmpk, & x))
+              return 0;
+        } else {
+           if (! range_decode_bits (ctx, 16, & x))
+              return 0;
+           if (! range_decode_bits (ctx, tmpk - 16, & or))
+              return 0;
+           x |= or << 16;
         }
         x += overflow << tmpk;
     } else {
@@ -345,14 +354,19 @@
         if (pivot == 0)
             pivot = 1;
 
-        overflow = range_get_symbol(ctx, counts_3980, counts_diff_3980);
+        if (! range_get_symbol (ctx, counts_3980, counts_diff_3980, & overflow))
+           return 0;
 
         if (overflow == (MODEL_ELEMENTS - 1)) {
-            overflow  = range_decode_bits(ctx, 16) << 16;
-            overflow |= range_decode_bits(ctx, 16);
+           if (! range_decode_bits (ctx, 16, & or))
+              return 0;
+           if (! range_decode_bits (ctx, 16, & overflow))
+              return 0;
+           overflow |= or << 16;
         }
 
-        base = range_decode_culfreq(ctx, pivot);
+        if (! range_decode_culfreq (ctx, pivot, & base))
+           return 0;
         range_decode_update(ctx, 1, base);
 
         x = base + overflow * pivot;
@@ -362,9 +376,10 @@
 
     /* Convert to signed */
     if (x & 1)
-        return (x >> 1) + 1;
+       * result = (x >> 1) + 1;
     else
-        return -(x >> 1);
+       * result = -(x >> 1);
+    return 1;
 }
 
 static void entropy_decode(APEDecoderContext * ctx, int blockstodecode, int stereo)
@@ -379,11 +394,17 @@
         memset(decoded0, 0, blockstodecode * sizeof(int32_t));
         memset(decoded1, 0, blockstodecode * sizeof(int32_t));
     } else {
-        while (blockstodecode--) {
-            *decoded0++ = ape_decode_value(ctx, &ctx->riceY);
-            if (stereo)
-                *decoded1++ = ape_decode_value(ctx, &ctx->riceX);
-        }
+       for (; blockstodecode; blockstodecode --) {
+          if (! ape_decode_value (ctx, & ctx->riceY, decoded0)
+           || (stereo && ! ape_decode_value (ctx, & ctx->riceX, decoded1))) {
+             fprintf (stderr, "ape: premature end of data\n");
+             memset (decoded0, 0, blockstodecode * sizeof (int32_t));
+             memset (decoded1, 0, blockstodecode * sizeof (int32_t));
+             return;
+          }
+          decoded0 ++;
+          decoded1 ++;
+       }
     }
 
     if (ctx->blocksdecoded == ctx->currentframeblocks)

Reply via email to