Commit 3dabebc2 authored by Neil Birkbeck's avatar Neil Birkbeck Committed by Michael Niedermayer

libavformat/matroskaenc.c: fix small memory leaks on error

Fixing small leaks that can occur when mkv_write_tracks fails in mkv_write_header
(e.g., if video track has unknown codec). Also changing mkv_write_seekhead to take
the MatroskaMuxContext to avoid having dangling pointers.
Signed-off-by: 's avatarNeil Birkbeck <neil.birkbeck@gmail.com>
Signed-off-by: 's avatarMichael Niedermayer <michael@niedermayer.cc>
parent fa95965f
...@@ -308,6 +308,23 @@ static void put_xiph_size(AVIOContext *pb, int size) ...@@ -308,6 +308,23 @@ static void put_xiph_size(AVIOContext *pb, int size)
avio_w8(pb, size % 255); avio_w8(pb, size % 255);
} }
/**
* Free the members allocated in the mux context.
*/
static void mkv_free(MatroskaMuxContext *mkv) {
if (mkv->main_seekhead) {
av_freep(&mkv->main_seekhead->entries);
av_freep(&mkv->main_seekhead);
}
if (mkv->cues) {
av_freep(&mkv->cues->entries);
av_freep(&mkv->cues);
}
av_freep(&mkv->tracks);
av_freep(&mkv->stream_durations);
av_freep(&mkv->stream_duration_offsets);
}
/** /**
* Initialize a mkv_seekhead element to be ready to index level 1 Matroska * Initialize a mkv_seekhead element to be ready to index level 1 Matroska
* elements. If a maximum number of elements is specified, enough space * elements. If a maximum number of elements is specified, enough space
...@@ -368,8 +385,9 @@ static int mkv_add_seekhead_entry(mkv_seekhead *seekhead, unsigned int elementid ...@@ -368,8 +385,9 @@ static int mkv_add_seekhead_entry(mkv_seekhead *seekhead, unsigned int elementid
* @return The file offset where the seekhead was written, * @return The file offset where the seekhead was written,
* -1 if an error occurred. * -1 if an error occurred.
*/ */
static int64_t mkv_write_seekhead(AVIOContext *pb, mkv_seekhead *seekhead) static int64_t mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv)
{ {
mkv_seekhead *seekhead = mkv->main_seekhead;
ebml_master metaseek, seekentry; ebml_master metaseek, seekentry;
int64_t currentpos; int64_t currentpos;
int i; int i;
...@@ -406,8 +424,8 @@ static int64_t mkv_write_seekhead(AVIOContext *pb, mkv_seekhead *seekhead) ...@@ -406,8 +424,8 @@ static int64_t mkv_write_seekhead(AVIOContext *pb, mkv_seekhead *seekhead)
currentpos = seekhead->filepos; currentpos = seekhead->filepos;
} }
fail: fail:
av_freep(&seekhead->entries); av_freep(&mkv->main_seekhead->entries);
av_free(seekhead); av_freep(&mkv->main_seekhead);
return currentpos; return currentpos;
} }
...@@ -1397,9 +1415,10 @@ static int mkv_write_header(AVFormatContext *s) ...@@ -1397,9 +1415,10 @@ static int mkv_write_header(AVFormatContext *s)
} }
mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks)); mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks));
if (!mkv->tracks) if (!mkv->tracks) {
return AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
goto fail;
}
ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0); ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0);
put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1);
put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1);
...@@ -1419,11 +1438,13 @@ static int mkv_write_header(AVFormatContext *s) ...@@ -1419,11 +1438,13 @@ static int mkv_write_header(AVFormatContext *s)
// isn't more than 10 elements if we only write one of each other // isn't more than 10 elements if we only write one of each other
// currently defined level 1 element // currently defined level 1 element
mkv->main_seekhead = mkv_start_seekhead(pb, mkv->segment_offset, 10); mkv->main_seekhead = mkv_start_seekhead(pb, mkv->segment_offset, 10);
if (!mkv->main_seekhead) if (!mkv->main_seekhead) {
return AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
goto fail;
}
ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, avio_tell(pb)); ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, avio_tell(pb));
if (ret < 0) return ret; if (ret < 0) goto fail;
segment_info = start_ebml_master(pb, MATROSKA_ID_INFO, 0); segment_info = start_ebml_master(pb, MATROSKA_ID_INFO, 0);
put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
...@@ -1472,7 +1493,7 @@ static int mkv_write_header(AVFormatContext *s) ...@@ -1472,7 +1493,7 @@ static int mkv_write_header(AVFormatContext *s)
ret = mkv_write_tracks(s); ret = mkv_write_tracks(s);
if (ret < 0) if (ret < 0)
return ret; goto fail;
for (i = 0; i < s->nb_chapters; i++) for (i = 0; i < s->nb_chapters; i++)
mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - s->chapters[i]->id); mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - s->chapters[i]->id);
...@@ -1480,24 +1501,25 @@ static int mkv_write_header(AVFormatContext *s) ...@@ -1480,24 +1501,25 @@ static int mkv_write_header(AVFormatContext *s)
if (mkv->mode != MODE_WEBM) { if (mkv->mode != MODE_WEBM) {
ret = mkv_write_chapters(s); ret = mkv_write_chapters(s);
if (ret < 0) if (ret < 0)
return ret; goto fail;
ret = mkv_write_tags(s); ret = mkv_write_tags(s);
if (ret < 0) if (ret < 0)
return ret; goto fail;
ret = mkv_write_attachments(s); ret = mkv_write_attachments(s);
if (ret < 0) if (ret < 0)
return ret; goto fail;
} }
if (!s->pb->seekable && !mkv->is_live) if (!s->pb->seekable && !mkv->is_live)
mkv_write_seekhead(pb, mkv->main_seekhead); mkv_write_seekhead(pb, mkv);
mkv->cues = mkv_start_cues(mkv->segment_offset); mkv->cues = mkv_start_cues(mkv->segment_offset);
if (!mkv->cues) if (!mkv->cues) {
return AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
goto fail;
}
if (pb->seekable && mkv->reserve_cues_space) { if (pb->seekable && mkv->reserve_cues_space) {
mkv->cues_pos = avio_tell(pb); mkv->cues_pos = avio_tell(pb);
put_ebml_void(pb, mkv->reserve_cues_space); put_ebml_void(pb, mkv->reserve_cues_space);
...@@ -1524,6 +1546,9 @@ static int mkv_write_header(AVFormatContext *s) ...@@ -1524,6 +1546,9 @@ static int mkv_write_header(AVFormatContext *s)
} }
return 0; return 0;
fail:
mkv_free(mkv);
return ret;
} }
static int mkv_blockgroup_size(int pkt_size) static int mkv_blockgroup_size(int pkt_size)
...@@ -2015,7 +2040,7 @@ static int mkv_write_trailer(AVFormatContext *s) ...@@ -2015,7 +2040,7 @@ static int mkv_write_trailer(AVFormatContext *s)
return ret; return ret;
} }
mkv_write_seekhead(pb, mkv->main_seekhead); mkv_write_seekhead(pb, mkv);
// update the duration // update the duration
av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration);
...@@ -2052,12 +2077,8 @@ static int mkv_write_trailer(AVFormatContext *s) ...@@ -2052,12 +2077,8 @@ static int mkv_write_trailer(AVFormatContext *s)
if (!mkv->is_live) { if (!mkv->is_live) {
end_ebml_master(pb, mkv->segment); end_ebml_master(pb, mkv->segment);
} }
av_freep(&mkv->tracks);
av_freep(&mkv->cues->entries);
av_freep(&mkv->cues);
av_freep(&mkv->stream_durations);
av_freep(&mkv->stream_duration_offsets);
mkv_free(mkv);
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment