X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fcook.c;h=361baeb3ac298844aba4bc0faf53cc34643e8aa2;hb=d92f38c179591a608390ffa9fee59c309142e79d;hp=c5f68c98ba6046261865f7dcbb4de5b6bca9e2c4;hpb=493240a522fca34882601fbeeda4e17aa40a0303;p=ffmpeg diff --git a/libavcodec/cook.c b/libavcodec/cook.c index c5f68c98ba6..361baeb3ac2 100644 --- a/libavcodec/cook.c +++ b/libavcodec/cook.c @@ -44,6 +44,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/lfg.h" +#include "libavutil/mem_internal.h" #include "audiodsp.h" #include "avcodec.h" @@ -60,11 +61,14 @@ #define MONO 0x1000001 #define STEREO 0x1000002 #define JOINT_STEREO 0x1000003 -#define MC_COOK 0x2000000 // multichannel Cook, not supported +#define MC_COOK 0x2000000 #define SUBBAND_SIZE 20 #define MAX_SUBPACKETS 5 +#define QUANT_VLC_BITS 9 +#define COUPLING_VLC_BITS 6 + typedef struct cook_gains { int *now; int *previous; @@ -143,7 +147,7 @@ typedef struct cook { /* generate tables and related variables */ int gain_size_factor; - float gain_table[23]; + float gain_table[31]; /* data buffers */ @@ -185,11 +189,26 @@ static av_cold void init_gain_table(COOKContext *q) { int i; q->gain_size_factor = q->samples_per_channel / 8; - for (i = 0; i < 23; i++) - q->gain_table[i] = pow(pow2tab[i + 52], + for (i = 0; i < 31; i++) + q->gain_table[i] = pow(pow2tab[i + 48], (1.0 / (double) q->gain_size_factor)); } +static av_cold int build_vlc(VLC *vlc, int nb_bits, const uint8_t counts[16], + const void *syms, int symbol_size, int offset, + void *logctx) +{ + uint8_t lens[MAX_COOK_VLC_ENTRIES]; + unsigned num = 0; + + for (int i = 0; i < 16; i++) + for (unsigned count = num + counts[i]; num < count; num++) + lens[num] = i + 1; + + return ff_init_vlc_from_lengths(vlc, nb_bits, num, lens, 1, + syms, symbol_size, symbol_size, + offset, 0, logctx); +} static av_cold int init_cook_vlc_tables(COOKContext *q) { @@ -197,23 +216,24 @@ static av_cold int init_cook_vlc_tables(COOKContext *q) result = 0; for (i = 0; i < 13; i++) { - result |= init_vlc(&q->envelope_quant_index[i], 9, 24, - envelope_quant_index_huffbits[i], 1, 1, - envelope_quant_index_huffcodes[i], 2, 2, 0); + result |= build_vlc(&q->envelope_quant_index[i], QUANT_VLC_BITS, + envelope_quant_index_huffcounts[i], + envelope_quant_index_huffsyms[i], 1, -12, q->avctx); } av_log(q->avctx, AV_LOG_DEBUG, "sqvh VLC init\n"); for (i = 0; i < 7; i++) { - result |= init_vlc(&q->sqvh[i], vhvlcsize_tab[i], vhsize_tab[i], - cvh_huffbits[i], 1, 1, - cvh_huffcodes[i], 2, 2, 0); + int sym_size = 1 + (i == 3); + result |= build_vlc(&q->sqvh[i], vhvlcsize_tab[i], + cvh_huffcounts[i], + cvh_huffsyms[i], sym_size, 0, q->avctx); } for (i = 0; i < q->num_subpackets; i++) { if (q->subpacket[i].joint_stereo == 1) { - result |= init_vlc(&q->subpacket[i].channel_coupling, 6, - (1 << q->subpacket[i].js_vlc_bits) - 1, - ccpl_huffbits[q->subpacket[i].js_vlc_bits - 2], 1, 1, - ccpl_huffcodes[q->subpacket[i].js_vlc_bits - 2], 2, 2, 0); + result |= build_vlc(&q->subpacket[i].channel_coupling, COUPLING_VLC_BITS, + ccpl_huffcounts[q->subpacket[i].js_vlc_bits - 2], + ccpl_huffsyms[q->subpacket[i].js_vlc_bits - 2], 1, + 0, q->avctx); av_log(q->avctx, AV_LOG_DEBUG, "subpacket %i Joint-stereo VLC used.\n", i); } } @@ -380,8 +400,8 @@ static int decode_envelope(COOKContext *q, COOKSubpacket *p, vlc_index = 13; // the VLC tables >13 are identical to No. 13 j = get_vlc2(&q->gb, q->envelope_quant_index[vlc_index - 1].table, - q->envelope_quant_index[vlc_index - 1].bits, 2); - quant_index_table[i] = quant_index_table[i - 1] + j - 12; // differential encoding + QUANT_VLC_BITS, 2); + quant_index_table[i] = quant_index_table[i - 1] + j; // differential encoding if (quant_index_table[i] > 63 || quant_index_table[i] < -63) { av_log(q->avctx, AV_LOG_ERROR, "Invalid quantizer %d at position %d, outside [-63, 63] range\n", @@ -670,7 +690,7 @@ static void interpolate_float(COOKContext *q, float *buffer, for (i = 0; i < q->gain_size_factor; i++) buffer[i] *= fc1; } else { // smooth gain - fc2 = q->gain_table[11 + (gain_index_next - gain_index)]; + fc2 = q->gain_table[15 + (gain_index_next - gain_index)]; for (i = 0; i < q->gain_size_factor; i++) { buffer[i] *= fc1; fc1 *= fc2; @@ -759,7 +779,7 @@ static int decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) for (i = 0; i < length; i++) decouple_tab[start + i] = get_vlc2(&q->gb, p->channel_coupling.table, - p->channel_coupling.bits, 2); + COUPLING_VLC_BITS, 3); else for (i = 0; i < length; i++) { int v = get_bits(&q->gb, p->js_vlc_bits); @@ -1075,12 +1095,19 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } + if (avctx->block_align >= INT_MAX / 8) + return AVERROR(EINVAL); + /* Initialize RNG. */ av_lfg_init(&q->random_state, 0); ff_audiodsp_init(&q->adsp); while (bytestream2_get_bytes_left(&gb)) { + if (s >= FFMIN(MAX_SUBPACKETS, avctx->block_align)) { + avpriv_request_sample(avctx, "subpackets > %d", FFMIN(MAX_SUBPACKETS, avctx->block_align)); + return AVERROR_PATCHWELCOME; + } /* 8 for mono, 16 for stereo, ? for multichannel Swap to right endianness so we don't need to care later on. */ q->subpacket[s].cookversion = bytestream2_get_be32(&gb); @@ -1212,11 +1239,16 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) q->num_subpackets++; s++; - if (s > FFMIN(MAX_SUBPACKETS, avctx->block_align)) { - avpriv_request_sample(avctx, "subpackets > %d", FFMIN(MAX_SUBPACKETS, avctx->block_align)); - return AVERROR_PATCHWELCOME; - } } + + /* Try to catch some obviously faulty streams, otherwise it might be exploitable */ + if (q->samples_per_channel != 256 && q->samples_per_channel != 512 && + q->samples_per_channel != 1024) { + avpriv_request_sample(avctx, "samples_per_channel = %d", + q->samples_per_channel); + return AVERROR_PATCHWELCOME; + } + /* Generate tables */ init_pow2table(); init_gain_table(q); @@ -1225,10 +1257,6 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) if ((ret = init_cook_vlc_tables(q))) return ret; - - if (avctx->block_align >= UINT_MAX / 2) - return AVERROR(EINVAL); - /* Pad the databuffer with: DECODE_BYTES_PAD1 or DECODE_BYTES_PAD2 for decode_bytes(), AV_INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */ @@ -1252,14 +1280,6 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) q->saturate_output = saturate_output_float; } - /* Try to catch some obviously faulty streams, otherwise it might be exploitable */ - if (q->samples_per_channel != 256 && q->samples_per_channel != 512 && - q->samples_per_channel != 1024) { - avpriv_request_sample(avctx, "samples_per_channel = %d", - q->samples_per_channel); - return AVERROR_PATCHWELCOME; - } - avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; if (channel_mask) avctx->channel_layout = channel_mask; @@ -1272,7 +1292,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) return 0; } -AVCodec ff_cook_decoder = { +const AVCodec ff_cook_decoder = { .name = "cook", .long_name = NULL_IF_CONFIG_SMALL("Cook / Cooker / Gecko (RealAudio G2)"), .type = AVMEDIA_TYPE_AUDIO,