[FFmpeg-devel] [PATCH 0/1][TOOL][HACK] Allocation NULL check fuzzer

Derek Buitenhuis derek.buitenhuis at gmail.com
Fri Nov 24 21:45:46 EET 2017


I've had this kicking around for like 4 years, maybe it can be of use to some people.
I haven't done full scale fuzzing with this because laziness. I just sometimes run it
when I'm bored. It's not thread-safe, but it would be trivial to make it so.

It's based off my old LD_PRELOAD hack from here:

    https://gist.github.com/dwbuiten/7101755

Optionally takes two env vars, MALLOC_SEED (the seed), and MALLOC_FAILPROB for the
probability of failing.

I've been running it directly integrated inside FFmpeg's allocator because it makes
it easier to run under gdb to find where it actually crashes, if the stack trace of
the failure is not enough info/context.

Currently FFmpeg has a lot of unchecked allocations - just one single FATE run with
this found:

    daemon404 at bbvm:~/dev/f/ffmpeg/tests/data/fate$ grep Seg *.err
    adpcm-ima-amv.err:Segmentation fault
    adpcm-ima-apc.err:Segmentation fault
    caf.err:Segmentation fault
    filter-mergeplanes.err:Segmentation fault
    filter-paletteuse-bayer.err:Segmentation fault
    filter-paletteuse-sierra2_4a.err:Segmentation fault
    lavf-wav.err:Segmentation fault
    lavf-wav_peak.err:Segmentation fault
    lavf-wav_peak_only.err:Segmentation fault
    vorbis-encode.err:Segmentation fault
    vsynth1-msvideo1.err:Segmentation fault

Plus an infinite EAGAIN loop with av_usleep ffmpeg.c, that I'm still trying to
debug.

It prints a stack trace when it fails so that you know which allocation failed:

    daemon404 at bbvm:~/dev/f/ffmpeg/tests/data/fate$ cat vorbis-encode.err

    [... snip ...]

    FAILED. Iteration = 9789, Seed = 1511549218.

    my_posix_memalign:77 in libavutil/posixmemalign.c
    av_malloc:89 in libavutil/mem.c
    av_mallocz:240 in libavutil/mem.c
    av_frame_alloc:152 in libavutil/frame.c
    av_frame_clone:499 in libavutil/frame.c
    vorbis_encode_frame:1098 in libavcodec/vorbisenc.c
    avcodec_encode_audio2:198 in libavcodec/encode.c
    do_encode:377 in libavcodec/encode.c
    avcodec_send_frame:423 in libavcodec/encode.c
    do_audio_out:931 in fftools/ffmpeg.c
    reap_filters:1507 in fftools/ffmpeg.c
    transcode_step:4562 in fftools/ffmpeg.c
    transcode:4606 in fftools/ffmpeg.c
    main:4812 in fftools/ffmpeg.c
    (null):0 in (null)
    (null):0 in (null)
    (null):0 in (null)
    Segmentation fault

The (null) stuff is noise from libbacktrace, and could be skipped with a proper
callback.

And e.g. to reproduce this under gdb:

    $ MALLOC_SEED=1511549218 gdb --args /home/daemon404/dev/f/ffmpeg/ffmpeg_g \
      -nostdin -nostats -cpuflags all -hwaccel none -threads 1 -thread_type frame+slice \ 
      -i /home/daemon404/fate/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a vorbis \
      -strict experimental -f ogg -y /home/daemon404/dev/f/ffmpeg/tests/data/fate/vorbis-encode.ogg

(Obtained from 'make fate-vorbis-encode V=1'.)

Currently it's using libbacktrace from GCC, which can be build entirely separately from
GDB (cd libbacktrace && ./configure && make && cp backtrace.h /usr/local/include &&
cp .libs/libbacktrace.a /usr/local/lib). Add -lbacktrace to extra-libs. Hacky? Yeah...

Derek Buitenhuis (1):
  Allocation NULL check fuzzing tool

 libavutil/mem.c           |  4 ++-
 libavutil/posixmemalign.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 1 deletion(-)
 create mode 100644 libavutil/posixmemalign.c

-- 
2.15.0



More information about the ffmpeg-devel mailing list