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)