Assertion in TiXmlBase::StringEqual can cause DoS
Brought to you by:
leethomason
This vulnerability is caused by the following code:
bool TiXmlBase::StringEqual( const char* p,
const char* tag,
bool ignoreCase,
TiXmlEncoding encoding )
{
assert( p );
assert( tag );
if ( !p || !*p )
{
assert( 0 );
return false;
}
My program for testing:
#include "tinyxml.h"
#include <stdlib.h>
#include <string>
int main(int argc, char*argv[]){
char buf[10240];
if(argc < 2){
printf("args error\n");
return 0;
}
FILE *f = fopen(argv[1], "rb");
size_t len = fread(buf, 1, sizeof(buf), f);
std::string s(buf, sizeof(buf));
TiXmlDocument doc;
doc.Parse(s.c_str());
fclose(f);
return 0;
}
Result:
test_input: tinyxmlparser.cpp:543: static bool TiXmlBase::StringEqual(const char *, const char *, bool, TiXmlEncoding): Assertion `0' failed.
[1] 1843 abort ./test_input minimized_crash
And I use libfuzzer to get more detailed output:
harness2: tinyxmlparser.cpp:543: static bool TiXmlBase::StringEqual(const char *, const char *, bool, TiXmlEncoding): Assertion `0' failed.
==1849== ERROR: libFuzzer: deadly signal
#0 0x527e41 in __sanitizer_print_stack_trace (/home/presler/fuzzing/tinyxml/harness2+0x527e41)
#1 0x472f98 in fuzzer::PrintStackTrace() (/home/presler/fuzzing/tinyxml/harness2+0x472f98)
#2 0x4580e3 in fuzzer::Fuzzer::CrashCallback() (/home/presler/fuzzing/tinyxml/harness2+0x4580e3)
#3 0x7f07d48103bf (/lib/x86_64-linux-gnu/libpthread.so.0+0x153bf)
#4 0x7f07d462118a in __libc_signal_restore_set /build/glibc-eX1tMB/glibc-2.31/signal/../sysdeps/unix/sysv/linux/internal-signals.h:86:3
#5 0x7f07d462118a in raise /build/glibc-eX1tMB/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:48:3
#6 0x7f07d4600858 in abort /build/glibc-eX1tMB/glibc-2.31/stdlib/abort.c:79:7
#7 0x7f07d4600728 in __assert_fail_base /build/glibc-eX1tMB/glibc-2.31/assert/assert.c:92:3
#8 0x7f07d4611f35 in __assert_fail /build/glibc-eX1tMB/glibc-2.31/assert/assert.c:101:3
#9 0x558e38 in TiXmlBase::StringEqual(char const*, char const*, bool, TiXmlEncoding) /home/presler/fuzzing/tinyxml/tinyxmlparser.cpp:543:3
#10 0x55b25c in TiXmlDeclaration::Parse(char const*, TiXmlParsingData*, TiXmlEncoding) /home/presler/fuzzing/tinyxml/tinyxmlparser.cpp:1603:8
#11 0x55a4bc in TiXmlElement::ReadValue(char const*, TiXmlParsingData*, TiXmlEncoding) /home/presler/fuzzing/tinyxml/tinyxmlparser.cpp:1229:16
#12 0x559e3a in TiXmlElement::Parse(char const*, TiXmlParsingData*, TiXmlEncoding) /home/presler/fuzzing/tinyxml/tinyxmlparser.cpp:1109:8
#13 0x55949a in TiXmlDocument::Parse(char const*, TiXmlParsingData*, TiXmlEncoding) /home/presler/fuzzing/tinyxml/tinyxmlparser.cpp:759:14
#14 0x551699 in LLVMFuzzerTestOneInput /home/presler/fuzzing/tinyxml/harness2.cpp:17:9
#15 0x4597a1 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/presler/fuzzing/tinyxml/harness2+0x4597a1)
#16 0x444f12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/home/presler/fuzzing/tinyxml/harness2+0x444f12)
#17 0x44a9c6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/presler/fuzzing/tinyxml/harness2+0x44a9c6)
#18 0x473682 in main (/home/presler/fuzzing/tinyxml/harness2+0x473682)
#19 0x7f07d46020b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
#20 0x41f5dd in _start (/home/presler/fuzzing/tinyxml/harness2+0x41f5dd)
NOTE: libFuzzer has rudimentary signal handlers.
Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
Test case also was attached