FLIF-hub / FLIF

Free Lossless Image Format
Other
3.72k stars 229 forks source link

Heap overflow in FLIF #457

Open Google-Autofuzz opened 7 years ago

Google-Autofuzz commented 7 years ago

Hello FLIF team,

As part of our fuzzing efforts at Google, we have identified an issue affecting FLIF (tested with revision 53ea74017b1b8e97b7f5ac04dde209002efeb451). To reproduce, we are attaching a Dockerfile flif_report1.zip which compiles the project with LLVM, taking advantage of the sanitizers that it offers. More information about how to use the attached Dockerfile can be found here: https://docs.docker.com/engine/reference/builder/

TL;DR instructions:

From another terminal, outside the container: docker cp /path/to/attached/reproducer running_container_hostname:/fuzzing/reproducer (reference: https://docs.docker.com/engine/reference/commandline/cp/)

And, back inside the container: /fuzzing/repro.sh /fuzzing/reproducer

Alternatively, and depending on the bug, you could use gcc, valgrind or other instrumentation tools to aid in the investigation. The sanitizer error that we encountered is here:

==22==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7fdbc42ff780 at pc 0x7fdbc7eef268 bp 0x7ffc3d930510 sp 0x7ffc3d930508
READ of size 2 at 0x7fdbc42ff780 thread T0
    #0 0x7fdbc7eef267 in Plane<unsigned short>::get(int, unsigned long, unsigned long) const (/fuzzing/FLIF/src/libflif.so.0+0xb8267)
    #1 0x7fdbc8186e3d in void flif_decode_FLIF2_inner_interpol<BlobReader>(std::vector<Image, std::allocator<Image> >&, ColorRanges const*, int, int, int, int, std::vector<int, std::allocator<int> >&, std::vector<Transform<BlobReader>*, std::allocator<Transform<BlobReader>*> >&) (/fuzzing/FLIF/src/libflif.so.0+0x34fe3d)
    #2 0x7fdbc822c7e8 in bool flif_decode_FLIF2_inner_vertical<BlobReader, RacInput24<BlobReader>, FinalPropertySymbolCoder<SimpleBitChance, RacInput24<BlobReader>, 18>, Plane<unsigned short>, ColorRanges>(int, BlobReader&, RacInput24<BlobReader>&, std::vector<FinalPropertySymbolCoder<SimpleBitChance, RacInput24<BlobReader>, 18>, std::allocator<FinalPropertySymbolCoder<SimpleBitChance, RacInput24<BlobReader>, 18> > >&, std::vector<Image, std::allocator<Image> >&, ColorRanges const*, int, int, int, int, int, int, int, std::vector<int, std::allocator<int> >&, std::vector<Transform<BlobReader>*, std::allocator<Transform<BlobReader>*> >&, int) (/fuzzing/FLIF/src/libflif.so.0+0x3f57e8)
    #3 0x7fdbc8227cfb in bool flif_decode_FLIF2_inner<BlobReader, RacInput24<BlobReader>, FinalPropertySymbolCoder<SimpleBitChance, RacInput24<BlobReader>, 18>, ColorRanges>(BlobReader&, RacInput24<BlobReader>&, std::vector<FinalPropertySymbolCoder<SimpleBitChance, RacInput24<BlobReader>, 18>, std::allocator<FinalPropertySymbolCoder<SimpleBitChance, RacInput24<BlobReader>, 18> > >&, std::vector<Image, std::allocator<Image> >&, ColorRanges const*, int, int, flif_options&, std::vector<Transform<BlobReader>*, std::allocator<Transform<BlobReader>*> >&, unsigned int (*)(unsigned int, long, unsigned char, void*, void*), void*, std::vector<Image, std::allocator<Image> >&) (/fuzzing/FLIF/src/libflif.so.0+0x3f0cfb)
    #4 0x7fdbc82257d2 in bool flif_decode_FLIF2_pass<BlobReader, RacInput24<BlobReader>, FinalPropertySymbolCoder<SimpleBitChance, RacInput24<BlobReader>, 18> >(BlobReader&, RacInput24<BlobReader>&, std::vector<Image, std::allocator<Image> >&, ColorRanges const*, std::vector<Tree, std::allocator<Tree> >&, int, int, flif_options&, std::vector<Transform<BlobReader>*, std::allocator<Transform<BlobReader>*> >&, unsigned int (*)(unsigned int, long, unsigned char, void*, void*), void*, std::vector<Image, std::allocator<Image> >&) (/fuzzing/FLIF/src/libflif.so.0+0x3ee7d2)
    #5 0x7fdbc8013050 in bool flif_decode_main<18, BlobReader>(RacInput24<BlobReader>&, BlobReader&, std::vector<Image, std::allocator<Image> >&, ColorRanges const*, std::vector<Transform<BlobReader>*, std::allocator<Transform<BlobReader>*> >&, flif_options&, unsigned int (*)(unsigned int, long, unsigned char, void*, void*), void*, std::vector<Image, std::allocator<Image> >&) (/fuzzing/FLIF/src/libflif.so.0+0x1dc050)
    #6 0x7fdbc800bfe3 in bool flif_decode<BlobReader>(BlobReader&, std::vector<Image, std::allocator<Image> >&, unsigned int (*)(unsigned int, long, unsigned char, void*, void*), void*, int, std::vector<Image, std::allocator<Image> >&, flif_options&, metadata_options&, FLIF_INFO*) (/fuzzing/FLIF/src/libflif.so.0+0x1d4fe3)
    #7 0x7fdbc82ddf4e in FLIF_DECODER::decode_memory(void const*, unsigned long) (/fuzzing/FLIF/src/libflif.so.0+0x4a6f4e)
    #8 0x7fdbc82def98 in flif_decoder_decode_memory (/fuzzing/FLIF/src/libflif.so.0+0x4a7f98)
    #9 0x5085f5 in LLVMFuzzerTestOneInput /fuzzing/FLIF/src/fuzzer.cc:6:3
    #10 0x50f17c in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzzing/FLIF/src/fuzzer+0x50f17c)
    #11 0x50e93e in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) (/fuzzing/FLIF/src/fuzzer+0x50e93e)
    #12 0x50879d in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*) (/fuzzing/FLIF/src/fuzzer+0x50879d)
    #13 0x509c6f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/fuzzing/FLIF/src/fuzzer+0x509c6f)
    #14 0x50864c in main (/fuzzing/FLIF/src/fuzzer+0x50864c)
    #15 0x7fdbc6bf22b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
    #16 0x41dd09 in _start (/fuzzing/FLIF/src/fuzzer+0x41dd09)

0x7fdbc42ff780 is located 26 bytes to the right of 900966-byte region [0x7fdbc4223800,0x7fdbc42ff766)
allocated by thread T0 here:
    #0 0x505280 in operator new(unsigned long) (/fuzzing/FLIF/src/fuzzer+0x505280)
    #1 0x7fdbc7eeded8 in Plane<unsigned short>::Plane(unsigned long, unsigned long, int, int) (/fuzzing/FLIF/src/libflif.so.0+0xb6ed8)
    #2 0x7fdbc7ee72a0 in Image::real_init(bool) (/fuzzing/FLIF/src/libflif.so.0+0xb02a0)
    #3 0x7fdbc800b556 in bool flif_decode<BlobReader>(BlobReader&, std::vector<Image, std::allocator<Image> >&, unsigned int (*)(unsigned int, long, unsigned char, void*, void*), void*, int, std::vector<Image, std::allocator<Image> >&, flif_options&, metadata_options&, FLIF_INFO*) (/fuzzing/FLIF/src/libflif.so.0+0x1d4556)
    #4 0x7fdbc82ddf4e in FLIF_DECODER::decode_memory(void const*, unsigned long) (/fuzzing/FLIF/src/libflif.so.0+0x4a6f4e)
    #5 0x7fdbc82def98 in flif_decoder_decode_memory (/fuzzing/FLIF/src/libflif.so.0+0x4a7f98)
    #6 0x5085f5 in LLVMFuzzerTestOneInput /fuzzing/FLIF/src/fuzzer.cc:6:3
    #7 0x50f17c in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzzing/FLIF/src/fuzzer+0x50f17c)
    #8 0x50864c in main (/fuzzing/FLIF/src/fuzzer+0x50864c)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/fuzzing/FLIF/src/libflif.so.0+0xb8267) in Plane<unsigned short>::get(int, unsigned long, unsigned long) const
Shadow bytes around the buggy address:
  0x0ffbf8857ea0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffbf8857eb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffbf8857ec0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffbf8857ed0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffbf8857ee0: 00 00 00 00 00 00 00 00 00 00 00 00 06 fa fa fa
=>0x0ffbf8857ef0:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ffbf8857f00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ffbf8857f10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ffbf8857f20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ffbf8857f30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ffbf8857f40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==22==ABORTING

We will gladly work with you so you can successfully confirm and reproduce this issue. Do let us know if you have any feedback surrounding the documentation.

Once you have reproduced the issue, we’d appreciate to learn your expected timeline for an update to be released. With any fix, please attribute the report to “Google Autofuzz project”.

We are also pleased to inform you that your project is eligible for inclusion to the OSS-Fuzz project, which can provide additional continuous fuzzing, and encourage you to investigate integration options.

Don’t hesitate to let us know if you have any questions!

Google AutoFuzz Team

jonsneyers commented 7 years ago

This one doesn't reproduce anymore in the current version (cfd25e57578ccd047dd2177aea2924f5a3fa1e5f). Instead of a heap overflow, it now results in a memleak.