From b3f04657368a32a9903406395f865e230b1de348 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 5 Jan 2015 10:40:41 +0100 Subject: [PATCH] segment: Fix the failure paths A failure in segment_end() or segment_start() would lead to freeing a dangling pointer and in general further calls to seg_write_packet() or to seg_write_trailer() would have the same faulty behaviour. CC: libav-stable@libav.org Reported-By: luodalongde@gmail.com --- libavformat/segment.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/libavformat/segment.c b/libavformat/segment.c index 52da6b9ce3..bcfd1f9973 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -184,6 +184,13 @@ static void close_null_ctx(AVIOContext *pb) av_free(pb); } +static void seg_free_context(SegmentContext *seg) +{ + avio_closep(&seg->pb); + avformat_free_context(seg->avf); + seg->avf = NULL; +} + static int seg_write_header(AVFormatContext *s) { SegmentContext *seg = s->priv_data; @@ -265,12 +272,9 @@ static int seg_write_header(AVFormatContext *s) } fail: - if (ret) { - if (seg->list) - avio_close(seg->pb); - if (seg->avf) - avformat_free_context(seg->avf); - } + if (ret < 0) + seg_free_context(seg); + return ret; } @@ -282,6 +286,9 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) int64_t end_pts = seg->recording_time * seg->number; int ret, can_split = 1; + if (!oc) + return AVERROR(EINVAL); + if (seg->has_video) { can_split = st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pkt->flags & AV_PKT_FLAG_KEY; @@ -322,11 +329,8 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) ret = ff_write_chained(oc, pkt->stream_index, pkt, s); fail: - if (ret < 0) { - if (seg->list) - avio_close(seg->pb); - avformat_free_context(oc); - } + if (ret < 0) + seg_free_context(seg); return ret; } @@ -335,7 +339,11 @@ static int seg_write_trailer(struct AVFormatContext *s) { SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; - int ret; + int ret = 0; + + if (!oc) + goto fail; + if (!seg->write_header_trailer) { if ((ret = segment_end(oc, 0)) < 0) goto fail;