Opened 11 months ago

Closed 9 months ago

#11640 closed defect (fixed)

Specific combination of timeclamp, fps, and count on showcqt causing crash

Reported by: Aseer Tayeem Owned by:
Priority: critical Component: avfilter
Version: 7.1 Keywords:
Cc: Blocked By:
Blocking: Reproduced by developer: yes
Analyzed by developer: no

Description

Summary of the bug:
This bug in showcqt of libavfilter causes a whole array of different memory errors causing crashes. I don't know how important this is, since a memory error could do anything, so I put it as critical. This is using valid inputs to showcqt.

How to reproduce:

% ffmpeg -f lavfi -i "amovie=test.mp3, showcqt=timeclamp=0.01:fps=15:count=5 [out0]" out.mp4
ffmpeg version n7.1.1
  built with gcc 15.1.1 (GCC) 20250425

% ffplay -f lavfi "amovie=test.mp3, showcqt=timeclamp=0.01:fps=15:count=5 [out0]"
ffplay version n7.1.1
  built with gcc 15.1.1 (GCC) 20250425

I had some complex filtergraph, until I reduced it to this. Removing any of these three will prevent the crash. Works with any input audio, but I don't know if this changes the behavior.

Some other quirks:

  • Keeping fixed timeclamp=0.01 and count=5. At fps=1-16, it crashes with SIGSEGV. At fps=17, it doesn't crash until you terminate it, then it instead has SIGABRT with an error in free(). At fps=18, it doesn't crash.
    # at fps=17
    free(): invalid next size (normal)
    fish: Job 1, 'ffmpeg -f lavfi -i "amovie=test…' terminated by signal SIGABRT (Abort)
    
  • Keeping fixed fps=15 and count=5. timeclamp=0.002 causes a SIGSEGV only when terminating the program. timeclamp=0.003-0.011 causes an immediate SIGSEGV. timeclamp=0.012 does nothing.
  • Keeping fixed fps=15 and timeclamp=0.01. count=1-5 causes immediate crashes. count=6 does nothing.
  • Overall, these ranges start at the minimum values allowed (fps=1, timeclamp=0.002, count=1), and end at fps=18, timeclamp=0.012, count=6. I didn't try using more precision.
  • Sometimes it would say something about a corrupted double-linked list, but only in ffplay.
  • With some inputs I saw a malloc assertion failure, but only in ffplay
    Fatal glibc error: malloc.c:4434 (_int_malloc): assertion failed: (unsigned long) (size) >= (unsigned long) (nb)
    
  • In ffplay at fps=17, I got an error like this:
    double free or corruption (!prev)  0KB vq=   11KB sq=    0B
    

Change History (6)

comment:1 by Aseer Tayeem, 11 months ago

Here's a valgrind output:

$ valgrind ./ffmpeg_g -f lavfi -i "amovie=test.mp3, showcqt=timeclamp=0.01:fps=15:count=5 [out0]" out.mp4
==155534== Memcheck, a memory error detector
==155534== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==155534== Using Valgrind-3.25.1 and LibVEX; rerun with -h for copyright info
==155534== Command: ./ffmpeg_g -f lavfi -i amovie=test.mp3,\ showcqt=timeclamp=0.01:fps=15:count=5\ [out0] out.mp4
==155534== 
ffmpeg version N-120002-gb1172b8cc6 Copyright (c) 2000-2025 the FFmpeg developers
  built with gcc 15.1.1 (GCC) 20250425
  configuration: 
  libavutil      60.  3.100 / 60.  3.100
  libavcodec     62.  3.101 / 62.  3.101
  libavformat    62.  1.100 / 62.  1.100
  libavdevice    62.  0.100 / 62.  0.100
  libavfilter    11.  0.100 / 11.  0.100
  libswscale      9.  0.100 /  9.  0.100
  libswresample   6.  0.100 /  6.  0.100
==155534== Invalid write of size 4
==155534==    at 0x4209CEC: filter_frame (avf_showcqt.c:1548)
==155534==    by 0x4209F5C: activate (avf_showcqt.c:1577)
==155534==    by 0x4220538: ff_filter_activate (avfilter.c:1433)
==155534==    by 0x4224515: get_frame_internal (buffersink.c:133)
==155534==    by 0x41F733A: lavfi_read_packet (lavfi.c:394)
==155534==    by 0x44EFCE3: ff_read_packet (demux.c:649)
==155534==    by 0x44EFE41: read_frame_internal (demux.c:1346)
==155534==    by 0x44F1E9F: avformat_find_stream_info (demux.c:2692)
==155534==    by 0x41C38A6: ifile_open (ffmpeg_demux.c:1814)
==155534==    by 0x41D8EAB: open_files (ffmpeg_opt.c:1366)
==155534==    by 0x41DBEE9: ffmpeg_parse_options (ffmpeg_opt.c:1415)
==155534==    by 0x41BA6A2: main (ffmpeg.c:991)
==155534==  Address 0x7dfc4c0 is 0 bytes after a block of size 2,048 alloc'd
==155534==    at 0x76F9AD9: posix_memalign (vg_replace_malloc.c:2226)
==155534==    by 0x5218846: av_malloc (mem.c:107)
==155534==    by 0x5237F14: ff_tx_gen_ptwo_revtab (tx.c:140)
==155534==    by 0x41B5EB1: ff_tx_init_subtx (tx.c:853)
==155534==    by 0x41B82BF: ff_tx_fft_init_float_c (tx_template.c:749)
==155534==    by 0x41B5EB1: ff_tx_init_subtx (tx.c:853)
==155534==    by 0x41B6126: av_tx_init (tx.c:926)
==155534==    by 0x420A86B: config_output (avf_showcqt.c:1380)
==155534==    by 0x421E789: ff_filter_config_links (avfilter.c:384)
==155534==    by 0x422373B: graph_config_links (avfiltergraph.c:255)
==155534==    by 0x422373B: avfilter_graph_config (avfiltergraph.c:1303)
==155534==    by 0x4122284: lavfi_read_header (lavfi.c:282)
==155534==    by 0x44EF5FB: avformat_open_input (demux.c:309)
==155534== 
==155534== Invalid write of size 4
==155534==    at 0x4209CF6: filter_frame (avf_showcqt.c:1549)
==155534==    by 0x4209F5C: activate (avf_showcqt.c:1577)
==155534==    by 0x4220538: ff_filter_activate (avfilter.c:1433)
==155534==    by 0x4224515: get_frame_internal (buffersink.c:133)
==155534==    by 0x41F733A: lavfi_read_packet (lavfi.c:394)
==155534==    by 0x44EFCE3: ff_read_packet (demux.c:649)
==155534==    by 0x44EFE41: read_frame_internal (demux.c:1346)
==155534==    by 0x44F1E9F: avformat_find_stream_info (demux.c:2692)
==155534==    by 0x41C38A6: ifile_open (ffmpeg_demux.c:1814)
==155534==    by 0x41D8EAB: open_files (ffmpeg_opt.c:1366)
==155534==    by 0x41DBEE9: ffmpeg_parse_options (ffmpeg_opt.c:1415)
==155534==    by 0x41BA6A2: main (ffmpeg.c:991)
==155534==  Address 0x7dfc4c4 is 4 bytes after a block of size 2,048 alloc'd
==155534==    at 0x76F9AD9: posix_memalign (vg_replace_malloc.c:2226)
==155534==    by 0x5218846: av_malloc (mem.c:107)
==155534==    by 0x5237F14: ff_tx_gen_ptwo_revtab (tx.c:140)
==155534==    by 0x41B5EB1: ff_tx_init_subtx (tx.c:853)
==155534==    by 0x41B82BF: ff_tx_fft_init_float_c (tx_template.c:749)
==155534==    by 0x41B5EB1: ff_tx_init_subtx (tx.c:853)
==155534==    by 0x41B6126: av_tx_init (tx.c:926)
==155534==    by 0x420A86B: config_output (avf_showcqt.c:1380)
==155534==    by 0x421E789: ff_filter_config_links (avfilter.c:384)
==155534==    by 0x422373B: graph_config_links (avfiltergraph.c:255)
==155534==    by 0x422373B: avfilter_graph_config (avfiltergraph.c:1303)
==155534==    by 0x4122284: lavfi_read_header (lavfi.c:282)
==155534==    by 0x44EF5FB: avformat_open_input (demux.c:309)
==155534== 
Input #0, lavfi, from 'amovie=test.mp3, showcqt=timeclamp=0.01:fps=15:count=5 [out0]':
  Duration: N/A, start: 0.000000, bitrate: N/A
  Stream #0:0: Video: wrapped_avframe, yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 15 fps, 15 tbr, 15 tbn
Stream mapping:
  Stream #0:0 -> #0:0 (wrapped_avframe (native) -> mpeg4 (native))
Press [q] to stop, [?] for help
Output #0, mp4, to 'out.mp4':
  Metadata:
    encoder         : Lavf62.1.100
  Stream #0:0: Video: mpeg4 (mp4v / 0x7634706D), yuv420p(tv, progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 15 fps, 15360 tbn
    Metadata:
      encoder         : Lavc62.3.101 mpeg4
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: N/A
==155534== Thread 8 dmx0:lavfi:       0KiB time=00:00:00.33 bitrate=   1.1kbits/s speed=0.0467x elapsed=0:00:07.14    
==155534== Invalid read of size 8
==155534==    at 0x524F924: ff_tx_fft_float_c (tx_template.c:783)
==155534==    by 0x4208B3E: plot_cqt.isra.0 (avf_showcqt.c:1154)
==155534==    by 0x4209B91: filter_frame (avf_showcqt.c:1522)
==155534==    by 0x4209F5C: activate (avf_showcqt.c:1577)
==155534==    by 0x4220538: ff_filter_activate (avfilter.c:1433)
==155534==    by 0x4224515: get_frame_internal (buffersink.c:133)
==155534==    by 0x41F733A: lavfi_read_packet (lavfi.c:394)
==155534==    by 0x44EFCE3: ff_read_packet (demux.c:649)
==155534==    by 0x44EFE41: read_frame_internal (demux.c:1346)
==155534==    by 0x44F0B64: av_read_frame (demux.c:1539)
==155534==    by 0x41BF3B5: input_thread (ffmpeg_demux.c:740)
==155534==    by 0x41DD994: task_wrapper (ffmpeg_sched.c:2534)
==155534==  Address 0x1c8fc55e8 is not stack'd, malloc'd or (recently) free'd
==155534== 
==155534== 
==155534== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==155534==  Access not within mapped region at address 0x1C8FC55E8
==155534==    at 0x524F924: ff_tx_fft_float_c (tx_template.c:783)
==155534==    by 0x4208B3E: plot_cqt.isra.0 (avf_showcqt.c:1154)
==155534==    by 0x4209B91: filter_frame (avf_showcqt.c:1522)
==155534==    by 0x4209F5C: activate (avf_showcqt.c:1577)
==155534==    by 0x4220538: ff_filter_activate (avfilter.c:1433)
==155534==    by 0x4224515: get_frame_internal (buffersink.c:133)
==155534==    by 0x41F733A: lavfi_read_packet (lavfi.c:394)
==155534==    by 0x44EFCE3: ff_read_packet (demux.c:649)
==155534==    by 0x44EFE41: read_frame_internal (demux.c:1346)
==155534==    by 0x44F0B64: av_read_frame (demux.c:1539)
==155534==    by 0x41BF3B5: input_thread (ffmpeg_demux.c:740)
==155534==    by 0x41DD994: task_wrapper (ffmpeg_sched.c:2534)
==155534==  If you believe this happened as a result of a stack
==155534==  overflow in your program's main thread (unlikely but
==155534==  possible), you can try to increase the size of the
==155534==  main thread stack using the --main-stacksize= flag.
==155534==  The main thread stack size used in this run was 8388608.
==155534== 
==155534== HEAP SUMMARY:
==155534==     in use at exit: 139,270,492 bytes in 2,885 blocks
==155534==   total heap usage: 6,192 allocs, 3,307 frees, 140,807,500 bytes allocated
==155534== 
==155534== LEAK SUMMARY:
==155534==    definitely lost: 0 bytes in 0 blocks
==155534==    indirectly lost: 0 bytes in 0 blocks
==155534==      possibly lost: 79,597,165 bytes in 491 blocks
==155534==    still reachable: 59,673,327 bytes in 2,394 blocks
==155534==         suppressed: 0 bytes in 0 blocks
==155534== Rerun with --leak-check=full to see details of leaked memory
==155534== 
==155534== For lists of detected and suppressed errors, rerun with: -s
==155534== ERROR SUMMARY: 7921 errors from 3 contexts (suppressed: 0 from 0)
fish: Job 1, 'valgrind ./ffmpeg_g -f lavfi -i…' terminated by signal SIGSEGV (Address boundary error)

comment:2 by Kiran, 11 months ago

Something seems to have happened in the current git master, I was able to reproduce the initial crash with my system FFmpeg 7.1.1 but when testing with a fresh build from git master using the same command it doesn't segfault immediately rather dumps core with double free or corruption (!prev) somewhere near the middle of the file

Last edited 11 months ago by Kiran (previous) (diff)

comment:3 by Aseer Tayeem, 11 months ago

I also tried this on the git master and I guess the behavior is not always the same, maybe it depends on the input audio. Also avf_showcqt.c hasn't been touched in years except for some reorganization, so there hasn't been a fix.

comment:4 by ePirat, 11 months ago

Reproduced by developer: set
Status: newopen

comment:6 by Muhammad Faiz, 9 months ago

Resolution: fixed
Status: openclosed
Note: See TracTickets for help on using tickets.