Commit 6eca20aa authored by Michael Niedermayer's avatar Michael Niedermayer

avformat/mov: check atom nesting depth

Fixes call stack overflow
Fixes: case1_call_stack_overflow.mp4
Found-by: 's avatarMichal Zalewski <lcamtuf@coredump.cx>
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
(cherry picked from commit caa7a391)

Conflicts:

	libavformat/isom.h
parent 7ef11e82
...@@ -171,6 +171,7 @@ typedef struct MOVContext { ...@@ -171,6 +171,7 @@ typedef struct MOVContext {
int *bitrates; ///< bitrates read before streams creation int *bitrates; ///< bitrates read before streams creation
int bitrates_count; int bitrates_count;
int moov_retry; int moov_retry;
int atom_depth;
} MOVContext; } MOVContext;
int ff_mp4_read_descr_len(AVIOContext *pb); int ff_mp4_read_descr_len(AVIOContext *pb);
......
...@@ -3151,6 +3151,12 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -3151,6 +3151,12 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
MOVAtom a; MOVAtom a;
int i; int i;
if (c->atom_depth > 10) {
av_log(c->fc, AV_LOG_ERROR, "Atoms too deeply nested\n");
return AVERROR_INVALIDDATA;
}
c->atom_depth ++;
if (atom.size < 0) if (atom.size < 0)
atom.size = INT64_MAX; atom.size = INT64_MAX;
while (total_size + 8 <= atom.size && !url_feof(pb)) { while (total_size + 8 <= atom.size && !url_feof(pb)) {
...@@ -3180,6 +3186,7 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -3180,6 +3186,7 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{ {
av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n"); av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n");
avio_skip(pb, -8); avio_skip(pb, -8);
c->atom_depth --;
return 0; return 0;
} }
} }
...@@ -3216,13 +3223,16 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -3216,13 +3223,16 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
int64_t start_pos = avio_tell(pb); int64_t start_pos = avio_tell(pb);
int64_t left; int64_t left;
int err = parse(c, pb, a); int err = parse(c, pb, a);
if (err < 0) if (err < 0) {
c->atom_depth --;
return err; return err;
}
if (c->found_moov && c->found_mdat && if (c->found_moov && c->found_mdat &&
((!pb->seekable || c->fc->flags & AVFMT_FLAG_IGNIDX) || ((!pb->seekable || c->fc->flags & AVFMT_FLAG_IGNIDX) ||
start_pos + a.size == avio_size(pb))) { start_pos + a.size == avio_size(pb))) {
if (!pb->seekable || c->fc->flags & AVFMT_FLAG_IGNIDX) if (!pb->seekable || c->fc->flags & AVFMT_FLAG_IGNIDX)
c->next_root_atom = start_pos + a.size; c->next_root_atom = start_pos + a.size;
c->atom_depth --;
return 0; return 0;
} }
left = a.size - avio_tell(pb) + start_pos; left = a.size - avio_tell(pb) + start_pos;
...@@ -3242,6 +3252,7 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -3242,6 +3252,7 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if (total_size < atom.size && atom.size < 0x7ffff) if (total_size < atom.size && atom.size < 0x7ffff)
avio_skip(pb, atom.size - total_size); avio_skip(pb, atom.size - total_size);
c->atom_depth --;
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment