Description
There are two logic issues in toml_parse:
Case 1: Quoted key is not handled, causing an infinite loop - CRITICAL
toml_parse only treats keys beginning with isalnum, _, or - as valid keys
Quoted keys are valid in TOML, but toml_parse doesn’t handle them and gets stuck in an infinite loop.
Case 2: Early returns due to error do not free the allocated table, causing memory leaks
When toml_parse_table() or toml_parse_key_value() returns an error, toml_parse simply returns NULL without freeing the table allocated at the beginning:
TomlTable* toml_parse(TomlParser *self)
{
TomlTable *table = NULL;
table = toml_table_new();
while (self->ptr < self->end) {
char ch = *self->ptr;
while (self->ptr < self->end && isspace(ch)) {
toml_move_next(self);
ch = *self->ptr;
}
if (ch == '#') {
do {
toml_move_next(self);
ch = *self->ptr;
} while (self->ptr < self->end && ch != '\n');
toml_move_next(self);
} else if (ch == '[') {
toml_move_next(self);
if (toml_parse_table(self, table) != 0)
return NULL; // should free 'table'
} else if (isalnum(ch) || ch == '_' || ch == '-') { // should not check '-', but should check quotes: '\"', '\''
if (toml_parse_key_value(self, table) != 0)
return NULL; // should free 'table'
} else if (ch == ' ' || ch == '\t' || ch == '\r') {
do {
toml_move_next(self);
ch = *self->ptr;
} while (ch == ' ' || ch == '\t' || ch == '\r');
} else if (ch == '\n') {
toml_move_next(self);
}
}
return table;
}
Reproduction
- create file named:
repro_logic_bug with one of following contents:
case 1 (infinite loop):
or
case 2 (memory leak):
-table_not_freed = "true"
- run the parser
toml_load_filename("./repro_logic_bug");
Actual behavior
Case 1: Parser enters an infinite loop and never terminates.
Case 2: toml_load_filename returns NULL without freeing allocated table.
example output:
=================================================================
==21457==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 24 byte(s) in 1 object(s) allocated from:
#0 0x55d1fd5f8902 in malloc
#1 0x55d1fd683460 in toml_default_malloc src/toml.c:18:15
#2 0x55d1fd636c45 in toml_malloc src/toml.c:54:12
#3 0x55d1fd63c639 in toml_table_new src/toml.c:270:23
#4 0x55d1fd67f4e3 in toml_parse src/toml.c:1653:13
#5 0x55d1fd6815bf in toml_load_nstr_filename src/toml.c:1698:13
#6 0x55d1fd682f7d in toml_load_file_filename src/toml.c:1743:13
#7 0x55d1fd6832e3 in toml_load_filename src/toml.c:1772:13
#8 0x55d1fd6366ff in main fuzz_libtoml.c:13:24
#9 0x7fdf69d301c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#10 0x7fdf69d3028a in __libc_start_main csu/../csu/libc-start.c:360:3
#11 0x55d1fd55a404 in _start
SUMMARY: AddressSanitizer: 24 byte(s) leaked in 1 allocation(s).
Expected behavior
Case 1: toml_load_filename should parse quoted key normally
Case 2: toml_load_filename should free table and return NULL
Fix suggestion
Description
There are two logic issues in
toml_parse:Case 1: Quoted key is not handled, causing an infinite loop - CRITICAL
toml_parseonly treats keys beginning withisalnum,_, or-as valid keysQuoted keys are valid in TOML, but
toml_parsedoesn’t handle them and gets stuck in an infinite loop.Case 2: Early returns due to error do not free the allocated table, causing memory leaks
When
toml_parse_table()ortoml_parse_key_value()returns an error, toml_parse simply returns NULL without freeing the table allocated at the beginning:Reproduction
repro_logic_bugwith one of following contents:case 1 (infinite loop):
or
case 2 (memory leak):
Actual behavior
Case 1: Parser enters an infinite loop and never terminates.
Case 2:
toml_load_filenamereturns NULL without freeing allocated table.example output:
Expected behavior
Case 1:
toml_load_filenameshould parse quoted key normallyCase 2:
toml_load_filenameshould free table and return NULLFix suggestion
Detect quoted keys (
"or') in the key-value branch.Free allocated table before early return of NULL