adafruit / Adafruit_MP3

mp3 decoding on arduino
40 stars 17 forks source link

Crashes in MP3 decoder found by fuzzing #22

Open jepler opened 3 months ago

jepler commented 3 months ago

I instrumented the host-based mp3 decoder test and asked the open source fuzzer aflplusplus to find crashes in it.

After running for an hour or two it found 95 distinct crashes: crashes.zip

some (many) of the crashes require use of the extra "-fsanitize=address" checker on the host. More info on how I built & tested to find these problems will be forthcoming, but to reproduce on a linux based computer you should just need to add "-fsanitize=address" to the Makefile, make then run on each input with a commandine like ./decoder <input> /dev/null. If the exit status is not 0 or 2 then a problem was detected.

One example:

=================================================================
==896588==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61d000000890 at pc 0x7ffff7848061 bp 0x7fffffffd9e0 sp 0x7fffffffd190
WRITE of size 41823 at 0x61d000000890 thread T0
    #0 0x7ffff7848060 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
    #1 0x55555556e6d3 in MP3Decode ../../src/mp3dec.c:351
    #2 0x555555557928 in main /home/jepler/src/circuitpython/lib/mp3/examples/standalone/main.c:159
    #3 0x7ffff7646249 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #4 0x7ffff7646304 in __libc_start_main_impl ../csu/libc-start.c:360
    #5 0x555555557ca0 in _start (/home/jepler/src/circuitpython/lib/mp3/examples/standalone/decoder+0x3ca0)

0x61d000000890 is located 0 bytes to the right of 2064-byte region [0x61d000000080,0x61d000000890)
allocated by thread T0 here:
    #0 0x7ffff78b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x55555555ce3c in xmp3_AllocateBuffers ../../src/buffers.c:111
    #2 0x55555557d17f  (/home/jepler/src/circuitpython/lib/mp3/examples/standalone/decoder+0x2917f)

Here, an inappropriate amount of memory is copied, possibly because the value mp3DecInfo->nSlots is not adequately validated.

here are the locations of the detected problems (1st and 2nd stack frames, sorted and uniq'd):

    #0 0x5555555580b3 in RefillBitstreamCache ../../src/bitstream.c:102
    #0 0x55555555c71c in RefillBitstreamCache ../../src/bitstream.c:93
    #0 0x55555555c72c in RefillBitstreamCache ../../src/bitstream.c:95
    #0 0x555555560e64 in xmp3_Dequantize ../../src/dequant.c:139
    #0 0x555555563910 in xmp3_DecodeHuffman ../../src/huffman.c:451
    #0 0x55555556d4c5 in MP3FindSyncWord ../../src/mp3dec.c:110
    #0 0x55555556eea8 in MP3ClearBadFrame ../../src/mp3dec.c:256
    #0 0x55555556f0a6 in MP3ClearBadFrame ../../src/mp3dec.c:256
    #0 0x55555556f1d4 in MP3ClearBadFrame ../../src/mp3dec.c:256
    #0 0x55555556fa69 in xmp3_PolyphaseMono ../../src/polyphase.c:145
    #0 0x555555576e87 in xmp3_IntensityProcMPEG1 ../../src/stproc.c:146
    #0 0x7ffff7848060 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
    #0 0x7ffff78481b7 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
    #1 0x5555555577f9 in mp3file_find_sync_word /home/jepler/src/circuitpython/lib/mp3/examples/standalone/main.c:48
    #1 0x5555555580b3 in xmp3_GetBits ../../src/bitstream.c:142
    #1 0x55555555c71c in xmp3_GetBits ../../src/bitstream.c:142
    #1 0x55555555c72c in xmp3_GetBits ../../src/bitstream.c:142
    #1 0x555555560cb8 in xmp3_Dequantize ../../src/dequant.c:139
    #1 0x55555556e349 in MP3Decode ../../src/mp3dec.c:389
    #1 0x55555556e6d3 in MP3Decode ../../src/mp3dec.c:351
    #1 0x55555556e734 in MP3Decode ../../src/mp3dec.c:400
    #1 0x55555556eb32 in MP3Decode ../../src/mp3dec.c:359
    #1 0x55555556eea8 in MP3ClearBadFrame ../../src/mp3dec.c:248
    #1 0x55555556f0a6 in MP3ClearBadFrame ../../src/mp3dec.c:248
    #1 0x55555556f1d4 in MP3ClearBadFrame ../../src/mp3dec.c:248
    #1 0x555555577d90 in xmp3_Subband ../../src/subband.c:86

Happily there appear to be a lot fewer than 95 distinct crash sites. (aflplusplus considers other details to make for different "paths": I think a different if/else path, or a different number of loop counts, or a different size of access can all create different crashes as far as aflpluslus is concerned, for instance)