avformat/mov: check atom nesting depth
Fixes call stack overflow
Fixes: case1_call_stack_overflow.mp4
Found-by: Michal Zalewski <lcamtuf@coredump.cx>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit caa7a3914f
)
Conflicts:
libavformat/isom.h
This commit is contained in:
@@ -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);
|
||||||
|
@@ -3172,6 +3172,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 && !avio_feof(pb)) {
|
while (total_size + 8 <= atom.size && !avio_feof(pb)) {
|
||||||
@@ -3201,6 +3207,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3237,13 +3244,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;
|
||||||
@@ -3263,6 +3273,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user