diff mbox series

[FFmpeg-devel,v2] libavformat/mov: Fix memleaks when demuxing DV audio

Message ID 20200629215055.31965-1-andreas.rheinhardt@gmail.com
State Accepted
Headers show
Series [FFmpeg-devel,v2] libavformat/mov: Fix memleaks when demuxing DV audio
Related show

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Andreas Rheinhardt June 29, 2020, 9:50 p.m. UTC
The code for demuxing DV audio predates the introduction of refcounted
packets and when the latter was added, changes to the former were
forgotten. This meant that when avpriv_dv_produce_packet initialized the
packet containing the AVBufferRef, the AVBufferRef as well as the
underlying AVBuffer leaked; the actual packet data didn't leak: They
were directly freed, but not via their AVBuffer's free function.

https://samples.ffmpeg.org/ffmpeg-bugs/trac/ticket4671/dir1.tar.bz2
contains samples for this (enable_drefs needs to be enabled for them).

Moreover, errors in avpriv_dv_produce_packet were ignored; this has been
changed, too.

Furthermore, in the hypothetical scenario that the track has a palette,
this would leak, too, so reorder the code so that the palette code
appears after the DV audio code.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
---
I already sent this patch last September [1]; the only difference is
that I have updated the commit message in light of the fact that I have
now found a sample to actually test it (it works as intended). I intend
to apply it in two days unless there are objections.

[1]: https://patchwork.ffmpeg.org/project/ffmpeg/patch/20190916155502.17579-3-andreas.rheinhardt@gmail.com/

 libavformat/mov.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/mov.c b/libavformat/mov.c
index adc52de947..8be01dd66b 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -7898,6 +7898,19 @@  static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
             }
             return ret;
         }
+#if CONFIG_DV_DEMUXER
+        if (mov->dv_demux && sc->dv_audio_container) {
+            AVBufferRef *buf = pkt->buf;
+            ret = avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos);
+            pkt->buf = buf;
+            av_packet_unref(pkt);
+            if (ret < 0)
+                return ret;
+            ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
+            if (ret < 0)
+                return ret;
+        }
+#endif
         if (sc->has_palette) {
             uint8_t *pal;
 
@@ -7909,16 +7922,6 @@  static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
                 sc->has_palette = 0;
             }
         }
-#if CONFIG_DV_DEMUXER
-        if (mov->dv_demux && sc->dv_audio_container) {
-            avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos);
-            av_freep(&pkt->data);
-            pkt->size = 0;
-            ret = avpriv_dv_get_packet(mov->dv_demux, pkt);
-            if (ret < 0)
-                return ret;
-        }
-#endif
         if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !st->need_parsing && pkt->size > 4) {
             if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0)
                 st->need_parsing = AVSTREAM_PARSE_FULL;