From 3f0b6d7a6248a33df37b98cfcb37a1acce263f62 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 22 May 2013 12:27:04 +0200 Subject: wavpack: use bytestream2 in wavpack_decode_block Prevent most out of buffer reads. Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/wavpack.c | 166 +++++++++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 83 deletions(-) (limited to 'libavcodec/wavpack.c') diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index 8d7c82b2fe..cfcd22d9f6 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -26,6 +26,7 @@ #include "get_bits.h" #include "internal.h" #include "unary.h" +#include "bytestream.h" /** * @file @@ -761,12 +762,11 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, { WavpackContext *wc = avctx->priv_data; WavpackFrameContext *s; + GetByteContext gb; void *samples = data; int samplecount; int got_terms = 0, got_weights = 0, got_samples = 0, got_entropy = 0, got_bs = 0, got_float = 0, got_hybrid = 0; - const uint8_t *orig_buf = buf; - const uint8_t *buf_end = buf + buf_size; int i, j, id, size, ssize, weights, t; int bpp, chan, chmask, orig_bpp; @@ -793,9 +793,10 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, s->and = s->or = s->shift = 0; s->got_extra_bits = 0; + bytestream2_init(&gb, buf, buf_size); + if (!wc->mkv_mode) { - s->samples = AV_RL32(buf); - buf += 4; + s->samples = bytestream2_get_le32(&gb); if (s->samples != wc->samples) return AVERROR_INVALIDDATA; @@ -806,8 +807,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, } else { s->samples = wc->samples; } - s->frame_flags = AV_RL32(buf); - buf += 4; + s->frame_flags = bytestream2_get_le32(&gb); bpp = av_get_bytes_per_sample(avctx->sample_fmt); samples = (uint8_t *)samples + bpp * wc->ch_offset; orig_bpp = ((s->frame_flags & 0x03) + 1) << 3; @@ -820,20 +820,20 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, s->post_shift = bpp * 8 - orig_bpp + ((s->frame_flags >> 13) & 0x1f); s->hybrid_maxclip = ((1LL << (orig_bpp - 1)) - 1); s->hybrid_minclip = ((-1LL << (orig_bpp - 1))); - s->CRC = AV_RL32(buf); - buf += 4; + s->CRC = bytestream2_get_le32(&gb); + if (wc->mkv_mode) - buf += 4; // skip block size; + bytestream2_skip(&gb, 4); // skip block size; wc->ch_offset += 1 + s->stereo; // parse metadata blocks - while (buf < buf_end) { - id = *buf++; - size = *buf++; + while (bytestream2_get_bytes_left(&gb)) { + id = bytestream2_get_byte(&gb); + size = bytestream2_get_byte(&gb); if (id & WP_IDF_LONG) { - size |= (*buf++) << 8; - size |= (*buf++) << 16; + size |= (bytestream2_get_byte(&gb)) << 8; + size |= (bytestream2_get_byte(&gb)) << 16; } size <<= 1; // size is specified in words ssize = size; @@ -844,13 +844,13 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, "Got incorrect block %02X with size %i\n", id, size); break; } - if (buf + ssize > buf_end) { + if (bytestream2_get_bytes_left(&gb) < ssize) { av_log(avctx, AV_LOG_ERROR, "Block size %i is out of bounds\n", size); break; } if (id & WP_IDF_IGNORE) { - buf += ssize; + bytestream2_skip(&gb, ssize); continue; } switch (id & WP_IDF_MASK) { @@ -858,14 +858,14 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, if (size > MAX_TERMS) { av_log(avctx, AV_LOG_ERROR, "Too many decorrelation terms\n"); s->terms = 0; - buf += ssize; + bytestream2_skip(&gb, ssize); continue; } s->terms = size; for (i = 0; i < s->terms; i++) { - s->decorr[s->terms - i - 1].value = (*buf & 0x1F) - 5; - s->decorr[s->terms - i - 1].delta = *buf >> 5; - buf++; + uint8_t val = bytestream2_get_byte(&gb); + s->decorr[s->terms - i - 1].value = (val & 0x1F) - 5; + s->decorr[s->terms - i - 1].delta = val >> 5; } got_terms = 1; break; @@ -877,17 +877,17 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, weights = size >> s->stereo_in; if (weights > MAX_TERMS || weights > s->terms) { av_log(avctx, AV_LOG_ERROR, "Too many decorrelation weights\n"); - buf += ssize; + bytestream2_skip(&gb, ssize); continue; } for (i = 0; i < weights; i++) { - t = (int8_t)(*buf++); + t = (int8_t)bytestream2_get_byte(&gb); s->decorr[s->terms - i - 1].weightA = t << 3; if (s->decorr[s->terms - i - 1].weightA > 0) s->decorr[s->terms - i - 1].weightA += (s->decorr[s->terms - i - 1].weightA + 64) >> 7; if (s->stereo_in) { - t = (int8_t)(*buf++); + t = (int8_t)bytestream2_get_byte(&gb); s->decorr[s->terms - i - 1].weightB = t << 3; if (s->decorr[s->terms - i - 1].weightB > 0) s->decorr[s->terms - i - 1].weightB += @@ -904,31 +904,32 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, t = 0; for (i = s->terms - 1; (i >= 0) && (t < size); i--) { if (s->decorr[i].value > 8) { - s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); - buf += 2; - s->decorr[i].samplesA[1] = wp_exp2(AV_RL16(buf)); - buf += 2; + s->decorr[i].samplesA[0] = + wp_exp2(bytestream2_get_le16(&gb)); + s->decorr[i].samplesA[1] = + wp_exp2(bytestream2_get_le16(&gb)); + if (s->stereo_in) { - s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); - buf += 2; - s->decorr[i].samplesB[1] = wp_exp2(AV_RL16(buf)); - buf += 2; + s->decorr[i].samplesB[0] = + wp_exp2(bytestream2_get_le16(&gb)); + s->decorr[i].samplesB[1] = + wp_exp2(bytestream2_get_le16(&gb)); t += 4; } t += 4; } else if (s->decorr[i].value < 0) { - s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); - buf += 2; - s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); - buf += 2; + s->decorr[i].samplesA[0] = + wp_exp2(bytestream2_get_le16(&gb)); + s->decorr[i].samplesB[0] = + wp_exp2(bytestream2_get_le16(&gb)); t += 4; } else { for (j = 0; j < s->decorr[i].value; j++) { - s->decorr[i].samplesA[j] = wp_exp2(AV_RL16(buf)); - buf += 2; + s->decorr[i].samplesA[j] = + wp_exp2(bytestream2_get_le16(&gb)); if (s->stereo_in) { - s->decorr[i].samplesB[j] = wp_exp2(AV_RL16(buf)); - buf += 2; + s->decorr[i].samplesB[j] = + wp_exp2(bytestream2_get_le16(&gb)); } } t += s->decorr[i].value * 2 * (s->stereo_in + 1); @@ -941,33 +942,30 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, av_log(avctx, AV_LOG_ERROR, "Entropy vars size should be %i, got %i", 6 * (s->stereo_in + 1), size); - buf += ssize; + bytestream2_skip(&gb, ssize); continue; } for (j = 0; j <= s->stereo_in; j++) for (i = 0; i < 3; i++) { - s->ch[j].median[i] = wp_exp2(AV_RL16(buf)); - buf += 2; + s->ch[j].median[i] = wp_exp2(bytestream2_get_le16(&gb)); } got_entropy = 1; break; case WP_ID_HYBRID: if (s->hybrid_bitrate) { for (i = 0; i <= s->stereo_in; i++) { - s->ch[i].slow_level = wp_exp2(AV_RL16(buf)); - buf += 2; + s->ch[i].slow_level = wp_exp2(bytestream2_get_le16(&gb)); size -= 2; } } for (i = 0; i < (s->stereo_in + 1); i++) { - s->ch[i].bitrate_acc = AV_RL16(buf) << 16; - buf += 2; + s->ch[i].bitrate_acc = bytestream2_get_le16(&gb) << 16; size -= 2; } if (size > 0) { for (i = 0; i < (s->stereo_in + 1); i++) { - s->ch[i].bitrate_delta = wp_exp2((int16_t)AV_RL16(buf)); - buf += 2; + s->ch[i].bitrate_delta = + wp_exp2((int16_t)bytestream2_get_le16(&gb)); } } else { for (i = 0; i < (s->stereo_in + 1); i++) @@ -975,24 +973,26 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, } got_hybrid = 1; break; - case WP_ID_INT32INFO: + case WP_ID_INT32INFO: { + uint8_t val[4]; if (size != 4) { av_log(avctx, AV_LOG_ERROR, - "Invalid INT32INFO, size = %i, sent_bits = %i\n", - size, *buf); - buf += ssize; + "Invalid INT32INFO, size = %i\n", + size); + bytestream2_skip(&gb, ssize - 4); continue; } - if (buf[0]) - s->extra_bits = buf[0]; - else if (buf[1]) - s->shift = buf[1]; - else if (buf[2]) { + bytestream2_get_buffer(&gb, val, 4); + if (val[0]) { + s->extra_bits = val[0]; + } else if (val[1]) { + s->shift = val[1]; + } else if (val[2]) { s->and = s->or = 1; - s->shift = buf[2]; - } else if (buf[3]) { + s->shift = val[2]; + } else if (val[3]) { s->and = 1; - s->shift = buf[3]; + s->shift = val[3]; } /* original WavPack decoder forces 32-bit lossy sound to be treated * as 24-bit one in order to have proper clipping */ @@ -1002,41 +1002,41 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, s->hybrid_maxclip >>= 8; s->hybrid_minclip >>= 8; } - buf += 4; break; + } case WP_ID_FLOATINFO: if (size != 4) { av_log(avctx, AV_LOG_ERROR, "Invalid FLOATINFO, size = %i\n", size); - buf += ssize; + bytestream2_skip(&gb, ssize); continue; } - s->float_flag = buf[0]; - s->float_shift = buf[1]; - s->float_max_exp = buf[2]; - buf += 4; + s->float_flag = bytestream2_get_byte(&gb); + s->float_shift = bytestream2_get_byte(&gb); + s->float_max_exp = bytestream2_get_byte(&gb); got_float = 1; + bytestream2_skip(&gb, 1); break; case WP_ID_DATA: - s->sc.offset = buf - orig_buf; + s->sc.offset = bytestream2_tell(&gb); s->sc.size = size * 8; - init_get_bits(&s->gb, buf, size * 8); + init_get_bits(&s->gb, gb.buffer, size * 8); s->data_size = size * 8; - buf += size; + bytestream2_skip(&gb, size); got_bs = 1; break; case WP_ID_EXTRABITS: if (size <= 4) { av_log(avctx, AV_LOG_ERROR, "Invalid EXTRABITS, size = %i\n", size); - buf += size; + bytestream2_skip(&gb, size); continue; } - s->extra_sc.offset = buf - orig_buf; + s->extra_sc.offset = bytestream2_tell(&gb); s->extra_sc.size = size * 8; - init_get_bits(&s->gb_extra_bits, buf, size * 8); + init_get_bits(&s->gb_extra_bits, gb.buffer, size * 8); s->crc_extra_bits = get_bits_long(&s->gb_extra_bits, 32); - buf += size; + bytestream2_skip(&gb, size); s->got_extra_bits = 1; break; case WP_ID_CHANINFO: @@ -1045,23 +1045,24 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, "Insufficient channel information\n"); return AVERROR_INVALIDDATA; } - chan = *buf++; + chan = bytestream2_get_byte(&gb); switch (size - 2) { case 0: - chmask = *buf; + chmask = bytestream2_get_byte(&gb); break; case 1: - chmask = AV_RL16(buf); + chmask = bytestream2_get_le16(&gb); break; case 2: - chmask = AV_RL24(buf); + chmask = bytestream2_get_le24(&gb); break; case 3: - chmask = AV_RL32(buf); + chmask = bytestream2_get_le32(&gb);; break; case 5: - chan |= (buf[1] & 0xF) << 8; - chmask = AV_RL24(buf + 2); + bytestream2_skip(&gb, 1); + chan |= (bytestream2_get_byte(&gb) & 0xF) << 8; + chmask = bytestream2_get_le16(&gb); break; default: av_log(avctx, AV_LOG_ERROR, "Invalid channel info size %d\n", @@ -1078,13 +1079,12 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, } if (!avctx->channel_layout) avctx->channel_layout = chmask; - buf += size - 1; break; default: - buf += size; + bytestream2_skip(&gb, size); } if (id & WP_IDF_ODD) - buf++; + bytestream2_skip(&gb, 1); } if (!got_terms) { -- cgit v1.2.3