diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-12-22 14:04:42 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-12-22 14:04:49 +0100 |
commit | dd1fb6528791b32ac9d6b3c2d81707cf1949ec5d (patch) | |
tree | a36e7a71cb40b860ac8014119d5f2541d50db243 | |
parent | 834f80db22c186f3d0662754f6a00085c64c2323 (diff) | |
parent | cc1dda851b082826e652d698a9ca4738fc2a0ea5 (diff) | |
download | ffmpeg-dd1fb6528791b32ac9d6b3c2d81707cf1949ec5d.tar.gz |
Merge remote-tracking branch 'tjoppen/fuzz_fixes'
* tjoppen/fuzz_fixes:
mxfdec: Don't crash in mxf_packet_timestamps() if current_edit_unit overflows
mxfdec: Zero nb_ptses in mxf_compute_ptses_fake_index()
mxfdec: Sanity check PreviousPartition
mxfdec: Never seek back in local sets and KLVs
mxfdec: Move the current_partition check inside mxf_read_header()
mxfdec: Fix infinite loop in mxf_packet_timestamps()
mxfdec: Check url_feof() in mxf_read_local_tags()
mxfdec: Check for NULL component
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavformat/mxfdec.c | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index b6a63c90a2..47fa81d495 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -479,6 +479,13 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size partition->previous_partition, footer_partition, partition->index_sid, partition->body_sid); + /* sanity check PreviousPartition if set */ + if (partition->previous_partition && + mxf->run_in + partition->previous_partition >= klv_offset) { + av_log(mxf->fc, AV_LOG_ERROR, "PreviousPartition points to this partition or forward\n"); + return AVERROR_INVALIDDATA; + } + if (op[12] == 1 && op[13] == 1) mxf->op = OP1a; else if (op[12] == 1 && op[13] == 2) mxf->op = OP1b; else if (op[12] == 1 && op[13] == 3) mxf->op = OP1c; @@ -1021,8 +1028,10 @@ static int mxf_compute_ptses_fake_index(MXFContext *mxf, MXFIndexTable *index_ta for (i = 0; i < index_table->nb_segments; i++) { MXFIndexTableSegment *s = index_table->segments[i]; - if (!s->nb_index_entries) + if (!s->nb_index_entries) { + index_table->nb_ptses = 0; return 0; /* no TemporalOffsets */ + } index_table->nb_ptses += s->index_duration; } @@ -1276,7 +1285,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) break; } } - if (!source_track) + if (!source_track || !component) continue; if (!(source_track->sequence = mxf_resolve_strong_ref(mxf, &source_track->sequence_ref, Sequence))) { @@ -1437,7 +1446,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF if (!ctx) return -1; - while (avio_tell(pb) + 4 < klv_end) { + while (avio_tell(pb) + 4 < klv_end && !url_feof(pb)) { int tag = avio_rb16(pb); int size = avio_rb16(pb); /* KLV specified by 0x53 */ uint64_t next = avio_tell(pb) + size; @@ -1464,6 +1473,13 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF else if (read_child(ctx, pb, tag, size, uid, -1) < 0) return -1; + /* accept the 64k local set limit being exceeded (Avid) + * don't accept it extending past the end of the KLV though (zzuf5.mxf) */ + if (avio_tell(pb) > klv_end) { + av_log(mxf->fc, AV_LOG_ERROR, "local tag %#04x extends past end of local set @ %#"PRIx64"\n", + tag, klv->offset); + return AVERROR_INVALIDDATA; + } else if (avio_tell(pb) <= next) /* only seek forward, else this can loop for a long time */ avio_seek(pb, next, SEEK_SET); } if (ctx_size) ctx->type = type; @@ -1500,11 +1516,6 @@ static int mxf_parse_handle_essence(MXFContext *mxf) AVIOContext *pb = mxf->fc->pb; int64_t ret; - if (!mxf->current_partition) { - av_log(mxf->fc, AV_LOG_ERROR, "found essence prior to PartitionPack\n"); - return AVERROR_INVALIDDATA; - } - if (mxf->parsing_backward) { return mxf_seek_to_previous_partition(mxf); } else { @@ -1620,6 +1631,12 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) IS_KLV_KEY(klv.key, mxf_essence_element_key) || IS_KLV_KEY(klv.key, mxf_avid_essence_element_key) || IS_KLV_KEY(klv.key, mxf_system_item_key)) { + + if (!mxf->current_partition) { + av_log(mxf->fc, AV_LOG_ERROR, "found essence prior to first PartitionPack\n"); + return AVERROR_INVALIDDATA; + } + if (!mxf->current_partition->essence_offset) { /* for OP1a we compute essence_offset * for OPAtom we point essence_offset after the KL (usually op1a_essence_offset + 20 or 25) @@ -1666,6 +1683,14 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) } else { uint64_t next = avio_tell(s->pb) + klv.length; res = metadata->read(mxf, s->pb, 0, klv.length, klv.key, klv.offset); + + /* only seek forward, else this can loop for a long time */ + if (avio_tell(s->pb) > next) { + av_log(s, AV_LOG_ERROR, "read past end of KLV @ %#"PRIx64"\n", + klv.offset); + return AVERROR_INVALIDDATA; + } + avio_seek(s->pb, next, SEEK_SET); } if (res < 0) { @@ -1712,7 +1737,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) */ static void mxf_packet_timestamps(MXFContext *mxf, AVPacket *pkt) { - int64_t next_ofs; + int64_t last_ofs = -1, next_ofs; MXFIndexTable *t = &mxf->index_tables[0]; /* this is called from the OP1a demuxing logic, which means there may be no index tables */ @@ -1720,17 +1745,25 @@ static void mxf_packet_timestamps(MXFContext *mxf, AVPacket *pkt) return; /* find mxf->current_edit_unit so that the next edit unit starts ahead of pkt->pos */ - for (;;) { + while (mxf->current_edit_unit >= 0) { if (mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 1, NULL, &next_ofs, 0) < 0) break; + if (next_ofs <= last_ofs) { + /* large next_ofs didn't change or current_edit_unit wrapped around + * this fixes the infinite loop on zzuf3.mxf */ + av_log(mxf->fc, AV_LOG_ERROR, "next_ofs didn't change. not deriving packet timestamps\n"); + return; + } + if (next_ofs > pkt->pos) break; + last_ofs = next_ofs; mxf->current_edit_unit++; } - if (mxf->current_edit_unit >= t->nb_ptses) + if (mxf->current_edit_unit < 0 || mxf->current_edit_unit >= t->nb_ptses) return; pkt->dts = mxf->current_edit_unit + t->first_dts; |