Opened 2 years ago
Last modified 2 years ago
#9968 new defect
Certain broken MP3s may cause allocation of large amounts of memory
Reported by: | johnt | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | avcodec |
Version: | git-master | Keywords: | mp3 |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
Summary of the bug:
Tested with commit 479747645f795b6f4f376578ea1556409f943c31.
If an MP3 file contains a region of all-zero bytes, the entire byte region gets
included into the same AVPacket when FFmpeg reads the file. I'm not sure if this
is expected behavior or not, but it may potentially be problematic since it
allows for triggering allocations of essentially arbitrarily large amounts of
memory (limited only by the size of the entire input MP3 file).
How to reproduce:
- Create an MP3 file with a large amount of zero bytes appended at the end. This example uses 100 MiB, but larger sizes can be used as well.
$ ./ffmpeg_g -f lavfi -i "sine=frequency=220:duration=10" -c:a libmp3lame 10s_sine.mp3 $ dd if=/dev/zero of=100m_zeroes.bin bs=8192 count=12800 $ cat 10s_sine.mp3 100m_zeroes.bin > repro.mp3
- Demux the file to trigger the large (111 174 804 byte) allocation. (The $rsi reg is the 2nd size argument to realloc. Breakpoint condition may need to be adjusted on platforms other than x86_64.)
$ printf 'break realloc if $rsi >= 8192 * 12800\nrun\nbacktrace\ninfo register rsi\n' > gdb_commands.txt $ gdb -x gdb_commands.txt --args ./ffmpeg_g -i repro.mp3 -f null /dev/null
GDB output (from after the breakpoint is hit):
Thread 2 "ffmpeg_g" hit Breakpoint 1, 0x00007f561175a19f in realloc () from /lib/ld-musl-x86_64.so.1 #0 0x00007f561175a19f in realloc () from /lib/ld-musl-x86_64.so.1 #1 0x0000559d7c33c2e3 in av_fast_realloc (ptr=<optimized out>, size=size@entry=0x7f5611734f90, min_size=111174804) at libavutil/mem.c:523 #2 0x0000559d7bc932d6 in ff_combine_frame (pc=pc@entry=0x7f5611734f80, next=next@entry=-100, buf=buf@entry=0x7f56116be6b8, buf_size=buf_size@entry=0x7f56116be6b4) at libavcodec/parser.c:224 #3 0x0000559d7c1dfe4d in mpegaudio_parse (s1=0x7f56117256c0, avctx=<optimized out>, poutbuf=0x7f56117cc998, poutbuf_size=0x7f56117cc9a0, buf=<optimized out>, buf_size=<optimized out>) at libavcodec/mpegaudio_parser.c:115 #4 0x0000559d7bc92e75 in av_parser_parse2 (s=0x7f56117256c0, avctx=0x7f56117250c0, poutbuf=poutbuf@entry=0x7f56117cc998, poutbuf_size=poutbuf_size@entry=0x7f56117cc9a0, buf=<optimized out>, buf@entry=0x7f56116dfac0 "", buf_size=buf_size@entry=1024, pts=-9223372036854775808, dts=-9223372036854775808, pos=104714467) at libavcodec/parser.c:163 #5 0x0000559d7b83dec0 in parse_packet (s=s@entry=0x7f56117cc0c0, pkt=pkt@entry=0x7f56116e50c0, stream_index=<optimized out>, flush=flush@entry=0) at libavformat/demux.c:1140 #6 0x0000559d7b83f3a5 in read_frame_internal (s=0x7f56117cc0c0, pkt=0x7f56116e50c0) at libavformat/demux.c:1334 #7 0x0000559d7b84006d in av_read_frame (s=0x7f56117cc0c0, pkt=0x7f56116e50c0) at libavformat/demux.c:1450 #8 0x0000559d7b5805d0 in input_thread (arg=0x7f5611725ec0) at fftools/ffmpeg_demux.c:196 #9 0x00007f56117881f5 in ?? () from /lib/ld-musl-x86_64.so.1 #10 0x0000000000000000 in ?? () rsi 0x6a06494 111174804
FFmpeg version:
ffmpeg version N-108616-g479747645f Copyright (c) 2000-2022 the FFmpeg developers built with gcc 11.2.1 (Alpine 11.2.1_git20220219) 20220219 configuration: --enable-libmp3lame --disable-shared --enable-static libavutil 57. 39.101 / 57. 39.101 libavcodec 59. 50.100 / 59. 50.100 libavformat 59. 34.101 / 59. 34.101 libavdevice 59. 8.101 / 59. 8.101 libavfilter 8. 49.101 / 8. 49.101 libswscale 6. 8.112 / 6. 8.112 libswresample 4. 9.100 / 4. 9.100
Change History (5)
comment:1 by , 2 years ago
Version: | unspecified → git-master |
---|
comment:2 by , 2 years ago
comment:3 by , 2 years ago
Keywords: | mp3 added |
---|
comment:5 by , 2 years ago
Hi, thanks a lot for the info on that max_alloc setting! I had missed that that existed. It does indeed work for limiting the allocation size.
I was a little bit surprised though that the mp3 parsing didn’t seem to fail if the allocation failure case occurred. I can see the error log messages, but it seems to produce a truncated AVPacket instead of failing. Is that expected behavior? (This is somewhat of a tangent to the original problem stated in the ticket - let me know if you’d prefer that I open a separate ticket about this instead.)
I.e. running something like this that has a 20 MiB single-allocation limit:
$ ./ffprobe_g -hide_banner -max_alloc 20971520 -show_packets repro.mp3 | grep 'size=' | tail -n1
Produces:
[mp3 @ 0x7f18918440c0] invalid concatenated file detected - using bitrate for duration [mp3 @ 0x7f18918440c0] Estimating duration from bitrate, this may be inaccurate Input #0, mp3, from 'repro.mp3': Metadata: encoder : Lavf59.34.101 Duration: 03:38:37.23, start: 0.025057, bitrate: 64 kb/s Stream #0:0: Audio: mp3, 44100 Hz, mono, fltp, 64 kb/s Failed to reallocate parser buffer to 20972232 Failed to reallocate parser buffer to 20971584 Last message repeated 2 times size=20970872
Does using -max_alloc avoid the issue?