aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2014-12-16 21:14:40 +0100
committerMichael Niedermayer <michaelni@gmx.at>2014-12-21 04:40:35 +0100
commit2c5898c1d303093adccb0e9b117c435ca878735f (patch)
treef077228456a7a96f323ed9e27e217526c816683d /libavformat
parentb9d2c2e9870142e8255d93fa6a004d012b4caa42 (diff)
downloadffmpeg-2c5898c1d303093adccb0e9b117c435ca878735f.tar.gz
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 caa7a3914f499f74b3ee346f26d598ebdc0ec210) Conflicts: libavformat/isom.h
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/isom.h1
-rw-r--r--libavformat/mov.c13
2 files changed, 13 insertions, 1 deletions
diff --git a/libavformat/isom.h b/libavformat/isom.h
index 0360c53f11..83fb91851c 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -161,6 +161,7 @@ typedef struct MOVContext {
int use_absolute_path;
int ignore_editlist;
int64_t next_root_atom; ///< offset of the next root atom
+ int atom_depth;
} MOVContext;
int ff_mp4_read_descr_len(AVIOContext *pb);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 888d2ac588..081305b34f 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2806,6 +2806,12 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
MOVAtom a;
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)
atom.size = INT64_MAX;
while (total_size + 8 <= atom.size && !url_feof(pb)) {
@@ -2822,6 +2828,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");
avio_skip(pb, -8);
+ c->atom_depth --;
return 0;
}
}
@@ -2858,13 +2865,16 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
int64_t start_pos = avio_tell(pb);
int64_t left;
int err = parse(c, pb, a);
- if (err < 0)
+ if (err < 0) {
+ c->atom_depth --;
return err;
+ }
if (c->found_moov && c->found_mdat &&
((!pb->seekable || c->fc->flags & AVFMT_FLAG_IGNIDX) ||
start_pos + a.size == avio_size(pb))) {
if (!pb->seekable || c->fc->flags & AVFMT_FLAG_IGNIDX)
c->next_root_atom = start_pos + a.size;
+ c->atom_depth --;
return 0;
}
left = a.size - avio_tell(pb) + start_pos;
@@ -2884,6 +2894,7 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if (total_size < atom.size && atom.size < 0x7ffff)
avio_skip(pb, atom.size - total_size);
+ c->atom_depth --;
return 0;
}