Segmentation Fault on Single-Byte UTF-16 BOM Input
Summary
The ezxml library crashes with a segmentation fault when parsing XML files containing a single byte 0xFE. This occurs due to incomplete UTF-16 BOM (Byte Order Mark) validation that violates the XML standard.
Environment
- Library: ezxml v0.8.5
- Platform: x86_64-linux-gnu
- Compiler: GCC
Steps to Reproduce
-
Create a file with a single byte 0xFE:
printf '\xfe' > crash.xml
-
Parse the file with ezxmltest:
-
Observe the crash:
Segmentation fault (core dumped)
Expected Behavior
The library should either:
- Treat the incomplete BOM as invalid and return an error
- Fall back to UTF-8 encoding (default per XML standard)
- Provide a clear error message instead of crashing
Actual Behavior
The program crashes with a segmentation fault due to NULL pointer dereference at ezxml.c:481.
Root Cause Analysis
GDB Backtrace
#0 ezxml_parse_str (s=0x0, len=0) at ezxml.c:481
#1 ezxml_parse_fd (fd=3) at ezxml.c:641
#2 ezxml_parse_file (file=0x7fffffffdf7c "crash.xml") at ezxml.c:659
#3 main (argc=2, argv=0x7fffffffdc08) at ezxml.c:1008
Technical Details
The XML standard specifies that:
- UTF-16 Big Endian BOM:
0xFE 0xFF (2 bytes)
- UTF-16 Little Endian BOM:
0xFF 0xFE (2 bytes)
- Files without a complete BOM should be treated as UTF-8
However, the ezxml_str2utf8() function (line 427) only checks the first byte:
int b, be = (**s == '\xFE') ? 1 : (**s == '\xFF') ? 0 : -1;
Crash Mechanism
ezxml_str2utf8() misidentifies single byte 0xFE as UTF-16 BE BOM
- Sets
be = 1 (UTF-16 Big Endian mode)
- The conversion loop
for (sl = 2; sl < *len - 1; sl += 2) never executes because *len = 1
- Returns
realloc(u, *len = 0) which returns NULL on many systems
ezxml_parse_str() receives s = NULL, len = 0 but doesn't validate
- Line 481:
e = s[len - 1] attempts s[-1] access → Segmentation Fault
Proposed Fix
Option 1: Complete BOM Validation (Recommended)
char *ezxml_str2utf8(char **s, size_t *len)
{
char *u;
size_t l = 0, sl, max = *len;
long c, d;
int b, be = -1;
// UTF-16 BOM requires at least 2 bytes
if (*len >= 2) {
if ((*s)[0] == '\xFE' && (*s)[1] == '\xFF') {
be = 1; // UTF-16 Big Endian
}
else if ((*s)[0] == '\xFF' && (*s)[1] == '\xFE') {
be = 0; // UTF-16 Little Endian
}
}
if (be == -1) return NULL; // not UTF-16
}
Option 2: Add NULL Check in Parser
ezxml_t ezxml_parse_str(char *s, size_t len)
{
ezxml_root_t root = (ezxml_root_t)ezxml_new(NULL);
// ...
root->m = s;
if (! len) return ezxml_err(root, NULL, "root tag missing");
root->u = ezxml_str2utf8(&s, &len);
// Add NULL check
if (!s) {
return ezxml_err(root, NULL, "invalid or incomplete UTF-16 BOM");
}
root->e = (root->s = s) + len;
e = s[len - 1]; // now safe
// ...
}
Segmentation Fault on Single-Byte UTF-16 BOM Input
Summary
The ezxml library crashes with a segmentation fault when parsing XML files containing a single byte
0xFE. This occurs due to incomplete UTF-16 BOM (Byte Order Mark) validation that violates the XML standard.Environment
Steps to Reproduce
Create a file with a single byte
0xFE:Parse the file with ezxmltest:
Observe the crash:
Expected Behavior
The library should either:
Actual Behavior
The program crashes with a segmentation fault due to NULL pointer dereference at
ezxml.c:481.Root Cause Analysis
GDB Backtrace
Technical Details
The XML standard specifies that:
0xFE 0xFF(2 bytes)0xFF 0xFE(2 bytes)However, the
ezxml_str2utf8()function (line 427) only checks the first byte:Crash Mechanism
ezxml_str2utf8()misidentifies single byte0xFEas UTF-16 BE BOMbe = 1(UTF-16 Big Endian mode)for (sl = 2; sl < *len - 1; sl += 2)never executes because*len = 1realloc(u, *len = 0)which returnsNULLon many systemsezxml_parse_str()receivess = NULL,len = 0but doesn't validatee = s[len - 1]attemptss[-1]access → Segmentation FaultProposed Fix
Option 1: Complete BOM Validation (Recommended)
Option 2: Add NULL Check in Parser