|
=== Uninitialized Memory Read Evidence ===
|
|
Command: json2dcm --ignore-errors poc.json /dev/null
|
|
PoC size: 40 bytes
|
|
Build: clang -fsanitize=address,undefined (UBSan required)
|
|
|
|
$ json2dcm --ignore-errors poc.json /dev/null
|
|
|
|
dcjsonrd.cc:571:18: runtime error: load of value 3200171710,
|
|
which is not a valid value for type 'jsmntype_t'
|
|
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
|
|
dcjsonrd.cc:571:18
|
|
|
|
The UBSan error confirms that at dcjsonrd.cc:571, the code loads
|
|
a value (3200171710 = 0xBEBDBEBE, an ASan poison pattern) from
|
|
the token's type field. This is heap garbage from an uninitialized
|
|
sentinel token past the end of the valid JSMN token array.
|
|
|
|
Note: This bug requires UBSan (-fsanitize=undefined) to detect.
|
|
ASan alone does not flag this because the read is within the
|
|
allocated token array's memory (the sentinel slot), not out of
|
|
bounds. The issue is that the sentinel token's type field was
|
|
never initialized by the JSMN tokenizer or by reserveTokens().
|
|
|
|
Root cause: reserveTokens() at dcjsonrd.cc:200 does:
|
|
memset(tokenArray_, 0, tokenNum * sizeof(OFJsmnToken));
|
|
|
|
This zeros the first tokenNum tokens, but the sentinel at
|
|
tokenArray_[tokenNum] (allocated via new[tokenNum+1]) has only
|
|
start, end, size explicitly set. The 'type' field is left
|
|
UNINITIALIZED.
|
|
|
|
When parseElement() at line 571 reads this uninitialized type:
|
|
switch(current->type) { ... }
|
|
UBSan detects the invalid enum value load.
|