aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/segment.c
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2021-09-01 21:14:41 +0200
committerAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2021-09-03 19:23:18 +0200
commit2f710734c878b95eaeb9b84b0b5f367ab976c1bd (patch)
tree1afc1e28a86641c046e6a8e005a3fabeb4d08b46 /libavformat/segment.c
parentc0be596fc1647a2d6b731003adf3f64b9df0c5d2 (diff)
downloadffmpeg-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.c4
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++;
}