Description
toml_parse_basic_string can lead to a use-after-free (UAF) in two scenarios:
- invalid escape character
result is freed, but loop isn't broken causing UAF on result
- unterminated string
result is freed, but the pointer is still returned
TomlString* toml_parse_basic_string(TomlParser *self)
{
TomlString *result = toml_string_new();
...
while (self->ptr < self->end && *self->ptr != '\"' && *self->ptr != '\n') {
char ch1 = *self->ptr;
...
} else {
toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid escape charactor"); // typo
toml_string_free(result);
// case 1: `result` is freed, but loop not broken
}
...
}
if (self->ptr >= self->end || *self->ptr != '\"' || *self->ptr == '\n') {
toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unterminated basic string",
self->filename, self->lineno, self->colno);
toml_string_free(result);
// case 2: freed pointer is returned
}
toml_move_next(self);
return result;
}
Reproduction
- create file named: "repro_uaf" with following contents:
[table]
key = "value"
"key2
= "use after free"
- run the parser
toml_load_filename("./repro_uaf")
Actual behavior
-
toml_parse_basic_string returns freed pointer.
-
when executed with sanitized binary, UAF is detected (built with: afl-clang-fast -O0 -g -fsanitize=address,undefined).
output:
=================================================================
==135590==ERROR: AddressSanitizer: heap-use-after-free on address 0x5030000001f8 at pc 0x55f7423ad95c bp 0x7fffaab9b720 sp 0x7fffaab9b718
READ of size 8 at 0x5030000001f8 thread T0
#0 0x55f7423ad95b in toml_string_equals src/toml.c:251:29
#1 0x55f7423b1040 in toml_table_set_by_string src/toml.c:303:13
#2 0x55f7423e50b6 in toml_parse_key_value src/toml.c:1257:9
#3 0x55f7423f12be in toml_parse_table src/toml.c:1638:5
#4 0x55f7423f2933 in toml_parse src/toml.c:1671:17
#5 0x55f7423f35bf in toml_load_nstr_filename src/toml.c:1698:13
#6 0x55f7423f4f7d in toml_load_file_filename src/toml.c:1743:13
#7 0x55f7423f52e3 in toml_load_filename src/toml.c:1772:13
0x5030000001f8 is located 8 bytes inside of 24-byte region [0x5030000001f0,0x503000000208)
freed by thread T0 here:
#0 0x55f74236a65a in free
#1 0x55f7423ad2ce in toml_string_free src/toml.c:236:9
#2 0x55f7423c3f91 in toml_parse_basic_string src/toml.c:813:9
#3 0x55f7423e21e1 in toml_parse_key_value src/toml.c:1200:19
#4 0x55f7423f12be in toml_parse_table src/toml.c:1638:5
#5 0x55f7423f2933 in toml_parse src/toml.c:1671:17
#6 0x55f7423f35bf in toml_load_nstr_filename src/toml.c:1698:13
#7 0x55f7423f4f7d in toml_load_file_filename src/toml.c:1743:13
#8 0x55f7423f52e3 in toml_load_filename src/toml.c:1772:13
previously allocated by thread T0 here:
#0 0x55f74236a902 in malloc
#1 0x55f7423f5460 in toml_default_malloc src/toml.c:18:15
#2 0x55f7423a8c45 in toml_malloc src/toml.c:54:12
#3 0x55f7423aa5a9 in toml_string_new src/toml.c:177:24
#4 0x55f7423c1bab in toml_parse_basic_string src/toml.c:754:26
#5 0x55f7423e21e1 in toml_parse_key_value src/toml.c:1200:19
#6 0x55f7423f12be in toml_parse_table src/toml.c:1638:5
#7 0x55f7423f2933 in toml_parse src/toml.c:1671:17
#8 0x55f7423f35bf in toml_load_nstr_filename src/toml.c:1698:13
#9 0x55f7423f4f7d in toml_load_file_filename src/toml.c:1743:13
#10 0x55f7423f52e3 in toml_load_filename src/toml.c:1772:13
SUMMARY: AddressSanitizer: heap-use-after-free src/toml.c:251:29 in toml_string_equals
- with a normal binary, the returned structure from
toml_load_filename is not NULL and contains a dangling pointer.
Expected behavior
Fix suggestion
- immediately return
NULL after each toml_string_free(result);
Description
toml_parse_basic_stringcan lead to a use-after-free (UAF) in two scenarios:resultis freed, but loop isn't broken causing UAF onresultresultis freed, but the pointer is still returnedReproduction
Actual behavior
toml_parse_basic_stringreturns freed pointer.when executed with sanitized binary, UAF is detected (built with:
afl-clang-fast -O0 -g -fsanitize=address,undefined).output:
toml_load_filenameis not NULL and contains a dangling pointer.Expected behavior
toml_parse_basic_stringshould return NULL on invalid input.toml_load_filenameshould propagate the NULL to indicate parsing failure.Fix suggestion
NULLafter eachtoml_string_free(result);