Opened 4 months ago

Last modified 3 months 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:

  1. 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
    
  1. 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 johnt, 4 months ago

Version: unspecifiedgit-master

comment:2 by Carl Eugen Hoyos, 4 months ago

Does using -max_alloc avoid the issue?

comment:3 by Carl Eugen Hoyos, 4 months ago

Keywords: mp3 added

comment:4 by Carl Eugen Hoyos, 3 months ago

Component: undeterminedavcodec

-max_alloc indeed avoids the issue.

comment:5 by johnt, 3 months 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
Note: See TracTickets for help on using tickets.