[FFmpeg-trac] #11032(avformat:closed): Memory Leak in avformat_open_input

FFmpeg trac at avcodec.org
Thu Jun 6 12:26:23 EEST 2024


#11032: Memory Leak in avformat_open_input
--------------------------------------+------------------------------------
             Reporter:  safa karakus  |                    Owner:  (none)
                 Type:  defect        |                   Status:  closed
             Priority:  normal        |                Component:  avformat
              Version:  unspecified   |               Resolution:  invalid
             Keywords:                |               Blocked By:
             Blocking:                |  Reproduced by developer:  0
Analyzed by developer:  0             |
--------------------------------------+------------------------------------
Description changed by safa karakus:

Old description:

> A memory leak vulnerability has been identified in the FFmpeg library,
> specifically in the avformat_open_input function. This vulnerability can
> lead to the unintended exposure of sensitive data stored in memory. The
> issue arises due to improper handling and freeing of allocated memory
> within the avformat_open_input and related functions.
> {{{
> #include <stdint.h>
> #include <stddef.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include "libavformat/avformat.h"
> #include "libavcodec/avcodec.h"
> #include "libavutil/avutil.h"
> #include "libavutil/imgutils.h"
>
> void leak_memory_information(const char *filename) {
>     AVFormatContext *fmt_ctx = avformat_alloc_context();
>     if (!fmt_ctx) {
>         fprintf(stderr, "Could not allocate context\n");
>         return;
>     }
>
>     printf("Attempting to open file: %s\n", filename);
>
>     int ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL);
>     if (ret < 0) {
>         char err_buf[256];
>         av_strerror(ret, err_buf, sizeof(err_buf));
>         fprintf(stderr, "Could not open input file: %s. Error: %s\n",
> filename, err_buf);
>         avformat_free_context(fmt_ctx);
>         return;
>     }
>
>     if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
>         fprintf(stderr, "Could not find stream information\n");
>         avformat_close_input(&fmt_ctx);
>         avformat_free_context(fmt_ctx);
>         return;
>     }
>
>     // Stream bilgilerini al
>     for (unsigned int i = 0; i < fmt_ctx->nb_streams; i++) {
>         AVCodecParameters *codecpar = fmt_ctx->streams[i]->codecpar;
>         const AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
>         if (!codec) {
>             continue;
>         }
>
>         AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
>         if (!codec_ctx) {
>             continue;
>         }
>
>         if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {
>             avcodec_free_context(&codec_ctx);
>             continue;
>         }
>
>         if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
>             avcodec_free_context(&codec_ctx);
>             continue;
>         }
>
>         AVFrame *frame = av_frame_alloc();
>         AVPacket *packet = av_packet_alloc();
>         if (!frame || !packet) {
>             av_frame_free(&frame);
>             av_packet_free(&packet);
>             avcodec_free_context(&codec_ctx);
>             continue;
>         }
>
>         // Paketleri oku ve işleyerek bellek sızıntısını tetikle
>         while (av_read_frame(fmt_ctx, packet) >= 0) {
>             if (packet->stream_index == i) {
>                 int ret = avcodec_send_packet(codec_ctx, packet);
>                 if (ret < 0) {
>                     break;
>                 }
>
>                 ret = avcodec_receive_frame(codec_ctx, frame);
>                 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
>                     continue;
>                 } else if (ret < 0) {
>                     break;
>                 }
>
>                 // Bellek sızıntısına neden olacak işlemler
>                 for (int y = 0; y < frame->height; y++) {
>                     for (int x = 0; x < frame->width; x++) {
>                         int offset = y * frame->linesize[0] + x * 4; //
> Örnek olarak 4 byte per pixel (RGBA)
>                         if (offset < frame->linesize[0] * frame->height)
> {
>                             volatile uint8_t val =
> frame->data[0][offset];
>                             (void)val;
>                         }
>                     }
>                 }
>
>                 av_frame_unref(frame);
>             }
>             av_packet_unref(packet);
>         }
>
>         av_frame_free(&frame);
>         av_packet_free(&packet);
>         avcodec_free_context(&codec_ctx);
>     }
>
>     // Bellek içeriğini sızdırma
>     char *leaked_memory = (char *)malloc(100);
>     if (leaked_memory) {
>         snprintf(leaked_memory, 100, "Leaked memory content at %p: %s\n",
> fmt_ctx, (char *)fmt_ctx);
>         printf("%s", leaked_memory);
>         free(leaked_memory);
>     }
>
>     avformat_close_input(&fmt_ctx);
>     avformat_free_context(fmt_ctx); // Bu satır bellek sızıntısını
> önlemek için eklenebilir
> }
>
> int main(int argc, char *argv[]) {
>     if (argc != 2) {
>         fprintf(stderr, "Usage: %s <input file>\n", argv[0]);
>         return 1;
>     }
>
>     const char *filename = argv[1];
>
>     // Bellek ve bilgi sızıntısını tetiklemek için fonksiyonu çağır
>     leak_memory_information(filename);
>
>     return 0;
> }
>
> }}}
>
> {{{
> Attempting to open file: test.mp4
> Leaked memory content at 0x5ae0d4e34080: ��FH�|
> }}}
>
> {{{
> ==3878783==ERROR: LeakSanitizer: detected memory leaks
>
> Direct leak of 48 byte(s) in 2 object(s) allocated from:
>     #0 0x5e23f8521e07 in posix_memalign
> (/home/sazak/fuzz_project/ffmpeg-7.0/use_after_fuzz/memleak_test/memor_sanitize+0xa1e07)
> (BuildId: 07d05b4f8da1d513c1a0b32d7f7abdeaf6de5ecc)
>     #1 0x73665d2419e4 in av_malloc (/lib/x86_64-linux-
> gnu/libavutil.so.56+0x419e4) (BuildId:
> abc6b699a880017e212d717fb86a1c6ea0e022e8)
>
> Indirect leak of 9467 byte(s) in 4 object(s) allocated from:
>     #0 0x5e23f8521e07 in posix_memalign
> (/home/sazak/fuzz_project/ffmpeg-7.0/use_after_fuzz/memleak_test/memor_sanitize+0xa1e07)
> (BuildId: 07d05b4f8da1d513c1a0b32d7f7abdeaf6de5ecc)
>     #1 0x73665d2419e4 in av_malloc (/lib/x86_64-linux-
> gnu/libavutil.so.56+0x419e4) (BuildId:
> abc6b699a880017e212d717fb86a1c6ea0e022e8)
>
> SUMMARY: AddressSanitizer: 9515 byte(s) leaked in 6 allocation(s).
> }}}
> Patches should be submitted to the ffmpeg-devel mailing list and not this
> bug tracker.

New description:

 A memory leak has been identified in the FFmpeg library, specifically in
 the avformat_open_input function. This vulnerability can lead to the
 unintended exposure of sensitive data stored in memory. The issue arises
 due to improper handling and freeing of allocated memory within the
 avformat_open_input and related functions.
 {{{
 #include <stdint.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "libavformat/avformat.h"
 #include "libavcodec/avcodec.h"
 #include "libavutil/avutil.h"
 #include "libavutil/imgutils.h"

 void leak_memory_information(const char *filename) {
     AVFormatContext *fmt_ctx = avformat_alloc_context();
     if (!fmt_ctx) {
         fprintf(stderr, "Could not allocate context\n");
         return;
     }

     printf("Attempting to open file: %s\n", filename);

     int ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL);
     if (ret < 0) {
         char err_buf[256];
         av_strerror(ret, err_buf, sizeof(err_buf));
         fprintf(stderr, "Could not open input file: %s. Error: %s\n",
 filename, err_buf);
         avformat_free_context(fmt_ctx);
         return;
     }

     if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
         fprintf(stderr, "Could not find stream information\n");
         avformat_close_input(&fmt_ctx);
         avformat_free_context(fmt_ctx);
         return;
     }

     for (unsigned int i = 0; i < fmt_ctx->nb_streams; i++) {
         AVCodecParameters *codecpar = fmt_ctx->streams[i]->codecpar;
         const AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
         if (!codec) {
             continue;
         }

         AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
         if (!codec_ctx) {
             continue;
         }

         if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {
             avcodec_free_context(&codec_ctx);
             continue;
         }

         if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
             avcodec_free_context(&codec_ctx);
             continue;
         }

         AVFrame *frame = av_frame_alloc();
         AVPacket *packet = av_packet_alloc();
         if (!frame || !packet) {
             av_frame_free(&frame);
             av_packet_free(&packet);
             avcodec_free_context(&codec_ctx);
             continue;
         }

         while (av_read_frame(fmt_ctx, packet) >= 0) {
             if (packet->stream_index == i) {
                 ret = avcodec_send_packet(codec_ctx, packet);
                 if (ret < 0) {
                     break;
                 }

                 while (ret >= 0) {
                     ret = avcodec_receive_frame(codec_ctx, frame);
                     if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                         break;
                     } else if (ret < 0) {
                         break;
                     }

                     for (int y = 0; y < frame->height; y++) {
                         for (int x = 0; x < frame->width; x++) {
                             int offset = y * frame->linesize[0] + x * 4;
                             if (offset < frame->linesize[0] *
 frame->height) {
                                 volatile uint8_t val =
 frame->data[0][offset];
                                 (void)val;
                             }
                         }
                     }

                     av_frame_unref(frame);
                 }
                 av_packet_unref(packet);  // ^^
             }
         }

         av_frame_free(&frame);
         av_packet_free(&packet);
         avcodec_free_context(&codec_ctx);
     }


     char *leaked_memory = (char *)malloc(100);
     if (leaked_memory) {
         snprintf(leaked_memory, 100, "Leaked memory content at %p: %s\n",
 fmt_ctx, (char *)fmt_ctx);
         printf("%s", leaked_memory);
         free(leaked_memory);
     }

     avformat_close_input(&fmt_ctx);
     avformat_free_context(fmt_ctx); // you can add this line for memleak
 protection
 }

 int main(int argc, char *argv[]) {
     if (argc != 2) {
         fprintf(stderr, "Usage: %s <input file>\n", argv[0]);
         return 1;
     }

     const char *filename = argv[1];

     leak_memory_information(filename);

     return 0;
 }

 }

 }}}

 {{{
 Attempting to open file: test.mp4
 Leaked memory content at 0x5ae0d4e34080: ��FH�|
 }}}

 {{{
 ==3878783==ERROR: LeakSanitizer: detected memory leaks

 Direct leak of 48 byte(s) in 2 object(s) allocated from:
     #0 0x5e23f8521e07 in posix_memalign
 (/home/sazak/fuzz_project/ffmpeg-7.0/use_after_fuzz/memleak_test/memor_sanitize+0xa1e07)
 (BuildId: 07d05b4f8da1d513c1a0b32d7f7abdeaf6de5ecc)
     #1 0x73665d2419e4 in av_malloc (/lib/x86_64-linux-
 gnu/libavutil.so.56+0x419e4) (BuildId:
 abc6b699a880017e212d717fb86a1c6ea0e022e8)

 Indirect leak of 9467 byte(s) in 4 object(s) allocated from:
     #0 0x5e23f8521e07 in posix_memalign
 (/home/sazak/fuzz_project/ffmpeg-7.0/use_after_fuzz/memleak_test/memor_sanitize+0xa1e07)
 (BuildId: 07d05b4f8da1d513c1a0b32d7f7abdeaf6de5ecc)
     #1 0x73665d2419e4 in av_malloc (/lib/x86_64-linux-
 gnu/libavutil.so.56+0x419e4) (BuildId:
 abc6b699a880017e212d717fb86a1c6ea0e022e8)

 SUMMARY: AddressSanitizer: 9515 byte(s) leaked in 6 allocation(s).
 }}}
 Patches should be submitted to the ffmpeg-devel mailing list and not this
 bug tracker.

--
-- 
Ticket URL: <https://trac.ffmpeg.org/ticket/11032#comment:5>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list