Skip to content

Fix precondition violation in parse_key when parsing '[[[' table headers#301

Merged
marzer merged 2 commits into
marzer:masterfrom
gistrec:fix/parse-table-header-precondition
May 10, 2026
Merged

Fix precondition violation in parse_key when parsing '[[[' table headers#301
marzer merged 2 commits into
marzer:masterfrom
gistrec:fix/parse-table-header-precondition

Conversation

@gistrec
Copy link
Copy Markdown
Contributor

@gistrec gistrec commented May 9, 2026

Description of the bug

parse_table_header() can call parse_key() with an invalid starting character after consuming a table header prefix.

For example, with input like [[[1]]], the parser consumes the first [ and the second [ as an array-of-tables header, then enters parse_key() while *cp still points at the third [. That character is neither a bare-key character nor a string delimiter, so it violates this precondition in parse_key():

TOML_ASSERT_ASSUME(is_bare_key_character(*cp) || is_string_delimiter(*cp));

In debug builds this hits the assertion and aborts the process instead of returning a normal parse_error.

Reproduction

#include "toml++/toml.hpp"
int main()
{
    toml::parse("[[[1]]]");
}

With a debug clang build this currently fails with:

Assertion failed: (is_bare_key_character(*cp) || is_string_delimiter(*cp)),
function parse_key, file parser.inl

Similar small cases are [[[a]]], [[[]], and [[=.

Fix

Before calling parse_key(), parse_table_header() now checks that the next character is a valid key starter.
If it is not, the parser reports a normal parse_error instead of entering parse_key() with a broken precondition.

Tests

Added regression tests for malformed array-of-table headers such as:

  • [[[1]]]
  • [[[a]]]
  • [[[]]
  • [[=

Valid table headers and array-of-table headers still parse as before.

parse_table_header() consumes the leading '[' (and the second '[' for
array-of-tables headers) and then calls parse_key() unconditionally,
checking only for a closing ']'. When the next character is neither a
bare-key character nor a string delimiter (e.g. a third '[' as in the
input '[[[1]]]'), parse_key() is entered with its documented
precondition violated:

    TOML_ASSERT_ASSUME(is_bare_key_character(*cp) || is_string_delimiter(*cp));

In debug builds this aborts; under NDEBUG the macro expands to
__builtin_assume, so the violation is undefined behaviour.

Validate the key starter explicitly in parse_table_header() and raise
the usual parse_error instead. Add regression tests for the malformed
array-of-tables header cases and regenerate the single-header toml.hpp.
@gistrec
Copy link
Copy Markdown
Contributor Author

gistrec commented May 9, 2026

Write me if I should remove the comments from the code

@marzer
Copy link
Copy Markdown
Owner

marzer commented May 10, 2026

Write me if I should remove the comments from the code

Yes, please. These look like classic LLM comment vomit. Otherwise the fix is good 👍🏼

Copy link
Copy Markdown
Owner

@marzer marzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@marzer marzer merged commit e4bcc15 into marzer:master May 10, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants