Mercurial > libavcodec.hg
comparison apedec.c @ 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 |
comparison
equal
deleted
inserted
replaced
6442:28e45bf84973 | 6443:e3adb7e96812 |
---|---|
154 | 154 |
155 uint8_t *data; ///< current frame data | 155 uint8_t *data; ///< current frame data |
156 uint8_t *data_end; ///< frame data end | 156 uint8_t *data_end; ///< frame data end |
157 const uint8_t *ptr; ///< current position in frame data | 157 const uint8_t *ptr; ///< current position in frame data |
158 const uint8_t *last_ptr; ///< position where last 4608-sample block ended | 158 const uint8_t *last_ptr; ///< position where last 4608-sample block ended |
159 | |
160 int error; | |
159 } APEContext; | 161 } APEContext; |
160 | 162 |
161 // TODO: dsputilize | 163 // TODO: dsputilize |
162 static inline void vector_add(int16_t * v1, int16_t * v2, int order) | 164 static inline void vector_add(int16_t * v1, int16_t * v2, int order) |
163 { | 165 { |
380 { | 382 { |
381 int symbol, cf; | 383 int symbol, cf; |
382 | 384 |
383 cf = range_decode_culshift(ctx, 16); | 385 cf = range_decode_culshift(ctx, 16); |
384 | 386 |
387 if(cf > 65492){ | |
388 symbol= cf - 65535 + 63; | |
389 range_decode_update(ctx, 1, cf); | |
390 if(cf > 65535) | |
391 ctx->error=1; | |
392 return symbol; | |
393 } | |
385 /* figure out the symbol inefficiently; a binary search would be much better */ | 394 /* figure out the symbol inefficiently; a binary search would be much better */ |
386 for (symbol = 0; counts[symbol + 1] <= cf; symbol++); | 395 for (symbol = 0; counts[symbol + 1] <= cf; symbol++); |
387 | 396 |
388 range_decode_update(ctx, counts_diff[symbol], counts[symbol]); | 397 range_decode_update(ctx, counts_diff[symbol], counts[symbol]); |
389 | 398 |
892 } | 901 } |
893 | 902 |
894 nblocks = s->samples; | 903 nblocks = s->samples; |
895 blockstodecode = FFMIN(BLOCKS_PER_LOOP, nblocks); | 904 blockstodecode = FFMIN(BLOCKS_PER_LOOP, nblocks); |
896 | 905 |
906 s->error=0; | |
907 | |
897 if ((s->channels == 1) || (s->frameflags & APE_FRAMECODE_PSEUDO_STEREO)) | 908 if ((s->channels == 1) || (s->frameflags & APE_FRAMECODE_PSEUDO_STEREO)) |
898 ape_unpack_mono(s, blockstodecode); | 909 ape_unpack_mono(s, blockstodecode); |
899 else | 910 else |
900 ape_unpack_stereo(s, blockstodecode); | 911 ape_unpack_stereo(s, blockstodecode); |
912 | |
913 if(s->error || s->ptr > s->data_end){ | |
914 s->samples=0; | |
915 av_log(avctx, AV_LOG_ERROR, "Error decoding frame\n"); | |
916 return -1; | |
917 } | |
901 | 918 |
902 for (i = 0; i < blockstodecode; i++) { | 919 for (i = 0; i < blockstodecode; i++) { |
903 *samples++ = s->decoded0[i]; | 920 *samples++ = s->decoded0[i]; |
904 if(s->channels == 2) | 921 if(s->channels == 2) |
905 *samples++ = s->decoded1[i]; | 922 *samples++ = s->decoded1[i]; |