diff --git a/CHANGELOG.md b/CHANGELOG.md index 5efcb93..f42e2bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,18 @@ template: #### Removals: #### Build system: +

+ --> +## Unreleased + +#### Fixes: +- fixed null pointer dereference in parser when exceptions are disabled (#169) (@ncaklovic) + +

+ + ## v3.2.0 [Released](https://github.com/marzer/tomlplusplus/releases/tag/v3.2.0) 2022-08-29 diff --git a/include/toml++/impl/array.inl b/include/toml++/impl/array.inl index a8a4ac1..b35ca85 100644 --- a/include/toml++/impl/array.inl +++ b/include/toml++/impl/array.inl @@ -130,6 +130,7 @@ TOML_NAMESPACE_START TOML_EXTERNAL_LINKAGE void array::insert_at_back(impl::node_ptr && elem) { + TOML_ASSERT(elem); elems_.push_back(std::move(elem)); } diff --git a/include/toml++/impl/parser.inl b/include/toml++/impl/parser.inl index be4d496..ad4aeaa 100644 --- a/include/toml++/impl/parser.inl +++ b/include/toml++/impl/parser.inl @@ -3556,13 +3556,13 @@ TOML_IMPL_NAMESPACE_START node_ptr arr_ptr{ new array{} }; array& arr = arr_ptr->ref_cast(); - enum TOML_CLOSED_ENUM parse_elem : int + enum class TOML_CLOSED_ENUM parse_type : int { none, comma, val }; - parse_elem prev = none; + parse_type prev = parse_type::none; while (!is_error()) { @@ -3573,9 +3573,9 @@ TOML_IMPL_NAMESPACE_START // commas - only legal after a value if (*cp == U',') { - if (prev == val) + if (prev == parse_type::val) { - prev = comma; + prev = parse_type::comma; advance_and_return_if_error_or_eof({}); continue; } @@ -3592,15 +3592,19 @@ TOML_IMPL_NAMESPACE_START // must be a value else { - if (prev == val) + if (prev == parse_type::val) { set_error_and_return_default("expected comma or closing ']', saw '"sv, to_sv(*cp), "'"sv); continue; } - prev = val; + prev = parse_type::val; + + auto val = parse_value(); + return_if_error({}); + if (!arr.capacity()) arr.reserve(4u); - arr.emplace_back(parse_value()); + arr.emplace_back(std::move(val)); } } @@ -3624,13 +3628,13 @@ TOML_IMPL_NAMESPACE_START tbl.is_inline(true); table_vector_scope table_scope{ open_inline_tables, tbl }; - enum TOML_CLOSED_ENUM parse_elem : int + enum class TOML_CLOSED_ENUM parse_type : int { none, comma, kvp }; - parse_elem prev = none; + parse_type prev = parse_type::none; while (!is_error()) { if constexpr (TOML_LANG_UNRELEASED) // toml/issues/516 (newlines/trailing commas in inline tables) @@ -3649,9 +3653,9 @@ TOML_IMPL_NAMESPACE_START // commas - only legal after a key-value pair if (*cp == U',') { - if (prev == kvp) + if (prev == parse_type::kvp) { - prev = comma; + prev = parse_type::comma; advance_and_return_if_error_or_eof({}); } else @@ -3663,7 +3667,7 @@ TOML_IMPL_NAMESPACE_START { if constexpr (!TOML_LANG_UNRELEASED) // toml/issues/516 (newlines/trailing commas in inline tables) { - if (prev == comma) + if (prev == parse_type::comma) { set_error_and_return_default("expected key-value pair, saw closing '}' (dangling comma)"sv); continue; @@ -3676,11 +3680,11 @@ TOML_IMPL_NAMESPACE_START // key-value pair else if (is_string_delimiter(*cp) || is_bare_key_character(*cp)) { - if (prev == kvp) + if (prev == parse_type::kvp) set_error_and_return_default("expected comma or closing '}', saw '"sv, to_sv(*cp), "'"sv); else { - prev = kvp; + prev = parse_type::kvp; parse_key_value_pair_and_insert(&tbl); } } diff --git a/tests/user_feedback.cpp b/tests/user_feedback.cpp index c4b97df..7fa1d21 100644 --- a/tests/user_feedback.cpp +++ b/tests/user_feedback.cpp @@ -367,4 +367,12 @@ b = [] foo = 1 )"sv); } + + SECTION("tomlplusplus/issues/169") // https://github.com/marzer/tomlplusplus/issues/169 + { + parsing_should_fail(FILE_LINE_ARGS, R"( + [a] + b = [c"] + )"sv); + } } diff --git a/toml.hpp b/toml.hpp index 293ea79..7245d73 100644 --- a/toml.hpp +++ b/toml.hpp @@ -11311,6 +11311,7 @@ TOML_NAMESPACE_START TOML_EXTERNAL_LINKAGE void array::insert_at_back(impl::node_ptr && elem) { + TOML_ASSERT(elem); elems_.push_back(std::move(elem)); } @@ -15512,13 +15513,13 @@ TOML_IMPL_NAMESPACE_START node_ptr arr_ptr{ new array{} }; array& arr = arr_ptr->ref_cast(); - enum TOML_CLOSED_ENUM parse_elem : int + enum class TOML_CLOSED_ENUM parse_type : int { none, comma, val }; - parse_elem prev = none; + parse_type prev = parse_type::none; while (!is_error()) { @@ -15529,9 +15530,9 @@ TOML_IMPL_NAMESPACE_START // commas - only legal after a value if (*cp == U',') { - if (prev == val) + if (prev == parse_type::val) { - prev = comma; + prev = parse_type::comma; advance_and_return_if_error_or_eof({}); continue; } @@ -15548,15 +15549,19 @@ TOML_IMPL_NAMESPACE_START // must be a value else { - if (prev == val) + if (prev == parse_type::val) { set_error_and_return_default("expected comma or closing ']', saw '"sv, to_sv(*cp), "'"sv); continue; } - prev = val; + prev = parse_type::val; + + auto val = parse_value(); + return_if_error({}); + if (!arr.capacity()) arr.reserve(4u); - arr.emplace_back(parse_value()); + arr.emplace_back(std::move(val)); } } @@ -15580,13 +15585,13 @@ TOML_IMPL_NAMESPACE_START tbl.is_inline(true); table_vector_scope table_scope{ open_inline_tables, tbl }; - enum TOML_CLOSED_ENUM parse_elem : int + enum class TOML_CLOSED_ENUM parse_type : int { none, comma, kvp }; - parse_elem prev = none; + parse_type prev = parse_type::none; while (!is_error()) { if constexpr (TOML_LANG_UNRELEASED) // toml/issues/516 (newlines/trailing commas in inline tables) @@ -15605,9 +15610,9 @@ TOML_IMPL_NAMESPACE_START // commas - only legal after a key-value pair if (*cp == U',') { - if (prev == kvp) + if (prev == parse_type::kvp) { - prev = comma; + prev = parse_type::comma; advance_and_return_if_error_or_eof({}); } else @@ -15619,7 +15624,7 @@ TOML_IMPL_NAMESPACE_START { if constexpr (!TOML_LANG_UNRELEASED) // toml/issues/516 (newlines/trailing commas in inline tables) { - if (prev == comma) + if (prev == parse_type::comma) { set_error_and_return_default("expected key-value pair, saw closing '}' (dangling comma)"sv); continue; @@ -15632,11 +15637,11 @@ TOML_IMPL_NAMESPACE_START // key-value pair else if (is_string_delimiter(*cp) || is_bare_key_character(*cp)) { - if (prev == kvp) + if (prev == parse_type::kvp) set_error_and_return_default("expected comma or closing '}', saw '"sv, to_sv(*cp), "'"sv); else { - prev = kvp; + prev = parse_type::kvp; parse_key_value_pair_and_insert(&tbl); } }