From d5c58c2641349678c395d9fdd4c4be226d1a3452 Mon Sep 17 00:00:00 2001 From: Jiyong Min Date: Thu, 23 Jun 2016 08:29:31 +0900 Subject: [PATCH] [CVE patch] CVE patch in libav version 11.7 - asfenc: fix some possible integer overflows (CVE-2016-2326) - mov: Check the entries value when parsing dref boxes (CVE-2016-3062) Change-Id: I4a21091a20e10ee4b68f27ee4f5f5df6e419eca3 Signed-off-by: Jiyong Min --- libavformat/asfenc.c | 38 +++++++++++++++++++++++++++----------- libavformat/mov.c | 4 +++- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c index 79b44a7..4ae52bd 100644 --- a/libavformat/asfenc.c +++ b/libavformat/asfenc.c @@ -191,7 +191,7 @@ typedef struct { ASFStream streams[128]; ///< it's max number and it's not that big /* non streamed additonnal info */ uint64_t nb_packets; ///< how many packets are there in the file, invalid if broadcasting - int64_t duration; ///< in 100ns units + uint64_t duration; ///< in 100ns units /* packet filling */ unsigned char multi_payloads_present; int packet_size_left; @@ -359,7 +359,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, AVCodecContext *enc; int64_t header_offset, cur_pos, hpos; int bit_rate; - int64_t duration; + uint64_t play_duration, send_duration; ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL); @@ -369,7 +369,16 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, tags[3] = av_dict_get(s->metadata, "comment", NULL, 0); tags[4] = av_dict_get(s->metadata, "rating", NULL, 0); - duration = asf->duration + PREROLL_TIME * 10000; + if (asf->duration > UINT64_MAX / 10000 - PREROLL_TIME) { + av_log(s, AV_LOG_WARNING, "Duration %"PRIu64" too large\n", asf->duration); + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR(ERANGE); + send_duration = 0; + play_duration = 0; + } else { + send_duration = asf->duration * 10000; + play_duration = (asf->duration + PREROLL_TIME) * 10000; + } has_title = tags[0] || tags[1] || tags[2] || tags[3] || tags[4]; metadata_count = av_dict_count(s->metadata); @@ -400,8 +409,8 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, file_time = 0; avio_wl64(pb, unix_to_file_time(file_time)); avio_wl64(pb, asf->nb_packets); /* number of packets */ - avio_wl64(pb, duration); /* end time stamp (in 100ns units) */ - avio_wl64(pb, asf->duration); /* duration (in 100ns units) */ + avio_wl64(pb, play_duration); /* end time stamp (in 100ns units) */ + avio_wl64(pb, send->duration); /* duration (in 100ns units) */ avio_wl64(pb, PREROLL_TIME); /* start time stamp */ avio_wl32(pb, (asf->is_streamed || !pb->seekable) ? 3 : 2); /* ??? */ avio_wl32(pb, s->packet_size); /* packet size */ @@ -832,7 +841,6 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) ASFContext *asf = s->priv_data; AVIOContext *pb = s->pb; ASFStream *stream; - int64_t duration; AVCodecContext *codec; int64_t packet_st, pts; int start_sec, i; @@ -847,8 +855,9 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts; assert(pts != AV_NOPTS_VALUE); - duration = pts * 10000; - asf->duration = FFMAX(asf->duration, duration + pkt->duration * 10000); + if (pts > UINT64_MAX - pkt->duration) + return AVERROR(ERANGE); + asf->duration = FFMAX(asf->duration, pts + pkt->duration); packet_st = asf->nb_packets; put_frame(s, stream, s->streams[pkt->stream_index], @@ -856,8 +865,15 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) /* check index */ if ((!asf->is_streamed) && (flags & AV_PKT_FLAG_KEY)) { - start_sec = (int)(duration / INT64_C(10000000)); - if (start_sec != (int)(asf->last_indexed_pts / INT64_C(10000000))) { + if (pts / 1000LL > INT_MAX) + return AVERROR(ERANGE); + + start_sec = pts / 1000; + if (start_sec != asf->last_indexed_pts / 1000) { if (pts / 1000LL > INT_MAX) + return AVERROR(ERANGE); + + start_sec = pts / 1000; + if (start_sec != asf->last_indexed_pts / 1000) { for (i = asf->nb_index_count; i < start_sec; i++) { if (i >= asf->nb_index_memory_alloc) { int err; @@ -878,7 +894,7 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) (uint16_t)(asf->nb_packets - packet_st)); } asf->nb_index_count = start_sec; - asf->last_indexed_pts = duration; + asf->last_indexed_pts = pts; } } return 0; diff --git a/libavformat/mov.c b/libavformat/mov.c index 2c6ebb1..35105a8 100755 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -412,9 +412,11 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb32(pb); // version + flags entries = avio_rb32(pb); - if (entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 || + if (!entries || + entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 || entries >= UINT_MAX / sizeof(*sc->drefs)) return AVERROR_INVALIDDATA; + sc->drefs_count = 0; av_free(sc->drefs); sc->drefs = av_mallocz(entries * sizeof(*sc->drefs)); if (!sc->drefs) -- 2.7.4