diff options
author | Laurent Aimar <fenrir@videolan.org> | 2011-09-08 00:02:55 +0400 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-12-24 15:20:32 +0400 |
commit | 1edc513bcf78341b4614081812cc7b66cd84b465 (patch) | |
tree | 37e7c1867daeb57a6e241c3f3231dd0e96b55ca1 | |
parent | 9864518544f85ca8f0c2764fd66d728c47652bcc (diff) |
Fixed invalid access in wavpack decoder on corrupted bitstream.
Signed-off-by: Martin Storsjö <martin@martin.st>
(cherry picked from commit 55354b7de21e7bb4bbeb1c12ff55ea17f807c70c)
Signed-off-by: Anton Khirnov <anton@khirnov.net>
(cherry picked from commit 4b84e995ad88f3bfa533c38218f2791c14fd72f0)
Signed-off-by: Reinhard Tartler <siretart@tauware.de>
-rw-r--r-- | libavcodec/wavpack.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index 3963a6003d..906ccea766 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -275,7 +275,14 @@ static int wv_get_value(WavpackContext *ctx, GetBitContext *gb, int channel, int } }else{ t = get_unary_0_33(gb); - if(t >= 2) t = get_bits(gb, t - 1) | (1 << (t-1)); + if(t >= 2){ + if(get_bits_left(gb) < t-1) + goto error; + t = get_bits(gb, t - 1) | (1 << (t-1)); + }else{ + if(get_bits_left(gb) < 0) + goto error; + } ctx->zeroes = t; if(ctx->zeroes){ memset(ctx->ch[0].median, 0, sizeof(ctx->ch[0].median)); @@ -286,24 +293,24 @@ static int wv_get_value(WavpackContext *ctx, GetBitContext *gb, int channel, int } } - if(get_bits_count(gb) >= ctx->data_size){ - *last = 1; - return 0; - } - if(ctx->zero){ t = 0; ctx->zero = 0; }else{ t = get_unary_0_33(gb); - if(get_bits_count(gb) >= ctx->data_size){ - *last = 1; - return 0; - } + if(get_bits_left(gb) < 0) + goto error; if(t == 16) { t2 = get_unary_0_33(gb); - if(t2 < 2) t += t2; - else t += get_bits(gb, t2 - 1) | (1 << (t2 - 1)); + if(t2 < 2){ + if(get_bits_left(gb) < 0) + goto error; + t += t2; + }else{ + if(get_bits_left(gb) < t2 - 1) + goto error; + t += get_bits(gb, t2 - 1) | (1 << (t2 - 1)); + } } if(ctx->one){ @@ -343,9 +350,13 @@ static int wv_get_value(WavpackContext *ctx, GetBitContext *gb, int channel, int } if(!c->error_limit){ ret = base + get_tail(gb, add); + if (get_bits_left(gb) <= 0) + goto error; }else{ int mid = (base*2 + add + 1) >> 1; while(add > c->error_limit){ + if(get_bits_left(gb) <= 0) + goto error; if(get_bits1(gb)){ add -= (mid - base); base = mid; @@ -359,6 +370,10 @@ static int wv_get_value(WavpackContext *ctx, GetBitContext *gb, int channel, int if(ctx->hybrid_bitrate) c->slow_level += wp_log2(ret) - LEVEL_DECAY(c->slow_level); return sign ? ~ret : ret; + +error: + *last = 1; + return 0; } static inline int wv_get_value_integer(WavpackContext *s, uint32_t *crc, int S) @@ -559,7 +574,10 @@ static inline int wv_unpack_stereo(WavpackContext *s, GetBitContext *gb, void *d count++; }while(!last && count < s->max_samples); - s->samples_left -= count; + if (last) + s->samples_left = 0; + else + s->samples_left -= count; if(!s->samples_left){ if(crc != s->CRC){ av_log(s->avctx, AV_LOG_ERROR, "CRC error\n"); @@ -632,7 +650,10 @@ static inline int wv_unpack_mono(WavpackContext *s, GetBitContext *gb, void *dst count++; }while(!last && count < s->samples); - s->samples_left -= count; + if (last) + s->samples_left = 0; + else + s->samples_left -= count; if(!s->samples_left){ if(crc != s->CRC){ av_log(s->avctx, AV_LOG_ERROR, "CRC error\n"); |