X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fwcmv.c;h=04c597e7674616bd70eb6fa00d68604d22f2f5bb;hb=0bf3a7361d17d596a5044882098f56817db0e103;hp=384ceecd32f13b353a197e8d6f2c6405a0c6c30e;hpb=203bbaccfaaeac9548862e83792d38509a8c8167;p=ffmpeg diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c index 384ceecd32f..04c597e7674 100644 --- a/libavcodec/wcmv.c +++ b/libavcodec/wcmv.c @@ -45,7 +45,7 @@ static int decode_frame(AVCodecContext *avctx, { WCMVContext *s = avctx->priv_data; AVFrame *frame = data; - int skip, blocks, zret, ret, intra = 0, bpp = s->bpp; + int skip, blocks, zret, ret, intra = 0, flags = 0, bpp = s->bpp; GetByteContext gb; uint8_t *dst; @@ -56,21 +56,13 @@ static int decode_frame(AVCodecContext *avctx, } bytestream2_init(&gb, avpkt->data, avpkt->size); + blocks = bytestream2_get_le16(&gb); + if (!blocks) + flags |= FF_REGET_BUFFER_FLAG_READONLY; - if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + if ((ret = ff_reget_buffer(avctx, s->prev_frame, flags)) < 0) return ret; - if (s->prev_frame->data[0]) { - ret = av_frame_copy(frame, s->prev_frame); - if (ret < 0) - return ret; - } else { - ptrdiff_t linesize[4] = { frame->linesize[0], 0, 0, 0 }; - av_image_fill_black(frame->data, linesize, avctx->pix_fmt, 0, - avctx->width, avctx->height); - } - - blocks = bytestream2_get_le16(&gb); if (blocks > 5) { GetByteContext bgb; int x = 0, size; @@ -113,6 +105,8 @@ static int decode_frame(AVCodecContext *avctx, bytestream2_skip(&bgb, 4); w = bytestream2_get_le16(&bgb); h = bytestream2_get_le16(&bgb); + if (x + bpp * (int64_t)w * h > INT_MAX) + return AVERROR_INVALIDDATA; x += bpp * w * h; } @@ -140,6 +134,8 @@ static int decode_frame(AVCodecContext *avctx, bytestream2_skip(&gb, 4); w = bytestream2_get_le16(&gb); h = bytestream2_get_le16(&gb); + if (x + bpp * (int64_t)w * h > INT_MAX) + return AVERROR_INVALIDDATA; x += bpp * w * h; } @@ -158,6 +154,15 @@ static int decode_frame(AVCodecContext *avctx, bytestream2_seek(&gb, 2, SEEK_SET); } + if (bytestream2_get_bytes_left(&gb) < 8LL * blocks) + return AVERROR_INVALIDDATA; + + if (!avctx->frame_number) { + ptrdiff_t linesize[4] = { s->prev_frame->linesize[0], 0, 0, 0 }; + av_image_fill_black(s->prev_frame->data, linesize, avctx->pix_fmt, 0, + avctx->width, avctx->height); + } + for (int block = 0; block < blocks; block++) { int x, y, w, h; @@ -175,7 +180,7 @@ static int decode_frame(AVCodecContext *avctx, if (w > avctx->width || h > avctx->height) return AVERROR_INVALIDDATA; - dst = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0] + x * bpp; + dst = s->prev_frame->data[0] + (avctx->height - y - 1) * s->prev_frame->linesize[0] + x * bpp; for (int i = 0; i < h; i++) { s->zstream.next_out = dst; s->zstream.avail_out = w * bpp; @@ -187,15 +192,14 @@ static int decode_frame(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } - dst -= frame->linesize[0]; + dst -= s->prev_frame->linesize[0]; } } - frame->key_frame = intra; - frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + s->prev_frame->key_frame = intra; + s->prev_frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - av_frame_unref(s->prev_frame); - if ((ret = av_frame_ref(s->prev_frame, frame)) < 0) + if ((ret = av_frame_ref(frame, s->prev_frame)) < 0) return ret; *got_frame = 1; @@ -245,7 +249,7 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -AVCodec ff_wcmv_decoder = { +const AVCodec ff_wcmv_decoder = { .name = "wcmv", .long_name = NULL_IF_CONFIG_SMALL("WinCAM Motion Video"), .type = AVMEDIA_TYPE_VIDEO,