Commit 101ef19e authored by Justin Ruggles's avatar Justin Ruggles

binkaudio: add some buffer overread checks.

This stops decoding before overreads instead of after.
parent 20732246
...@@ -152,11 +152,18 @@ static const uint8_t rle_length_tab[16] = { ...@@ -152,11 +152,18 @@ static const uint8_t rle_length_tab[16] = {
2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64
}; };
#define GET_BITS_SAFE(out, nbits) do { \
if (get_bits_left(gb) < nbits) \
return AVERROR_INVALIDDATA; \
out = get_bits(gb, nbits); \
} while (0)
/** /**
* Decode Bink Audio block * Decode Bink Audio block
* @param[out] out Output buffer (must contain s->block_size elements) * @param[out] out Output buffer (must contain s->block_size elements)
* @return 0 on success, negative error code on failure
*/ */
static void decode_block(BinkAudioContext *s, short *out, int use_dct) static int decode_block(BinkAudioContext *s, short *out, int use_dct)
{ {
int ch, i, j, k; int ch, i, j, k;
float q, quant[25]; float q, quant[25];
...@@ -169,13 +176,19 @@ static void decode_block(BinkAudioContext *s, short *out, int use_dct) ...@@ -169,13 +176,19 @@ static void decode_block(BinkAudioContext *s, short *out, int use_dct)
for (ch = 0; ch < s->channels; ch++) { for (ch = 0; ch < s->channels; ch++) {
FFTSample *coeffs = s->coeffs_ptr[ch]; FFTSample *coeffs = s->coeffs_ptr[ch];
if (s->version_b) { if (s->version_b) {
if (get_bits_left(gb) < 64)
return AVERROR_INVALIDDATA;
coeffs[0] = av_int2flt(get_bits(gb, 32)) * s->root; coeffs[0] = av_int2flt(get_bits(gb, 32)) * s->root;
coeffs[1] = av_int2flt(get_bits(gb, 32)) * s->root; coeffs[1] = av_int2flt(get_bits(gb, 32)) * s->root;
} else { } else {
if (get_bits_left(gb) < 58)
return AVERROR_INVALIDDATA;
coeffs[0] = get_float(gb) * s->root; coeffs[0] = get_float(gb) * s->root;
coeffs[1] = get_float(gb) * s->root; coeffs[1] = get_float(gb) * s->root;
} }
if (get_bits_left(gb) < s->num_bands * 8)
return AVERROR_INVALIDDATA;
for (i = 0; i < s->num_bands; i++) { for (i = 0; i < s->num_bands; i++) {
/* constant is result of 0.066399999/log10(M_E) */ /* constant is result of 0.066399999/log10(M_E) */
int value = get_bits(gb, 8); int value = get_bits(gb, 8);
...@@ -190,15 +203,20 @@ static void decode_block(BinkAudioContext *s, short *out, int use_dct) ...@@ -190,15 +203,20 @@ static void decode_block(BinkAudioContext *s, short *out, int use_dct)
while (i < s->frame_len) { while (i < s->frame_len) {
if (s->version_b) { if (s->version_b) {
j = i + 16; j = i + 16;
} else if (get_bits1(gb)) { } else {
j = i + rle_length_tab[get_bits(gb, 4)] * 8; int v;
GET_BITS_SAFE(v, 1);
if (v) {
GET_BITS_SAFE(v, 4);
j = i + rle_length_tab[v] * 8;
} else { } else {
j = i + 8; j = i + 8;
} }
}
j = FFMIN(j, s->frame_len); j = FFMIN(j, s->frame_len);
width = get_bits(gb, 4); GET_BITS_SAFE(width, 4);
if (width == 0) { if (width == 0) {
memset(coeffs + i, 0, (j - i) * sizeof(*coeffs)); memset(coeffs + i, 0, (j - i) * sizeof(*coeffs));
i = j; i = j;
...@@ -208,9 +226,11 @@ static void decode_block(BinkAudioContext *s, short *out, int use_dct) ...@@ -208,9 +226,11 @@ static void decode_block(BinkAudioContext *s, short *out, int use_dct)
while (i < j) { while (i < j) {
if (s->bands[k] == i) if (s->bands[k] == i)
q = quant[k++]; q = quant[k++];
coeff = get_bits(gb, width); GET_BITS_SAFE(coeff, width);
if (coeff) { if (coeff) {
if (get_bits1(gb)) int v;
GET_BITS_SAFE(v, 1);
if (v)
coeffs[i] = -q * coeff; coeffs[i] = -q * coeff;
else else
coeffs[i] = q * coeff; coeffs[i] = q * coeff;
...@@ -246,6 +266,8 @@ static void decode_block(BinkAudioContext *s, short *out, int use_dct) ...@@ -246,6 +266,8 @@ static void decode_block(BinkAudioContext *s, short *out, int use_dct)
s->overlap_len * s->channels * sizeof(*out)); s->overlap_len * s->channels * sizeof(*out));
s->first = 0; s->first = 0;
return 0;
} }
static av_cold int decode_end(AVCodecContext *avctx) static av_cold int decode_end(AVCodecContext *avctx)
...@@ -277,12 +299,17 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -277,12 +299,17 @@ static int decode_frame(AVCodecContext *avctx,
int reported_size; int reported_size;
GetBitContext *gb = &s->gb; GetBitContext *gb = &s->gb;
if (buf_size < 4) {
av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
return AVERROR_INVALIDDATA;
}
init_get_bits(gb, buf, buf_size * 8); init_get_bits(gb, buf, buf_size * 8);
reported_size = get_bits_long(gb, 32); reported_size = get_bits_long(gb, 32);
while (get_bits_count(gb) / 8 < buf_size && while (samples + s->block_size <= samples_end) {
samples + s->block_size <= samples_end) { if (decode_block(s, samples, avctx->codec->id == CODEC_ID_BINKAUDIO_DCT))
decode_block(s, samples, avctx->codec->id == CODEC_ID_BINKAUDIO_DCT); break;
samples += s->block_size; samples += s->block_size;
get_bits_align32(gb); get_bits_align32(gb);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment