https://bugs.kde.org/show_bug.cgi?id=525967
Bug ID: 525967
Summary: Heap read past TNEF and MAPI strings
Classification: Applications
Product: ktnef
Version First unspecified
Reported In:
Platform: Compiled Sources
OS: Linux
Status: REPORTED
Severity: normal
Priority: NOR
Component: general
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
Created attachment 196382
--> https://bugs.kde.org/attachment.cgi?id=196382&action=edit
tnef that causes the crash
DESCRIPTION
**Impact:** A crafted TNEF attribute can crash any consumer that parses it. The
same read can copy adjacent heap bytes into a parsed string. This is a one-byte
ASan-confirmed read.
**Trigger and evidence:** `cases/subject_nonul.tnef` is an 18-byte TNEF file
with a one-byte, non-NUL subject. Run `ASAN_OPTIONS=detect_leaks=0
/tmp/ktnef_repro_asan parse findings/repro/cases/subject_nonul.tnef`. ASan
reports `heap-buffer-overflow`, `READ of size 1`, at `readMAPIString` line 759,
called by `decodeMessage` line 210. The allocation is exactly one byte at line
749. The full trace is in
[string_oob.asan.txt](repro/logs/string_oob.asan.txt).
**Root cause:** ktnefparser.cpp:749 allocates exactly the declared length, then
passes its pointer to `QString::fromLatin1` or `QString::fromUtf16` without a
length. Both conversions search for a terminator beyond the allocation when
none is present. The return value of `readRawData` is also ignored, so a
truncated string can leave uninitialized bytes in that allocation. This helper
is reached from message attributes, attachment titles, and MAPI properties.
**Fix direction:** Check the declared length against the remaining attribute
data and the actual read count. Convert with an explicit length, handling a
trailing terminator only if it lies inside the buffer.
STEPS TO REPRODUCE
1. Compule ktnef with asan
2. Write small C reproducer to load this ktnef file
3. Witness crash
OBSERVED RESULT
```
org.kde.pim.ktnef: Attachment cross reference key: 0x0000
=================================================================
==41137==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x722d519e07b1 at pc 0x62f29aefd81f bp 0x7ffca6cbc610 sp 0x7ffca6cbc608
READ of size 1 at 0x722d519e07b1 thread T0
#0 0x62f29aefd81e in long long QtPrivate::lengthHelperPointer<char>(char
const*) /usr/include/x86_64-linux-gnu/qt6/QtCore/qbytearrayview.h:78:12
#1 0x62f29aefd81e in QByteArrayView::QByteArrayView<char*, true>(char*
const&) /usr/include/x86_64-linux-gnu/qt6/QtCore/qbytearrayview.h:162:28
#2 0x62f29aeede78 in readMAPIString(QDataStream&, bool, bool, int)
/home/fuzz/ktnef/src/ktnefparser.cpp:759:35
#3 0x62f29aeeaef8 in KTnef::ParserPrivate::decodeMessage()
/home/fuzz/ktnef/src/ktnefparser.cpp:210:17
#4 0x62f29aef73fe in KTnef::ParserPrivate::parseDevice()
/home/fuzz/ktnef/src/ktnefparser.cpp:415:22
#5 0x62f29af151f1 in main /tmp/ktnef-audit/harness.cpp:26:15
#6 0x760d5502a600 in __libc_start_call_main
csu/../sysdeps/nptl/libc_start_call_main.h:59:16
#7 0x760d5502a717 in __libc_start_main csu/../csu/libc-start.c:360:3
#8 0x62f29adfdbc4 in _start (/tmp/ktnef-audit/ktnef_asan+0x41bc4) (BuildId:
e8d138fb80df82076c679d970e73cd14feefcc55)
0x722d519e07b1 is located 0 bytes after 1-byte region
[0x722d519e07b0,0x722d519e07b1)
allocated by thread T0 here:
#0 0x62f29aee74b1 in operator new[](unsigned long)
(/tmp/ktnef-audit/ktnef_asan+0x12b4b1) (BuildId:
e8d138fb80df82076c679d970e73cd14feefcc55)
#1 0x62f29aeedd27 in readMAPIString(QDataStream&, bool, bool, int)
/home/fuzz/ktnef/src/ktnefparser.cpp:749:11
#2 0x62f29aeeaef8 in KTnef::ParserPrivate::decodeMessage()
/home/fuzz/ktnef/src/ktnefparser.cpp:210:17
#3 0x62f29aef73fe in KTnef::ParserPrivate::parseDevice()
/home/fuzz/ktnef/src/ktnefparser.cpp:415:22
#4 0x62f29af151f1 in main /tmp/ktnef-audit/harness.cpp:26:15
#5 0x760d5502a600 in __libc_start_call_main
csu/../sysdeps/nptl/libc_start_call_main.h:59:16
#6 0x760d5502a717 in __libc_start_main csu/../csu/libc-start.c:360:3
#7 0x62f29adfdbc4 in _start (/tmp/ktnef-audit/ktnef_asan+0x41bc4) (BuildId:
e8d138fb80df82076c679d970e73cd14feefcc55)
SUMMARY: AddressSanitizer: heap-buffer-overflow
/usr/include/x86_64-linux-gnu/qt6/QtCore/qbytearrayview.h:78:12 in long long
QtPrivate::lengthHelperPointer<char>(char const*)
Shadow bytes around the buggy address:
0x722d519e0500: fa fa 07 fa fa fa 00 fa fa fa fd fa fa fa fd fa
0x722d519e0580: fa fa 07 fa fa fa 00 fa fa fa fd fa fa fa fd fa
0x722d519e0600: fa fa 07 fa fa fa 00 fa fa fa 00 fa fa fa 00 00
0x722d519e0680: fa fa fd fd fa fa fd fd fa fa 00 fa fa fa fd fd
0x722d519e0700: fa fa fd fd fa fa 00 00 fa fa 00 00 fa fa 00 00
=>0x722d519e0780: fa fa 00 00 fa fa[01]fa fa fa fa fa fa fa fa fa
0x722d519e0800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x722d519e0880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x722d519e0900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x722d519e0980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x722d519e0a00: 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
==41137==ABORTING
```
EXPECTED RESULT
No crash.
SOFTWARE/OS VERSIONS
Operating System: Ubuntu 26.04
KDE Plasma Version: not applicable
KDE Frameworks Version: not applicable
Qt Version: 6
ADDITIONAL INFORMATION
This was a compiled source ktnef with latest commit:
2f0f59ceb9163f77cfb1e195777482674cedd88f
--
You are receiving this mail because:
You are watching all bug changes.