X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fwmaprodec.c;h=9607e509681ed1ca957ed14620bc590ccb57d1fc;hb=a247ac640df3da573cd661065bf53f37863e2b46;hp=d0fa974c80bf6af043a7522620b097d16c954fd3;hpb=39278ff0de5b5e3397c22538978bffbb38ee099b;p=ffmpeg diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index d0fa974c80b..9607e509681 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -92,6 +92,8 @@ #include "libavutil/float_dsp.h" #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "internal.h" #include "get_bits.h" @@ -437,7 +439,7 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu av_log(avctx, AV_LOG_ERROR, "invalid number of channels per XMA stream %d\n", s->nb_channels); return AVERROR_INVALIDDATA; - } else if (s->nb_channels > WMAPRO_MAX_CHANNELS) { + } else if (s->nb_channels > WMAPRO_MAX_CHANNELS || s->nb_channels > avctx->channels) { avpriv_request_sample(avctx, "More than %d channels", WMAPRO_MAX_CHANNELS); return AVERROR_PATCHWELCOME; @@ -544,7 +546,7 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) ff_mdct_init(&s->mdct_ctx[i], WMAPRO_BLOCK_MIN_BITS+1+i, 1, 1.0 / (1 << (WMAPRO_BLOCK_MIN_BITS + i - 1)) - / (1 << (s->bits_per_sample - 1))); + / (1ll << (s->bits_per_sample - 1))); /** init MDCT windows: simple sine window */ for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) { @@ -1565,9 +1567,9 @@ static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len, s->frame_offset = get_bits_count(gb) & 7; s->num_saved_bits = s->frame_offset; init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); - } - - buflen = (put_bits_count(&s->pb) + len + 8) >> 3; + buflen = (s->num_saved_bits + len + 7) >> 3; + } else + buflen = (put_bits_count(&s->pb) + len + 7) >> 3; if (len <= 0 || buflen > MAX_FRAMESIZE) { avpriv_request_sample(s->avctx, "Too small input buffer"); @@ -1579,14 +1581,14 @@ static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len, s->num_saved_bits += len; if (!append) { - avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), + ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), s->num_saved_bits); } else { int align = 8 - (get_bits_count(gb) & 7); align = FFMIN(align, len); put_bits(&s->pb, align, get_bits(gb, align)); len -= align; - avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len); + ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len); } skip_bits_long(gb, len); @@ -1644,6 +1646,7 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, if (avctx->codec_id == AV_CODEC_ID_WMAPRO && buf_size < avctx->block_align) { av_log(avctx, AV_LOG_ERROR, "Input packet too small (%d < %d)\n", buf_size, avctx->block_align); + s->packet_loss = 1; return AVERROR_INVALIDDATA; } @@ -1718,6 +1721,12 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, } } else { int frame_size; + + if (avpkt->size < s->next_packet_start) { + s->packet_loss = 1; + return AVERROR_INVALIDDATA; + } + s->buf_bit_size = (avpkt->size - s->next_packet_start) << 3; init_get_bits(gb, avpkt->data, s->buf_bit_size); skip_bits(gb, s->packet_offset); @@ -1793,10 +1802,21 @@ static int xma_decode_packet(AVCodecContext *avctx, void *data, AVFrame *frame = data; int i, ret, offset = INT_MAX; + if (!s->frames[s->current_stream]->data[0]) { + s->frames[s->current_stream]->nb_samples = 512; + if ((ret = ff_get_buffer(avctx, s->frames[s->current_stream], 0)) < 0) { + return ret; + } + } /* decode current stream packet */ ret = decode_packet(avctx, &s->xma[s->current_stream], s->frames[s->current_stream], &got_stream_frame_ptr, avpkt); + if (got_stream_frame_ptr && s->offset[s->current_stream] >= 64) { + got_stream_frame_ptr = 0; + ret = AVERROR_INVALIDDATA; + } + /* copy stream samples (1/2ch) to sample buffer (Nch) */ if (got_stream_frame_ptr) { int start_ch = s->start_channel[s->current_stream]; @@ -1888,12 +1908,14 @@ static av_cold int xma_decode_init(AVCodecContext *avctx) s->num_streams = avctx->extradata[1]; if (avctx->extradata_size != (32 + ((avctx->extradata[0]==3)?0:8) + 4*s->num_streams)) { av_log(avctx, AV_LOG_ERROR, "Incorrect XMA2 extradata size\n"); + s->num_streams = 0; return AVERROR(EINVAL); } } else if (avctx->codec_id == AV_CODEC_ID_XMA1 && avctx->extradata_size >= 4) { /* XMAWAVEFORMAT */ s->num_streams = avctx->extradata[4]; if (avctx->extradata_size != (8 + 20*s->num_streams)) { av_log(avctx, AV_LOG_ERROR, "Incorrect XMA1 extradata size\n"); + s->num_streams = 0; return AVERROR(EINVAL); } } else { @@ -1902,8 +1924,11 @@ static av_cold int xma_decode_init(AVCodecContext *avctx) } /* encoder supports up to 64 streams / 64*2 channels (would have to alloc arrays) */ - if (avctx->channels > XMA_MAX_CHANNELS || s->num_streams > XMA_MAX_STREAMS) { + if (avctx->channels > XMA_MAX_CHANNELS || s->num_streams > XMA_MAX_STREAMS || + s->num_streams <= 0 + ) { avpriv_request_sample(avctx, "More than %d channels in %d streams", XMA_MAX_CHANNELS, s->num_streams); + s->num_streams = 0; return AVERROR_PATCHWELCOME; } @@ -1915,14 +1940,12 @@ static av_cold int xma_decode_init(AVCodecContext *avctx) s->frames[i] = av_frame_alloc(); if (!s->frames[i]) return AVERROR(ENOMEM); - s->frames[i]->nb_samples = 512; - if ((ret = ff_get_buffer(avctx, s->frames[i], 0)) < 0) { - return AVERROR(ENOMEM); - } s->start_channel[i] = start_channels; start_channels += s->xma[i].nb_channels; } + if (start_channels != avctx->channels) + return AVERROR_INVALIDDATA; return ret; } @@ -1936,6 +1959,7 @@ static av_cold int xma_decode_end(AVCodecContext *avctx) decode_end(&s->xma[i]); av_frame_free(&s->frames[i]); } + s->num_streams = 0; return 0; } @@ -1981,7 +2005,7 @@ static void xma_flush(AVCodecContext *avctx) /** *@brief wmapro decoder */ -AVCodec ff_wmapro_decoder = { +const AVCodec ff_wmapro_decoder = { .name = "wmapro", .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"), .type = AVMEDIA_TYPE_AUDIO, @@ -1991,12 +2015,13 @@ AVCodec ff_wmapro_decoder = { .close = wmapro_decode_end, .decode = wmapro_decode_packet, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .flush = wmapro_flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; -AVCodec ff_xma1_decoder = { +const AVCodec ff_xma1_decoder = { .name = "xma1", .long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 1"), .type = AVMEDIA_TYPE_AUDIO, @@ -2006,11 +2031,12 @@ AVCodec ff_xma1_decoder = { .close = xma_decode_end, .decode = xma_decode_packet, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; -AVCodec ff_xma2_decoder = { +const AVCodec ff_xma2_decoder = { .name = "xma2", .long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 2"), .type = AVMEDIA_TYPE_AUDIO, @@ -2021,6 +2047,7 @@ AVCodec ff_xma2_decoder = { .decode = xma_decode_packet, .flush = xma_flush, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, };