diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2014-10-28 16:59:50 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-10-28 17:51:14 +0100 |
commit | f1c21a200bcbc9bbd54fc336016ac16c2e015012 (patch) | |
tree | 864fc4c7475566a47b226d6078011badd0f14e86 | |
parent | 86e574928536ee5249d9cf4da9f5d8714611d706 (diff) | |
download | ffmpeg-f1c21a200bcbc9bbd54fc336016ac16c2e015012.tar.gz |
avformat/mvdec: Check size in read_table() for validity
This check is redundant with the previous commit but it provides
better error messages and feedback while the previous commit
ensures that var_read_string() doesnt return uninitialized arrays
if it itself is feeded with an invalid size possibly through a
different future codepath.
Fixes: asan_heap-oob_49b1e5_12_011.movie
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavformat/mvdec.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index 0f09498b2b..c8a5ebf119 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -223,7 +223,7 @@ static int parse_video_var(AVFormatContext *avctx, AVStream *st, return 0; } -static void read_table(AVFormatContext *avctx, AVStream *st, +static int read_table(AVFormatContext *avctx, AVStream *st, int (*parse)(AVFormatContext *avctx, AVStream *st, const char *name, int size)) { @@ -238,11 +238,16 @@ static void read_table(AVFormatContext *avctx, AVStream *st, avio_read(pb, name, 16); name[sizeof(name) - 1] = 0; size = avio_rb32(pb); + if (size < 0) { + av_log(avctx, AV_LOG_ERROR, "entry size %d is invalid\n", size); + return AVERROR_INVALIDDATA; + } if (parse(avctx, st, name, size) < 0) { avpriv_request_sample(avctx, "Variable %s", name); avio_skip(pb, size); } } + return 0; } static void read_index(AVIOContext *pb, AVStream *st) @@ -268,6 +273,7 @@ static int mv_read_header(AVFormatContext *avctx) AVIOContext *pb = avctx->pb; AVStream *ast = NULL, *vst = NULL; //initialization to suppress warning int version, i; + int ret; avio_skip(pb, 4); @@ -340,7 +346,8 @@ static int mv_read_header(AVFormatContext *avctx) } else if (!version && avio_rb16(pb) == 3) { avio_skip(pb, 4); - read_table(avctx, NULL, parse_global_var); + if ((ret = read_table(avctx, NULL, parse_global_var)) < 0) + return ret; if (mv->nb_audio_tracks > 1) { avpriv_request_sample(avctx, "Multiple audio streams support"); @@ -350,7 +357,8 @@ static int mv_read_header(AVFormatContext *avctx) if (!ast) return AVERROR(ENOMEM); ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; - read_table(avctx, ast, parse_audio_var); + if ((read_table(avctx, ast, parse_audio_var)) < 0) + return ret; if (mv->acompression == 100 && mv->aformat == AUDIO_FORMAT_SIGNED && ast->codec->bits_per_coded_sample == 16) { @@ -376,7 +384,8 @@ static int mv_read_header(AVFormatContext *avctx) if (!vst) return AVERROR(ENOMEM); vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - read_table(avctx, vst, parse_video_var); + if ((ret = read_table(avctx, vst, parse_video_var))<0) + return ret; } if (mv->nb_audio_tracks) |