Hi! I've been fuzzing your projects and found an input, that leads to integer overflow and source/detail/cryptography/compound_document.cpp:591.
Executing with this input leads to later heap buffer overflow in /xlnt/source/detail/cryptography/compound_document.cpp:975.
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/new_allocator.h:147:27: runtime error: implicit conversion from type 'char' of value -48 (8-bit, signed) to type 'unsigned char' changed the value to 208 (8-bit, unsigned)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/new_allocator.h:147:27 in
/xlnt/source/detail/cryptography/compound_document.cpp:532:40: runtime error: shift exponent 201 is too large for 64-bit type 'std::size_t' (aka 'unsigned long')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /xlnt/source/detail/cryptography/compound_document.cpp:532:40 in
/xlnt/source/detail/cryptography/compound_document.cpp:591:80: runtime error: unsigned integer overflow: 512 * 18446744073709551615 cannot be represented in type 'unsigned long'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /xlnt/source/detail/cryptography/compound_document.cpp:591:80 in
/xlnt/source/detail/cryptography/compound_document.cpp:591:64: runtime error: unsigned integer overflow: 512 + 18446744073709551104 cannot be represented in type 'unsigned long'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /xlnt/source/detail/cryptography/compound_document.cpp:591:64 in
=================================================================
==17==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x615000002380 at pc 0x0000004dafd7 bp 0x7fffffffb8b0 sp 0x7fffffffb078
READ of size 128 at 0x615000002380 thread T0
#0 0x4dafd6 in __asan_memcpy /llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3
#1 0x10a16a9 in xlnt::detail::compound_document::read_directory() /xlnt/source/detail/cryptography/compound_document.cpp:975:34
#2 0x109e3eb in xlnt::detail::compound_document::compound_document(std::istream&) /xlnt/source/detail/cryptography/compound_document.cpp:517:5
#3 0x986850 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
#4 0x98604a 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
#5 0x9877fe 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
#6 0x547148 in xlnt::workbook::load(std::istream&) /xlnt/source/workbook/workbook.cpp:901:22
#7 0x56dfa7 in xlnt::workbook::load(std::vector<unsigned char, std::allocator<unsigned char> > const&) /xlnt/source/workbook/workbook.cpp:919:5
#8 0x514db2 in LLVMFuzzerTestOneInput /xlnt/build/../load_fuzzer.cc:9:23
#9 0x441d51 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15
#10 0x42c36c in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
#11 0x4320db in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9
#12 0x45ae22 in main /llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#13 0x7ffff7a760b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
#14 0x426c8d in _start (/load_fuzzer+0x426c8d)
0x615000002380 is located 768 bytes to the right of 512-byte region [0x615000001e80,0x615000002080) allocated by thread T0 here:
#0 0x51235d in operator new(unsigned long) /llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:95:3
#1 0x110db5e in __gnu_cxx::new_allocator<xlnt::detail::compound_document_entry>::allocate(unsigned long, void const*) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/new_allocator.h:114:27
#2 0x110d9ca in std::allocator_traits<std::allocator<xlnt::detail::compound_document_entry> >::allocate(std::allocator<xlnt::detail::compound_document_entry>&, unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/alloc_traits.h:444:20
#3 0x110cf2e in std::_Vector_base<xlnt::detail::compound_document_entry, std::allocator<xlnt::detail::compound_document_entry> >::_M_allocate(unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:343:20
#4 0x111bf85 in void std::vector<xlnt::detail::compound_document_entry, std::allocator<xlnt::detail::compound_document_entry> >::_M_realloc_insert<xlnt::detail::compound_document_entry>(__gnu_cxx::__normal_iterator<xlnt::detail::compound_document_entry*, std::vector<xlnt::detail::compound_document_entry, std::allocator<xlnt::detail::compound_document_entry> > >, xlnt::detail::compound_document_entry&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/vector.tcc:440:33
#5 0x111b705 in void std::vector<xlnt::detail::compound_document_entry, std::allocator<xlnt::detail::compound_document_entry> >::emplace_back<xlnt::detail::compound_document_entry>(xlnt::detail::compound_document_entry&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/vector.tcc:121:4
#6 0x10bea14 in std::vector<xlnt::detail::compound_document_entry, std::allocator<xlnt::detail::compound_document_entry> >::push_back(xlnt::detail::compound_document_entry&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1201:9
#7 0x10a0c57 in xlnt::detail::compound_document::read_directory() /xlnt/source/detail/cryptography/compound_document.cpp:949:18
#8 0x109e3eb in xlnt::detail::compound_document::compound_document(std::istream&) /xlnt/source/detail/cryptography/compound_document.cpp:517:5
#9 0x986850 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
#10 0x98604a 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
#11 0x9877fe 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
#12 0x547148 in xlnt::workbook::load(std::istream&) /xlnt/source/workbook/workbook.cpp:901:22
#13 0x56dfa7 in xlnt::workbook::load(std::vector<unsigned char, std::allocator<unsigned char> > const&) /xlnt/source/workbook/workbook.cpp:919:5
#14 0x514db2 in LLVMFuzzerTestOneInput /xlnt/build/../load_fuzzer.cc:9:23
#15 0x441d51 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15
#16 0x42c36c in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
#17 0x4320db in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9
#18 0x45ae22 in main /llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#19 0x7ffff7a760b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
SUMMARY: AddressSanitizer: heap-buffer-overflow /llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3 in __asan_memcpy
Shadow bytes around the buggy address:
0x0c2a7fff8420: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff8430: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff8440: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff8450: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff8460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a7fff8470:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff8480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff8490: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff84a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff84b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff84c0: 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
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
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
==17==ABORTING
Hi! I've been fuzzing your projects and found an input, that leads to integer overflow and source/detail/cryptography/compound_document.cpp:591. Executing with this input leads to later heap buffer overflow in /xlnt/source/detail/cryptography/compound_document.cpp:975.
Steps for reproducing:
You will see something like this:
OS version: ubuntu 20.04
xlnt version: d88c901faa539f9272a81ba0bab72def70ca18d7