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);
}
}