Fix buffer overflow in codecForName + normalizeAddressesAndDecodeIdn
The buffer overflow can happen if an invalid codec is passed to normalizeAddressesAndDecodeIdn
. There is a necessary check already:
https://github.com/KDE/kcodecs/blob/master/src/kcodecs.cpp#L273-L274
so the missing part is to return nullptr
.
Address sanitizer report:
==314938==ERROR: AddressSanitizer: global-buffer-overflow on address 0x555ea45822a8 at pc 0x555ea2a9ccf5 bp 0x7fff4d6bb5f0 sp 0x7fff4d6bb5e8
READ of size 8 at 0x555ea45822a8 thread T0
#0 0x555ea2a9ccf4 in std::__uniq_ptr_impl<KCodecs::Codec, std::default_delete<KCodecs::Codec>>::_M_ptr() const /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/unique_ptr.h:199:51
#1 0x555ea2a90076 in std::unique_ptr<KCodecs::Codec, std::default_delete<KCodecs::Codec>>::get() const /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/unique_ptr.h:470:21
#2 0x555ea2a85783 in KCodecs::Codec::codecForName(QByteArrayView) KDE/kcodecs/src/kcodecs.cpp:541:24
#3 0x555ea2a899c8 in KCodecs::parseEncodedWord(char const*&, char const*, QString*, QByteArray*, QByteArray*, QByteArray const&, KCodecs::CharsetOption) KDE/kcodecs/src/kcodecs.cpp:273:20
#4 0x555ea2a8b8c1 in KCodecs::decodeRFC2047String(QByteArrayView, QByteArray*, QByteArray const&, KCodecs::CharsetOption) KDE/kcodecs/src/kcodecs.cpp:370:17
#5 0x555ea2a7a217 in KEmailAddress::normalizeAddressesAndDecodeIdn(QString const&) KDE/kcodecs/src/kemailaddress.cpp:1010:27
#6 0x555ea109560e in LLVMFuzzerTestOneInput KDE/kcodecs/myfuzzing/emailaddress_fuzzer.cc:34:3
#7 0x555ea0fa1660 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (KDE/kcodecs/myfuzzing/prefix/bin/emailaddress_fuzzer+0x67f660) (BuildId: 1690c881f5f2b287ec56a484393cffd29fe39253)
#8 0x555ea0f8b7b2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (KDE/kcodecs/myfuzzing/prefix/bin/emailaddress_fuzzer+0x6697b2) (BuildId: 1690c881f5f2b287ec56a484393cffd29fe39253)
#9 0x555ea0f911f6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (KDE/kcodecs/myfuzzing/prefix/bin/emailaddress_fuzzer+0x66f1f6) (BuildId: 1690c881f5f2b287ec56a484393cffd29fe39253)
#10 0x555ea0fba362 in main (KDE/kcodecs/myfuzzing/prefix/bin/emailaddress_fuzzer+0x698362) (BuildId: 1690c881f5f2b287ec56a484393cffd29fe39253)
#11 0x7f9866d32d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#12 0x7f9866d32e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#13 0x555ea0f86794 in _start (KDE/kcodecs/myfuzzing/prefix/bin/emailaddress_fuzzer+0x664794) (BuildId: 1690c881f5f2b287ec56a484393cffd29fe39253)
0x555ea45822a8 is located 24 bytes before global variable 'guard variable for KCodecs::Codec::codecForName(QByteArrayView)::s_codecs' defined in 'KDE/kcodecs/src/kcodecs.cpp' (0x555ea45822c0) of size 8
0x555ea45822a8 is located 8 bytes after global variable 'KCodecs::Codec::codecForName(QByteArrayView)::s_codecs' defined in 'KDE/kcodecs/src/kcodecs.cpp:526' (0x555ea4582240) of size 96
SUMMARY: AddressSanitizer: global-buffer-overflow /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/unique_ptr.h:199:51 in std::__uniq_ptr_impl<KCodecs::Codec, std::default_delete<KCodecs::Codec>>::_M_ptr() const
Shadow bytes around the buggy address:
0x555ea4582000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x555ea4582080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x555ea4582100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x555ea4582180: 00 00 00 f9 f9 f9 f9 f9 00 f9 f9 f9 00 00 00 00
0x555ea4582200: 00 00 00 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 00
=>0x555ea4582280: 00 00 00 00 f9[f9]f9 f9 00 f9 f9 f9 00 00 00 00
0x555ea4582300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x555ea4582380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x555ea4582400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x555ea4582480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x555ea4582500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==314938==ABORTING