[FFmpeg-trac] #8271(avcodec:new): A use-after-free bug in libavcodec/cuvid.c
FFmpeg
trac at avcodec.org
Mon Oct 14 05:25:58 EEST 2019
#8271: A use-after-free bug in libavcodec/cuvid.c
-----------------------------------+------------------------------------
Reporter: wurongxin | Type: defect
Status: new | Priority: critical
Component: avcodec | Version: 3.4.6
Keywords: | Blocked By:
Blocking: | Reproduced by developer: 0
Analyzed by developer: 0 |
-----------------------------------+------------------------------------
Summary of the bug:
How to reproduce:
{{{
% ffmpeg -i input ... output
ffmpeg version
built on ...
}}}
Patches should be submitted to the ffmpeg-devel mailing list and not this
bug tracker.
In the source file
https://github.com/FFmpeg/FFmpeg/blob/release/3.4/libavcodec/cuvid.c, in
the function "cuvid_output_frame", at Line 495, the variable
"pkt->buf->buffer" could be freed when calling to "cuvid_decode_packet".
At Line 496, the variable "pkt->buf->buffer" could be freed again when
calling to "av_packet_unref" (See the below code).
{{{
https://github.com/FFmpeg/FFmpeg/blob/release/3.4/libavcodec/cuvid.c
473. static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame)
474. {
...
495. ret = cuvid_decode_packet(avctx, &pkt);
496. av_packet_unref(&pkt);
}}}
To see how the function call to "cuvid_decode_packet" freed the variable
"pkt->buf->buffer", please read the following code snippet. In the
function "cuvid_decode_packet", at Line 403, it calls to the function
"av_packet_ref", where filter_packet.buf->buffer is assigned with
avpkt->buf->buffer (More details can be refered to the implementation of
av_package_ref as below). Note that, filter_packet.buf->buffer is a
shallow copy of avpkt->buf->buffer. At Line 410, it will call the function
"av_packet_unref", and free filter_packet.buf->buffer. Thus, the variable
"avpkt->buf->buffer" is also freed. Although filter_packet.buf->buffer is
assigned with null pointer when calling to av_packet_unref,
avpkt->buf->buffer is not assigned with null pointer. Then, the dangling
pointer avpkt->buf->buffer is returned back to its caller
"cuvid_output_frame".
{{{
https://github.com/FFmpeg/FFmpeg/blob/release/3.4/libavcodec/cuvid.c
383. static int cuvid_decode_packet(AVCodecContext *avctx, const AVPacket
*avpkt)
384. {
...
403. if ((ret = av_packet_ref(&filter_packet, avpkt)) < 0) {
404. av_log(avctx, AV_LOG_ERROR, "av_packet_ref failed\n");
405. return ret;
406. }
407.
408. if ((ret = av_bsf_send_packet(ctx->bsf, &filter_packet)) < 0)
{
409. av_log(avctx, AV_LOG_ERROR, "av_bsf_send_packet
failed\n");
410. av_packet_unref(&filter_packet);
411. return ret;
412. }
https://github.com/FFmpeg/FFmpeg/blob/release/3.4/libavcodec/avpacket.c
627. int av_packet_ref(AVPacket *dst, const AVPacket *src)
628. {
...
635. if (!src->buf) {
...
643. } else {
644. dst->buf = av_buffer_ref(src->buf);
...
650. }
https://github.com/FFmpeg/FFmpeg/blob/release/3.4/libavutil/buffer.c
93. AVBufferRef *av_buffer_ref(AVBufferRef *buf)
94. {
95. AVBufferRef *ret = av_mallocz(sizeof(*ret));
96.
97. if (!ret)
98. return NULL;
99.
100. *ret = *buf;
101.
102. atomic_fetch_add_explicit(&buf->buffer->refcount, 1,
memory_order_relaxed);
103.
104. return ret;
105.}
}}}
--
Ticket URL: <https://trac.ffmpeg.org/ticket/8271>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker
More information about the FFmpeg-trac
mailing list