tfussell / xlnt

:bar_chart: Cross-platform user-friendly xlsx library for C++11+
Other
1.47k stars 409 forks source link

Integer overflow in compound_document::read_sector #616

Open kobrineli opened 2 years ago

kobrineli commented 2 years ago

I've found an input, that leads to unsigned integer overflow in source/detail/cryptography/compound_document.cpp:591. Also, executing with this input leads to crash in source/detail/cryptography/compound_document.cpp:592, because size of vector, that was taken from input, is larger than max_size.

Steps for reproducing:

  1. Build docker container for xlnt from https://github.com/ispras/oss-sydr-fuzz/tree/master/projects/xlnt
  2. Run docker container and execute /load_fuzzer overflow_input.txt with this input: overflow_input.txt
  3. You will see something like this:

    /xlnt/source/detail/cryptography/compound_document.cpp:591:80: runtime error: unsigned integer overflow: 9223372036854775808 * 18446744073709551615 cannot be represented in type 'unsigned long'
    SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /xlnt/source/detail/cryptography/compound_document.cpp:591:80 in terminate called after throwing an instance of 'std::length_error'
      what():  cannot create std::vector larger than max_size()
    ==113== ERROR: libFuzzer: deadly signal
        #0 0x4e5ba1 in __sanitizer_print_stack_trace /llvm-project/compiler-rt/lib/asan/asan_stack.cpp:87:3
        #1 0x45a4d7 in fuzzer::PrintStackTrace() /llvm-project/compiler-rt/lib/fuzzer/FuzzerUtil.cpp:210:5
        #2 0x440813 in fuzzer::Fuzzer::CrashCallback() /llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:233:3
        #3 0x7ff126e4d3bf  (/lib/x86_64-linux-gnu/libpthread.so.0+0x153bf)
        #4 0x7ff126c5e18a in __libc_signal_restore_set /build/glibc-eX1tMB/glibc-2.31/signal/../sysdeps/unix/sysv/linux/internal-signals.h:86:3
        #5 0x7ff126c5e18a in raise /build/glibc-eX1tMB/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:48:3
        #6 0x7ff126c3d858 in abort /build/glibc-eX1tMB/glibc-2.31/stdlib/abort.c:79:7
        #7 0x7ff127048910  (/lib/x86_64-linux-gnu/libstdc++.so.6+0x9e910)
        #8 0x7ff12705438b  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa38b)
        #9 0x7ff1270543f6 in std::terminate() (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa3f6)
        #10 0x7ff1270546a8 in __cxa_throw (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa6a8)
        #11 0x7ff12704b325 in std::__throw_length_error(char const*) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xa1325)
        #12 0x77a7af in std::vector<unsigned char, std::allocator<unsigned char> >::_S_check_init_len(unsigned long, std::allocator<unsigned char> const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1767:4
        #13 0x9aa224 in std::vector<unsigned char, std::allocator<unsigned char> >::vector(unsigned long, unsigned char const&, std::allocator<unsigned char> const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:521:15
        #14 0x10c13ef in void xlnt::detail::compound_document::read_sector<int>(int, xlnt::detail::binary_writer<int>&) /xlnt/source/detail/cryptography/compound_document.cpp:592:23
        #15 0x10986b6 in xlnt::detail::compound_document::read_sat() /xlnt/source/detail/cryptography/compound_document.cpp:1273:9
        #16 0x1097063 in xlnt::detail::compound_document::compound_document(std::istream&) /xlnt/source/detail/cryptography/compound_document.cpp:515:5
        #17 0x982c40 in (anonymous namespace)::decrypt_xlsx(std::vector<unsigned char, std::allocator<unsigned char> > const&, std::__cxx11::basic_string<char16_t, std::char_traits<char16_t>, std::allocator<char16_t> > const&) /xlnt/source/detail/cryptography/xlsx_crypto_consumer.cpp:320:37
        #18 0x98243a in xlnt::detail::decrypt_xlsx(std::vector<unsigned char, std::allocator<unsigned char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /xlnt/source/detail/cryptography/xlsx_crypto_consumer.cpp:339:12
        #19 0x983bee in xlnt::detail::xlsx_consumer::read(std::istream&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /xlnt/source/detail/cryptography/xlsx_crypto_consumer.cpp:345:28
        #20 0x547138 in xlnt::workbook::load(std::istream&) /xlnt/source/workbook/workbook.cpp:901:22
        #21 0x56df87 in xlnt::workbook::load(std::vector<unsigned char, std::allocator<unsigned char> > const&) /xlnt/source/workbook/workbook.cpp:919:5
        #22 0x514da2 in LLVMFuzzerTestOneInput /xlnt/build/../load_fuzzer.cc:9:23
        #23 0x441d41 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15
        #24 0x42c35c in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
        #25 0x4320cb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9
        #26 0x45ae12 in main /llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
        #27 0x7ff126c3f0b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
        #28 0x426c7d in _start (/load_fuzzer+0x426c7d)
    
    NOTE: libFuzzer has rudimentary signal handlers.
          Combine libFuzzer with AddressSanitizer or similar for better crash reports.
    • OS version: ubuntu 20.04
    • xlnt version: d88c901faa539f9272a81ba0bab72def70ca18d7