diff options
author | Luca Barbato <lu_zero@gentoo.org> | 2013-05-29 00:00:12 +0400 |
---|---|---|
committer | Luca Barbato <lu_zero@gentoo.org> | 2013-05-29 14:11:47 +0400 |
commit | c8f3cb9119c2183680d44a509a1b5a9817a3bee9 (patch) | |
tree | 1d359bfd511fb26d0b936c32d8f085e4f2d63346 /libavcodec/vmdav.c | |
parent | 91a6944e56236234f0a7ba162404665753cbcb51 (diff) |
vmd: return meaningful errors
CC: libav-stable@libav.org
Diffstat (limited to 'libavcodec/vmdav.c')
-rw-r--r-- | libavcodec/vmdav.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c index c9c3f4ead7..5e31f5597e 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdav.c @@ -191,7 +191,7 @@ static int rle_unpack(const unsigned char *src, unsigned char *dest, return bytestream2_tell(&gb); } -static void vmd_decode(VmdVideoContext *s, AVFrame *frame) +static int vmd_decode(VmdVideoContext *s, AVFrame *frame) { int i; unsigned int *palette32; @@ -215,13 +215,21 @@ static void vmd_decode(VmdVideoContext *s, AVFrame *frame) if (frame_x < 0 || frame_width < 0 || frame_x >= s->avctx->width || frame_width > s->avctx->width || - frame_x + frame_width > s->avctx->width) - return; + frame_x + frame_width > s->avctx->width) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid horizontal range %d-%d\n", + frame_x, frame_width); + return AVERROR_INVALIDDATA; + } if (frame_y < 0 || frame_height < 0 || frame_y >= s->avctx->height || frame_height > s->avctx->height || - frame_y + frame_height > s->avctx->height) - return; + frame_y + frame_height > s->avctx->height) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid vertical range %d-%d\n", + frame_x, frame_width); + return AVERROR_INVALIDDATA; + } if ((frame_width == s->avctx->width && frame_height == s->avctx->height) && (frame_x || frame_y)) { @@ -254,6 +262,9 @@ static void vmd_decode(VmdVideoContext *s, AVFrame *frame) b = bytestream2_get_byteu(&gb) * 4; palette32[i] = (r << 16) | (g << 8) | (b); } + } else { + av_log(s->avctx, AV_LOG_ERROR, "Incomplete palette\n"); + return AVERROR_INVALIDDATA; } s->size -= PALETTE_COUNT * 3 + 2; } @@ -261,7 +272,7 @@ static void vmd_decode(VmdVideoContext *s, AVFrame *frame) /* originally UnpackFrame in VAG's code */ bytestream2_init(&gb, gb.buffer, s->buf + s->size - gb.buffer); if (bytestream2_get_bytes_left(&gb) < 1) - return; + return AVERROR_INVALIDDATA; meth = bytestream2_get_byteu(&gb); if (meth & 0x80) { lz_unpack(gb.buffer, bytestream2_get_bytes_left(&gb), @@ -281,13 +292,13 @@ static void vmd_decode(VmdVideoContext *s, AVFrame *frame) if (len & 0x80) { len = (len & 0x7F) + 1; if (ofs + len > frame_width || bytestream2_get_bytes_left(&gb) < len) - return; + return AVERROR_INVALIDDATA; bytestream2_get_buffer(&gb, &dp[ofs], len); ofs += len; } else { /* interframe pixel copy */ if (ofs + len + 1 > frame_width || !s->prev_frame.data[0]) - return; + return AVERROR_INVALIDDATA; memcpy(&dp[ofs], &pp[ofs], len + 1); ofs += len + 1; } @@ -295,7 +306,7 @@ static void vmd_decode(VmdVideoContext *s, AVFrame *frame) if (ofs > frame_width) { av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n", ofs, frame_width); - break; + return AVERROR_INVALIDDATA; } dp += frame->linesize[0]; pp += s->prev_frame.linesize[0]; @@ -327,7 +338,7 @@ static void vmd_decode(VmdVideoContext *s, AVFrame *frame) } else { /* interframe pixel copy */ if (ofs + len + 1 > frame_width || !s->prev_frame.data[0]) - return; + return AVERROR_INVALIDDATA; memcpy(&dp[ofs], &pp[ofs], len + 1); ofs += len + 1; } @@ -335,6 +346,7 @@ static void vmd_decode(VmdVideoContext *s, AVFrame *frame) if (ofs > frame_width) { av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n", ofs, frame_width); + return AVERROR_INVALIDDATA; } dp += frame->linesize[0]; pp += s->prev_frame.linesize[0]; @@ -342,6 +354,7 @@ static void vmd_decode(VmdVideoContext *s, AVFrame *frame) break; } } + return 0; } static av_cold int vmdvideo_decode_init(AVCodecContext *avctx) @@ -397,14 +410,15 @@ static int vmdvideo_decode_frame(AVCodecContext *avctx, s->size = buf_size; if (buf_size < 16) - return buf_size; + return AVERROR_INVALIDDATA; if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n"); return ret; } - vmd_decode(s, frame); + if ((ret = vmd_decode(s, frame)) < 0) + return ret; /* make the palette available on the way out */ memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4); |