diff options
author | Paul B Mahol <onemda@gmail.com> | 2016-06-11 22:31:49 +0300 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2016-06-11 22:31:49 +0300 |
commit | 3ecc59bc35412d0cc2299668dd1f79fff090eb3f (patch) | |
tree | b58c4f903c50f523c26de93ce1168d343a45a077 /libavcodec/utvideodec.c | |
parent | 5d12cfacde01bf59cb876f4fb7c1e10a40f4527f (diff) |
avcodec/utvideodec: fix multiple slices for UQY2 and other issues
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavcodec/utvideodec.c')
-rw-r--r-- | libavcodec/utvideodec.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 5c6c318a01..4544b06272 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -494,28 +494,36 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, /* parse plane structure to get frame flags and validate slice offsets */ bytestream2_init(&gb, buf, buf_size); if (c->pro) { + if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) { + av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n"); + return AVERROR_INVALIDDATA; + } c->frame_info = bytestream2_get_le32u(&gb); - c->slices = ((c->frame_info >> 24) & 0xff) + 1; + c->slices = ((c->frame_info >> 16) & 0xff) + 1; for (i = 0; i < c->planes; i++) { - plane_size = 0; plane_start[i] = gb.buffer; if (bytestream2_get_bytes_left(&gb) < 1024 + 4 * c->slices) { av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n"); return AVERROR_INVALIDDATA; } + slice_start = 0; + slice_end = 0; for (j = 0; j < c->slices; j++) { - slice_size = bytestream2_get_le32u(&gb); + slice_end = bytestream2_get_le32u(&gb); + if (slice_end < 0 || slice_end < slice_start || + bytestream2_get_bytes_left(&gb) < slice_end) { + av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n"); + return AVERROR_INVALIDDATA; + } + slice_size = slice_end - slice_start; + slice_start = slice_end; max_slice_size = FFMAX(max_slice_size, slice_size); - plane_size += slice_size; } - bytestream2_skipu(&gb, 1024); + plane_size = slice_end; bytestream2_skipu(&gb, plane_size); + bytestream2_skipu(&gb, 1024); } plane_start[c->planes] = gb.buffer; - if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) { - av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n"); - return AVERROR_INVALIDDATA; - } } else { for (i = 0; i < c->planes; i++) { plane_start[i] = gb.buffer; @@ -684,6 +692,7 @@ static av_cold int decode_init(AVCodecContext *avctx) AV_RB32(avctx->extradata + 4)); c->interlaced = 0; c->pro = 1; + c->frame_info_size = 4; } else { av_log(avctx, AV_LOG_ERROR, "Insufficient extradata size %d, should be at least 16\n", |