Andreas Rheinhardt: > Andreas Rheinhardt: >> Andreas Rheinhardt: >>> The earlier version of the webm_chunk muxer had several bugs: >>> >>> 1. If the first packet of an audio stream didn't have a PTS of zero, >>> then no chunk will be started before a packet is delivered to the >>> underlying Matroska/WebM muxer, i.e. the AVFormatContext used to write >>> these packets had a NULL as AVIOContext for output. This is behind the >>> crash in ticket #5752. >>> >>> 2. If an error happens during writing a packet, the underlyimg >>> Matroska/WebM muxer context is freed. This leads to a use-after-free >>> coupled with a double-free in webm_chunk_write_trailer (which supposes >>> that the underlying AVFormatContext is still valid). >>> >>> 3. Even when no error occurs at all, webm_chunk_write_trailer is still >>> buggy: After the underlying Matroska/WebM muxer has written its trailer, >>> ending the chunk implicitly flushes it again which is illegal at this >>> point. >>> >>> These bugs have been fixed. >>> >>> Fixes #5752. >>> >>> Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@gmail.com> >>> --- >>> libavformat/webm_chunk.c | 44 +++++++++++++++++++++------------------- >>> 1 file changed, 23 insertions(+), 21 deletions(-) >>> >>> diff --git a/libavformat/webm_chunk.c b/libavformat/webm_chunk.c >>> index 2c99753b5b..391fee721a 100644 >>> --- a/libavformat/webm_chunk.c >>> +++ b/libavformat/webm_chunk.c >>> @@ -168,7 +168,7 @@ static int chunk_start(AVFormatContext *s) >>> return 0; >>> } >>> >>> -static int chunk_end(AVFormatContext *s) >>> +static int chunk_end(AVFormatContext *s, int flush) >>> { >>> WebMChunkContext *wc = s->priv_data; >>> AVFormatContext *oc = wc->avf; >>> @@ -179,11 +179,14 @@ static int chunk_end(AVFormatContext *s) >>> char filename[MAX_FILENAME_SIZE]; >>> AVDictionary *options = NULL; >>> >>> - if (wc->chunk_start_index == wc->chunk_index) >>> + if (!oc->pb) >>> return 0; >>> - // Flush the cluster in WebM muxer. >>> - oc->oformat->write_packet(oc, NULL); >>> + >>> + if (flush) >>> + // Flush the cluster in WebM muxer. >>> + oc->oformat->write_packet(oc, NULL); >>> buffer_size = avio_close_dyn_buf(oc->pb, &buffer); >>> + oc->pb = NULL; >>> ret = get_chunk_filename(s, 0, filename); >>> if (ret < 0) >>> goto fail; >>> @@ -194,7 +197,6 @@ static int chunk_end(AVFormatContext *s) >>> goto fail; >>> avio_write(pb, buffer, buffer_size); >>> ff_format_io_close(s, &pb); >>> - oc->pb = NULL; >>> fail: >>> av_dict_free(&options); >>> av_free(buffer); >>> @@ -216,27 +218,19 @@ static int webm_chunk_write_packet(AVFormatContext >>> *s, AVPacket *pkt) >>> } >>> >>> // For video, a new chunk is started only on key frames. For audio, a >>> new >>> - // chunk is started based on chunk_duration. >>> - if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && >>> + // chunk is started based on chunk_duration. Also, a new chunk is >>> started >>> + // unconditionally if there is no currently open chunk. >>> + if (!oc->pb || (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && >>> (pkt->flags & AV_PKT_FLAG_KEY)) || >>> (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && >>> - (pkt->pts == 0 || wc->duration_written >= wc->chunk_duration))) { >>> + wc->duration_written >= wc->chunk_duration)) { >>> wc->duration_written = 0; >>> - if ((ret = chunk_end(s)) < 0 || (ret = chunk_start(s)) < 0) { >>> - goto fail; >>> + if ((ret = chunk_end(s, 1)) < 0 || (ret = chunk_start(s)) < 0) { >>> + return ret; >>> } >>> } >>> >>> ret = oc->oformat->write_packet(oc, pkt); >>> - if (ret < 0) >>> - goto fail; >>> - >>> -fail: >>> - if (ret < 0) { >>> - oc->streams = NULL; >>> - oc->nb_streams = 0; >>> - avformat_free_context(oc); >>> - } >>> >>> return ret; >>> } >>> @@ -245,12 +239,20 @@ static int webm_chunk_write_trailer(AVFormatContext >>> *s) >>> { >>> WebMChunkContext *wc = s->priv_data; >>> AVFormatContext *oc = wc->avf; >>> + int ret; >>> + >>> + if (!oc->pb) { >>> + ret = chunk_start(s); >>> + if (ret < 0) >>> + goto fail; >>> + } >>> oc->oformat->write_trailer(oc); >>> - chunk_end(s); >>> + ret = chunk_end(s, 0); >>> +fail: >>> oc->streams = NULL; >>> oc->nb_streams = 0; >>> avformat_free_context(oc); >>> - return 0; >>> + return ret; >>> } >>> >>> #define OFFSET(x) offsetof(WebMChunkContext, x) >>> >>> >> Ping for the last two patches of this patchset (i.e. this one and >> https://ffmpeg.org/pipermail/ffmpeg-devel/2019-April/242902.html) >> >> - Andreas >> > And another ping for these two patches. > > - Andreas >
Ping #3. - Andreas _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".