diff options
Diffstat (limited to 'libavcodec/cook.c')
-rw-r--r-- | libavcodec/cook.c | 60 |
1 files changed, 42 insertions, 18 deletions
diff --git a/libavcodec/cook.c b/libavcodec/cook.c index 90d78eb..08cd401 100644 --- a/libavcodec/cook.c +++ b/libavcodec/cook.c @@ -3,20 +3,20 @@ * Copyright (c) 2003 Sascha Sommer * Copyright (c) 2005 Benjamin Larsson * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -396,7 +396,7 @@ static int decode_envelope(COOKContext *q, COOKSubpacket *p, * @param category pointer to the category array * @param category_index pointer to the category_index array */ -static void categorize(COOKContext *q, COOKSubpacket *p, int *quant_index_table, +static void categorize(COOKContext *q, COOKSubpacket *p, const int *quant_index_table, int *category, int *category_index) { int exp_idx, bias, tmpbias1, tmpbias2, bits_left, num_bits, index, v, i, j; @@ -629,13 +629,17 @@ static int mono_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer) int category_index[128] = { 0 }; int category[128] = { 0 }; int quant_index_table[102]; - int res; + int res, i; if ((res = decode_envelope(q, p, quant_index_table)) < 0) return res; q->num_vectors = get_bits(&q->gb, p->log2_numvector_size); categorize(q, p, quant_index_table, category, category_index); expand_category(q, category, category_index); + for (i=0; i<p->total_subbands; i++) { + if (category[i] > 7) + return AVERROR_INVALIDDATA; + } decode_vectors(q, p, category, quant_index_table, mlt_buffer); return 0; @@ -735,7 +739,7 @@ static void imlt_gain(COOKContext *q, float *inbuffer, * @param q pointer to the COOKContext * @param decouple_tab decoupling array */ -static void decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) +static int decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) { int i; int vlc = get_bits1(&q->gb); @@ -744,7 +748,7 @@ static void decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) int length = end - start + 1; if (start > end) - return; + return 0; if (vlc) for (i = 0; i < length; i++) @@ -752,11 +756,18 @@ static void decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) p->channel_coupling.table, p->channel_coupling.bits, 2); else - for (i = 0; i < length; i++) - decouple_tab[start + i] = get_bits(&q->gb, p->js_vlc_bits); + for (i = 0; i < length; i++) { + int v = get_bits(&q->gb, p->js_vlc_bits); + if (v == (1<<p->js_vlc_bits)-1) { + av_log(q->avctx, AV_LOG_ERROR, "decouple value too large\n"); + return AVERROR_INVALIDDATA; + } + decouple_tab[start + i] = v; + } + return 0; } -/* +/** * function decouples a pair of signals from a single signal via multiplication. * * @param q pointer to the COOKContext @@ -804,10 +815,10 @@ static int joint_decode(COOKContext *q, COOKSubpacket *p, /* Make sure the buffers are zeroed out. */ memset(mlt_buffer_left, 0, 1024 * sizeof(*mlt_buffer_left)); memset(mlt_buffer_right, 0, 1024 * sizeof(*mlt_buffer_right)); - decouple_info(q, p, decouple_tab); + if ((res = decouple_info(q, p, decouple_tab)) < 0) + return res; if ((res = mono_decode(q, p, decode_buffer)) < 0) return res; - /* The two channels are stored interleaved in decode_buffer. */ for (i = 0; i < p->js_subband_start; i++) { for (j = 0; j < SUBBAND_SIZE; j++) { @@ -926,7 +937,7 @@ static int decode_subpacket(COOKContext *q, COOKSubpacket *p, p->mono_previous_buffer1, outbuffer ? outbuffer[p->ch_idx] : NULL); - if (p->num_channels == 2) + if (p->num_channels == 2) { if (p->joint_stereo) mlt_compensate_output(q, q->decode_buffer_2, &p->gains1, p->mono_previous_buffer2, @@ -935,6 +946,7 @@ static int decode_subpacket(COOKContext *q, COOKSubpacket *p, mlt_compensate_output(q, q->decode_buffer_2, &p->gains2, p->mono_previous_buffer2, outbuffer ? outbuffer[p->ch_idx + 1] : NULL); + } return 0; } @@ -958,10 +970,8 @@ static int cook_decode_frame(AVCodecContext *avctx, void *data, /* get output buffer */ if (q->discarded_packets >= 2) { frame->nb_samples = q->samples_per_channel; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - } samples = (float **)frame->extended_data; } @@ -1045,7 +1055,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) int extradata_size = avctx->extradata_size; int s = 0; unsigned int channel_mask = 0; - int samples_per_frame; + int samples_per_frame = 0; int ret; q->avctx = avctx; @@ -1079,6 +1089,11 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) if (extradata_size >= 8) { bytestream_get_be32(&edata_ptr); // Unknown unused q->subpacket[s].js_subband_start = bytestream_get_be16(&edata_ptr); + if (q->subpacket[s].js_subband_start >= 51) { + av_log(avctx, AV_LOG_ERROR, "js_subband_start %d is too large\n", q->subpacket[s].js_subband_start); + return AVERROR_INVALIDDATA; + } + q->subpacket[s].js_vlc_bits = bytestream_get_be16(&edata_ptr); extradata_size -= 8; } @@ -1186,11 +1201,20 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) avpriv_request_sample(avctx, "subbands > 50"); return AVERROR_PATCHWELCOME; } + if (q->subpacket[s].subbands == 0) { + avpriv_request_sample(avctx, "subbands = 0"); + return AVERROR_PATCHWELCOME; + } q->subpacket[s].gains1.now = q->subpacket[s].gain_1; q->subpacket[s].gains1.previous = q->subpacket[s].gain_2; q->subpacket[s].gains2.now = q->subpacket[s].gain_3; q->subpacket[s].gains2.previous = q->subpacket[s].gain_4; + if (q->num_subpackets + q->subpacket[s].num_channels > q->avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "Too many subpackets %d for channels %d\n", q->num_subpackets, q->avctx->channels); + return AVERROR_INVALIDDATA; + } + q->num_subpackets++; s++; if (s > MAX_SUBPACKETS) { |