Skip to content

UAF in toml_parse_basic_string when invalid strings are given #15

Description

@jidnjs

Description

toml_parse_basic_string can lead to a use-after-free (UAF) in two scenarios:

  1. invalid escape character

result is freed, but loop isn't broken causing UAF on result

  1. 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

  1. create file named: "repro_uaf" with following contents:
[table]
key = "value"
"key2
 = "use after free"
  1. 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

  • toml_parse_basic_string should return NULL on invalid input.

  • toml_load_filename should propagate the NULL to indicate parsing failure.

Fix suggestion

  • immediately return NULL after each toml_string_free(result);

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions