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
This commit is contained in:
Luca Barbato 2015-01-05 10:40:41 +01:00
parent 8a3d9ca603
commit b3f0465736
1 changed files with 20 additions and 12 deletions

View File

@ -184,6 +184,13 @@ static void close_null_ctx(AVIOContext *pb)
av_free(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) static int seg_write_header(AVFormatContext *s)
{ {
SegmentContext *seg = s->priv_data; SegmentContext *seg = s->priv_data;
@ -265,12 +272,9 @@ static int seg_write_header(AVFormatContext *s)
} }
fail: fail:
if (ret) { if (ret < 0)
if (seg->list) seg_free_context(seg);
avio_close(seg->pb);
if (seg->avf)
avformat_free_context(seg->avf);
}
return ret; return ret;
} }
@ -282,6 +286,9 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
int64_t end_pts = seg->recording_time * seg->number; int64_t end_pts = seg->recording_time * seg->number;
int ret, can_split = 1; int ret, can_split = 1;
if (!oc)
return AVERROR(EINVAL);
if (seg->has_video) { if (seg->has_video) {
can_split = st->codec->codec_type == AVMEDIA_TYPE_VIDEO && can_split = st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
pkt->flags & AV_PKT_FLAG_KEY; 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); ret = ff_write_chained(oc, pkt->stream_index, pkt, s);
fail: fail:
if (ret < 0) { if (ret < 0)
if (seg->list) seg_free_context(seg);
avio_close(seg->pb);
avformat_free_context(oc);
}
return ret; return ret;
} }
@ -335,7 +339,11 @@ static int seg_write_trailer(struct AVFormatContext *s)
{ {
SegmentContext *seg = s->priv_data; SegmentContext *seg = s->priv_data;
AVFormatContext *oc = seg->avf; AVFormatContext *oc = seg->avf;
int ret; int ret = 0;
if (!oc)
goto fail;
if (!seg->write_header_trailer) { if (!seg->write_header_trailer) {
if ((ret = segment_end(oc, 0)) < 0) if ((ret = segment_end(oc, 0)) < 0)
goto fail; goto fail;