diff options
author | Andreas Rheinhardt <andreas.rheinhardt@outlook.com> | 2021-09-01 21:14:41 +0200 |
---|---|---|
committer | Andreas Rheinhardt <andreas.rheinhardt@outlook.com> | 2021-09-03 19:23:18 +0200 |
commit | 2f710734c878b95eaeb9b84b0b5f367ab976c1bd (patch) | |
tree | 1afc1e28a86641c046e6a8e005a3fabeb4d08b46 /libavformat/segment.c | |
parent | c0be596fc1647a2d6b731003adf3f64b9df0c5d2 (diff) | |
download | ffmpeg-2f710734c878b95eaeb9b84b0b5f367ab976c1bd.tar.gz |
avformat/mux: Fix double-free when using AVPacket.opaque_ref
Up until now, ff_write_chained() copied the packet (manually, not with
av_packet_move_ref()) from a packet given to it to a stack packet whose
timing and stream_index is then modified before being sent to another
muxer via av_(interleaved_)write_frame(). Afterwards it is intended to
sync the fields of the packet relevant to freeing again; yet this only
encompasses buf, side_data and side_data_elems and not the newly added
opaque_ref. The other fields are not synced so that the returned packet
can have a size > 0 and data != NULL despite its buf being NULL (this
always happens in the interleaved codepath; before commit
fe251f77c80b0512ab8907902e1dbed3f4fe1aad it could also happen in the
noninterleaved one). This leads to double-frees if the interleaved
codepath is used and opaque_ref is set.
This commit therefore changes this by directly reusing the packet
instead of a spare packet. Given that av_write_frame() does not
change the packet given to it, one only needs to restore the timing
information to return it as it was; for the interleaved codepath
it is not possible to do likewise*, because av_interleaved_write_frame()
takes ownership of the packets given to it and returns blank packets.
But precisely because of this users of the interleaved codepath
have no legitimate expectation that their packet will be returned
unchanged. In line with av_interleaved_write_frame() ff_write_chained()
therefore returns blank packets when using the interleaved codepath.
Making the only user of said codepath compatible with this was trivial.
*: Unless one wanted to create a full new reference.
Reviewed-by: Lynne <dev@lynne.ee>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Diffstat (limited to 'libavformat/segment.c')
-rw-r--r-- | libavformat/segment.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/libavformat/segment.c b/libavformat/segment.c index ed671353d0..7c171b6fa4 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -952,7 +952,9 @@ calc_times: seg->initial_offset || seg->reset_timestamps || seg->avf->oformat->interleave_packet); fail: - if (pkt->stream_index == seg->reference_stream_index) { + /* Use st->index here as the packet returned from ff_write_chained() + * is blank if interleaving has been used. */ + if (st->index == seg->reference_stream_index) { seg->frame_count++; seg->segment_frame_count++; } |