Function ezxml_decode() while parsing crafted XML file performs incorrect memory handling leading to heap buffer overread while running strchr() starting with pointer after NULL char finishing processed string.
For provided XML file following actions occur:
in line ezxml.c:197 variables has following values: l = 132, d = 60, r = 0x611000009f1e, m = 0x611000009f1e and strlen(r) is 26 bytes
so 132 bytes long buffer is allocated and 27 bytes (string r + NULL value) are copied starting from ptr r
in line ezxml.c:198 strchr is started at index r+60, so after NULL finishing string r
If uninitialized part of buffer and next memory blocks do not contain NULL values strchr function goes after heap area leading to segmentation fault
ASAN report (segmentation fault occurs also without ASAN):
=================================================================
==23242==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60d00000cff4 at pc 0x7f309124b2bb bp 0x7fffba60e810 sp 0x7fffba60dfb8
READ of size 73 at 0x60d00000cff4 thread T0
0 0x7f309124b2ba in strchr (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x712ba)
1 0x405454 in ezxml_decode ezxml_0.8.6/ezxml.c:198
2 0x405dfb in ezxml_char_content ezxml_0.8.6/ezxml.c:242
3 0x413820 in ezxml_parse_str ezxml_0.8.6/ezxml.c:591
4 0x4168a2 in ezxml_parse_fd ezxml_0.8.6/ezxml.c:641
5 0x4168a2 in ezxml_parse_file ezxml_0.8.6/ezxml.c:659
6 0x4018e8 in main ezxml_0.8.6/test_ezxml.c:113
7 0x7f3090e3082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
8 0x4019a8 in _start (ezxml_0.8.6/test_ezxml_asan.exe+0x4019a8)
0x60d00000cff4 is located 0 bytes to the right of 132-byte region [0x60d00000cf70,0x60d00000cff4)
allocated by thread T0 here:
0 0x7f3091272602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
1 0x405924 in ezxml_decode ezxml_0.8.6/ezxml.c:197
SUMMARY: AddressSanitizer: heap-buffer-overflow ??:0 strchr
Shadow bytes around the buggy address:
0x0c1a7fff99a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1a7fff99b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1a7fff99c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1a7fff99d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1a7fff99e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa 00 00
=>0x0c1a7fff99f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[04]fa
0x0c1a7fff9a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1a7fff9a10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1a7fff9a20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1a7fff9a30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1a7fff9a40: 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
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
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
==23242==ABORTING
Reproduction:
Sample XML file leading to crash:
crash_002_heap_buf_over_ezxml_decode.xml
Code snippet for reproduction:
ezxml_t result = ezxml_parse_file("crash_002_heap_buf_over_ezxml_decode.xml");