# HG changeset patch # User michael # Date 1204667914 0 # Node ID e3adb7e96812c3cbcc6808bc805e4d87cbcd9b62 # Parent 28e45bf84973a0936b1ecec74cde131dc7bc5fc3 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. diff -r 28e45bf84973 -r e3adb7e96812 apedec.c --- 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)