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>
pull/90/head
Michael Niedermayer 10 years ago
parent 86e5749285
commit f1c21a200b
  1. 17
      libavformat/mvdec.c

@ -223,7 +223,7 @@ static int parse_video_var(AVFormatContext *avctx, AVStream *st,
return 0; return 0;
} }
static void read_table(AVFormatContext *avctx, AVStream *st, static int read_table(AVFormatContext *avctx, AVStream *st,
int (*parse)(AVFormatContext *avctx, AVStream *st, int (*parse)(AVFormatContext *avctx, AVStream *st,
const char *name, int size)) const char *name, int size))
{ {
@ -238,11 +238,16 @@ static void read_table(AVFormatContext *avctx, AVStream *st,
avio_read(pb, name, 16); avio_read(pb, name, 16);
name[sizeof(name) - 1] = 0; name[sizeof(name) - 1] = 0;
size = avio_rb32(pb); 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) { if (parse(avctx, st, name, size) < 0) {
avpriv_request_sample(avctx, "Variable %s", name); avpriv_request_sample(avctx, "Variable %s", name);
avio_skip(pb, size); avio_skip(pb, size);
} }
} }
return 0;
} }
static void read_index(AVIOContext *pb, AVStream *st) static void read_index(AVIOContext *pb, AVStream *st)
@ -268,6 +273,7 @@ static int mv_read_header(AVFormatContext *avctx)
AVIOContext *pb = avctx->pb; AVIOContext *pb = avctx->pb;
AVStream *ast = NULL, *vst = NULL; //initialization to suppress warning AVStream *ast = NULL, *vst = NULL; //initialization to suppress warning
int version, i; int version, i;
int ret;
avio_skip(pb, 4); avio_skip(pb, 4);
@ -340,7 +346,8 @@ static int mv_read_header(AVFormatContext *avctx)
} else if (!version && avio_rb16(pb) == 3) { } else if (!version && avio_rb16(pb) == 3) {
avio_skip(pb, 4); 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) { if (mv->nb_audio_tracks > 1) {
avpriv_request_sample(avctx, "Multiple audio streams support"); avpriv_request_sample(avctx, "Multiple audio streams support");
@ -350,7 +357,8 @@ static int mv_read_header(AVFormatContext *avctx)
if (!ast) if (!ast)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; 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 && if (mv->acompression == 100 &&
mv->aformat == AUDIO_FORMAT_SIGNED && mv->aformat == AUDIO_FORMAT_SIGNED &&
ast->codec->bits_per_coded_sample == 16) { ast->codec->bits_per_coded_sample == 16) {
@ -376,7 +384,8 @@ static int mv_read_header(AVFormatContext *avctx)
if (!vst) if (!vst)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; 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) if (mv->nb_audio_tracks)

Loading…
Cancel
Save