[FFmpeg-cvslog] wavpack: use bytestream2 in wavpack_decode_block
Luca Barbato
git at videolan.org
Mon Jun 3 01:17:55 CEST 2013
ffmpeg | branch: release/1.1 | Luca Barbato <lu_zero at gentoo.org> | Wed May 22 12:27:04 2013 +0200| [7251de30322aff5660e571856132dc6c7256fe94] | committer: Reinhard Tartler
wavpack: use bytestream2 in wavpack_decode_block
Prevent most out of buffer reads.
Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
CC: libav-stable at libav.org
(cherry picked from commit 3f0b6d7a6248a33df37b98cfcb37a1acce263f62)
Signed-off-by: Reinhard Tartler <siretart at tauware.de>
Conflicts:
libavcodec/wavpack.c
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=7251de30322aff5660e571856132dc6c7256fe94
---
libavcodec/wavpack.c | 189 ++++++++++++++++++++++++++++----------------------
1 file changed, 106 insertions(+), 83 deletions(-)
diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c
index 0bbed04..02cef5f 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
@@ -763,12 +764,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;
@@ -794,8 +794,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,7 +808,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;
@@ -819,19 +821,19 @@ 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;
@@ -841,12 +843,13 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
av_log(avctx, AV_LOG_ERROR, "Got incorrect block %02X with size %i\n", id, size);
break;
}
- if (buf + ssize > buf_end) {
- av_log(avctx, AV_LOG_ERROR, "Block size %i is out of bounds\n", size);
+ 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) {
@@ -854,14 +857,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;
@@ -873,17 +876,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 +=
@@ -900,23 +903,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;
- t += 4;
+ 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;
- t += 4;
+ 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);
@@ -926,15 +938,15 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
break;
case WP_ID_ENTROPY:
if (size != 6 * (s->stereo_in + 1)) {
- av_log(avctx, AV_LOG_ERROR, "Entropy vars size should be %i, "
- "got %i", 6 * (s->stereo_in + 1), size);
- buf += ssize;
+ av_log(avctx, AV_LOG_ERROR,
+ "Entropy vars size should be %i, got %i",
+ 6 * (s->stereo_in + 1), size);
+ 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;
@@ -942,20 +954,18 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
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;
- size -= 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;
- size -= 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++)
@@ -963,22 +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;
+ av_log(avctx, AV_LOG_ERROR,
+ "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]){
- s->and = s->or = 1;
- s->shift = buf[2];
- } else if(buf[3]) {
+ 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 = 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
@@ -989,56 +1003,66 @@ 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;
+ av_log(avctx, AV_LOG_ERROR,
+ "Invalid FLOATINFO, size = %i\n", size);
+ bytestream2_skip(&gb, ssize);
continue;
}
- s->float_flag = buf[0];
- s->float_shift = buf[1];
- s->float_max_exp = buf[2];
- buf += 4;
- got_float = 1;
+ 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);
- s->crc_extra_bits = get_bits_long(&s->gb_extra_bits, 32);
- buf += size;
- s->got_extra_bits = 1;
+ init_get_bits(&s->gb_extra_bits, gb.buffer, size * 8);
+ s->crc_extra_bits = get_bits_long(&s->gb_extra_bits, 32);
+ bytestream2_skip(&gb, size);
+ s->got_extra_bits = 1;
break;
case WP_ID_CHANINFO:
if (size <= 1) {
av_log(avctx, AV_LOG_ERROR, "Insufficient channel information\n");
return AVERROR_INVALIDDATA;
}
- chan = *buf++;
+ chan = bytestream2_get_byte(&gb);
switch (size - 2) {
- case 0: chmask = *buf; break;
- case 1: chmask = AV_RL16(buf); break;
- case 2: chmask = AV_RL24(buf); break;
- case 3: chmask = AV_RL32(buf); break;
+ case 0:
+ chmask = bytestream2_get_byte(&gb);
+ break;
+ case 1:
+ chmask = bytestream2_get_le16(&gb);
+ break;
+ case 2:
+ chmask = bytestream2_get_le24(&gb);
+ break;
+ case 3:
+ 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",
@@ -1055,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) {
More information about the ffmpeg-cvslog
mailing list