mirror of
https://github.com/nlohmann/json.git
synced 2025-07-28 12:02:00 +03:00
🐛 fix assertion failure #2838
This commit is contained in:
@ -5371,8 +5371,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add element to array (move semantics)
|
// add element to array (move semantics)
|
||||||
|
const auto capacity = m_value.array->capacity();
|
||||||
m_value.array->push_back(std::move(val));
|
m_value.array->push_back(std::move(val));
|
||||||
set_parent(m_value.array->back());
|
if (capacity == m_value.array->capacity())
|
||||||
|
{
|
||||||
|
// capacity has not changed: updating parent of last element is sufficient
|
||||||
|
set_parent(m_value.array->back());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// capacity has changed: update all elements' parents
|
||||||
|
set_parents();
|
||||||
|
}
|
||||||
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
|
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5407,7 +5417,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add element to array
|
// add element to array
|
||||||
|
const auto capacity = m_value.array->capacity();
|
||||||
m_value.array->push_back(val);
|
m_value.array->push_back(val);
|
||||||
|
if (capacity == m_value.array->capacity())
|
||||||
|
{
|
||||||
|
// capacity has not changed: updating parent of last element is sufficient
|
||||||
|
set_parent(m_value.array->back());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// capacity has changed: update all elements' parents
|
||||||
|
set_parents();
|
||||||
|
}
|
||||||
set_parent(m_value.array->back());
|
set_parent(m_value.array->back());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5562,12 +5583,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add element to array (perfect forwarding)
|
// add element to array (perfect forwarding)
|
||||||
#ifdef JSON_HAS_CPP_17
|
const auto capacity = m_value.array->capacity();
|
||||||
return set_parent(m_value.array->emplace_back(std::forward<Args>(args)...));
|
|
||||||
#else
|
|
||||||
m_value.array->emplace_back(std::forward<Args>(args)...);
|
m_value.array->emplace_back(std::forward<Args>(args)...);
|
||||||
return set_parent(m_value.array->back());
|
|
||||||
#endif
|
if (capacity == m_value.array->capacity())
|
||||||
|
{
|
||||||
|
// capacity has not changed: updating parent of last element is sufficient
|
||||||
|
return set_parent(m_value.array->back());
|
||||||
|
}
|
||||||
|
|
||||||
|
// capacity has changed: update all elements' parents
|
||||||
|
set_parents();
|
||||||
|
return m_value.array->back();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -5630,12 +5657,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @note: This uses std::distance to support GCC 4.8,
|
/// @note: This uses std::distance to support GCC 4.8,
|
||||||
/// see https://github.com/nlohmann/json/pull/1257
|
/// see https://github.com/nlohmann/json/pull/1257
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
iterator insert_iterator(const_iterator pos, Args&& ... args)
|
iterator insert_iterator(const_iterator pos, typename iterator::difference_type cnt, Args&& ... args)
|
||||||
{
|
{
|
||||||
iterator result(this);
|
iterator result(this);
|
||||||
JSON_ASSERT(m_value.array != nullptr);
|
JSON_ASSERT(m_value.array != nullptr);
|
||||||
|
|
||||||
auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
|
auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
|
||||||
|
const auto capacity = m_value.array->capacity();
|
||||||
m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
|
m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
|
||||||
result.m_it.array_iterator = m_value.array->begin() + insert_pos;
|
result.m_it.array_iterator = m_value.array->begin() + insert_pos;
|
||||||
|
|
||||||
@ -5643,6 +5671,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
|
// result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
|
||||||
// but the return value of insert is missing in GCC 4.8, so it is written this way instead.
|
// but the return value of insert is missing in GCC 4.8, so it is written this way instead.
|
||||||
|
|
||||||
|
if (capacity == m_value.array->capacity())
|
||||||
|
{
|
||||||
|
// capacity has not changed: updating parent of inserted elements is sufficient
|
||||||
|
set_parents(result, cnt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// capacity has changed: update all elements' parents
|
||||||
|
set_parents();
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5680,7 +5719,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
return set_parents(insert_iterator(pos, val), static_cast<typename iterator::difference_type>(1));
|
return insert_iterator(pos, static_cast<typename iterator::difference_type>(1), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
||||||
@ -5731,7 +5770,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
return set_parents(insert_iterator(pos, cnt, val), static_cast<typename iterator::difference_type>(cnt));
|
return insert_iterator(pos, static_cast<typename iterator::difference_type>(cnt), cnt, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
||||||
@ -5793,7 +5832,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
return set_parents(insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator), std::distance(first, last));
|
return insert_iterator(pos, std::distance(first, last), first.m_it.array_iterator, last.m_it.array_iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -5835,7 +5874,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
return set_parents(insert_iterator(pos, ilist.begin(), ilist.end()), static_cast<typename iterator::difference_type>(ilist.size()));
|
return insert_iterator(pos, static_cast<typename iterator::difference_type>(ilist.size()), ilist.begin(), ilist.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -22406,8 +22406,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add element to array (move semantics)
|
// add element to array (move semantics)
|
||||||
|
const auto capacity = m_value.array->capacity();
|
||||||
m_value.array->push_back(std::move(val));
|
m_value.array->push_back(std::move(val));
|
||||||
set_parent(m_value.array->back());
|
if (capacity == m_value.array->capacity())
|
||||||
|
{
|
||||||
|
// capacity has not changed: updating parent of last element is sufficient
|
||||||
|
set_parent(m_value.array->back());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// capacity has changed: update all elements' parents
|
||||||
|
set_parents();
|
||||||
|
}
|
||||||
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
|
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22442,7 +22452,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add element to array
|
// add element to array
|
||||||
|
const auto capacity = m_value.array->capacity();
|
||||||
m_value.array->push_back(val);
|
m_value.array->push_back(val);
|
||||||
|
if (capacity == m_value.array->capacity())
|
||||||
|
{
|
||||||
|
// capacity has not changed: updating parent of last element is sufficient
|
||||||
|
set_parent(m_value.array->back());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// capacity has changed: update all elements' parents
|
||||||
|
set_parents();
|
||||||
|
}
|
||||||
set_parent(m_value.array->back());
|
set_parent(m_value.array->back());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22597,12 +22618,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add element to array (perfect forwarding)
|
// add element to array (perfect forwarding)
|
||||||
#ifdef JSON_HAS_CPP_17
|
const auto capacity = m_value.array->capacity();
|
||||||
return set_parent(m_value.array->emplace_back(std::forward<Args>(args)...));
|
|
||||||
#else
|
|
||||||
m_value.array->emplace_back(std::forward<Args>(args)...);
|
m_value.array->emplace_back(std::forward<Args>(args)...);
|
||||||
return set_parent(m_value.array->back());
|
|
||||||
#endif
|
if (capacity == m_value.array->capacity())
|
||||||
|
{
|
||||||
|
// capacity has not changed: updating parent of last element is sufficient
|
||||||
|
return set_parent(m_value.array->back());
|
||||||
|
}
|
||||||
|
|
||||||
|
// capacity has changed: update all elements' parents
|
||||||
|
set_parents();
|
||||||
|
return m_value.array->back();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -22665,12 +22692,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @note: This uses std::distance to support GCC 4.8,
|
/// @note: This uses std::distance to support GCC 4.8,
|
||||||
/// see https://github.com/nlohmann/json/pull/1257
|
/// see https://github.com/nlohmann/json/pull/1257
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
iterator insert_iterator(const_iterator pos, Args&& ... args)
|
iterator insert_iterator(const_iterator pos, typename iterator::difference_type cnt, Args&& ... args)
|
||||||
{
|
{
|
||||||
iterator result(this);
|
iterator result(this);
|
||||||
JSON_ASSERT(m_value.array != nullptr);
|
JSON_ASSERT(m_value.array != nullptr);
|
||||||
|
|
||||||
auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
|
auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
|
||||||
|
const auto capacity = m_value.array->capacity();
|
||||||
m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
|
m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
|
||||||
result.m_it.array_iterator = m_value.array->begin() + insert_pos;
|
result.m_it.array_iterator = m_value.array->begin() + insert_pos;
|
||||||
|
|
||||||
@ -22678,6 +22706,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
|
// result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
|
||||||
// but the return value of insert is missing in GCC 4.8, so it is written this way instead.
|
// but the return value of insert is missing in GCC 4.8, so it is written this way instead.
|
||||||
|
|
||||||
|
if (capacity == m_value.array->capacity())
|
||||||
|
{
|
||||||
|
// capacity has not changed: updating parent of inserted elements is sufficient
|
||||||
|
set_parents(result, cnt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// capacity has changed: update all elements' parents
|
||||||
|
set_parents();
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22715,7 +22754,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
return set_parents(insert_iterator(pos, val), static_cast<typename iterator::difference_type>(1));
|
return insert_iterator(pos, static_cast<typename iterator::difference_type>(1), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
||||||
@ -22766,7 +22805,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
return set_parents(insert_iterator(pos, cnt, val), static_cast<typename iterator::difference_type>(cnt));
|
return insert_iterator(pos, static_cast<typename iterator::difference_type>(cnt), cnt, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
|
||||||
@ -22828,7 +22867,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
return set_parents(insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator), std::distance(first, last));
|
return insert_iterator(pos, std::distance(first, last), first.m_it.array_iterator, last.m_it.array_iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -22870,7 +22909,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
return set_parents(insert_iterator(pos, ilist.begin(), ilist.end()), static_cast<typename iterator::difference_type>(ilist.size()));
|
return insert_iterator(pos, static_cast<typename iterator::difference_type>(ilist.size()), ilist.begin(), ilist.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -109,4 +109,61 @@ TEST_CASE("Better diagnostics")
|
|||||||
j["/foo"] = {1, 2, 3};
|
j["/foo"] = {1, 2, 3};
|
||||||
CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error);
|
CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Regression test for https://github.com/nlohmann/json/issues/2838")
|
||||||
|
{
|
||||||
|
// void push_back(basic_json&& val)
|
||||||
|
{
|
||||||
|
json j_arr = json::array();
|
||||||
|
j_arr.push_back(json::object());
|
||||||
|
j_arr.push_back(json::object());
|
||||||
|
json j_obj = json::object();
|
||||||
|
j_obj["key"] = j_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void push_back(const basic_json& val)
|
||||||
|
{
|
||||||
|
json j_arr = json::array();
|
||||||
|
auto object = json::object();
|
||||||
|
j_arr.push_back(object);
|
||||||
|
j_arr.push_back(object);
|
||||||
|
json j_obj = json::object();
|
||||||
|
j_obj["key"] = j_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reference emplace_back(Args&& ... args)
|
||||||
|
{
|
||||||
|
json j_arr = json::array();
|
||||||
|
j_arr.emplace_back(json::object());
|
||||||
|
j_arr.emplace_back(json::object());
|
||||||
|
json j_obj = json::object();
|
||||||
|
j_obj["key"] = j_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterator insert(const_iterator pos, const basic_json& val)
|
||||||
|
{
|
||||||
|
json j_arr = json::array();
|
||||||
|
j_arr.insert(j_arr.begin(), json::object());
|
||||||
|
j_arr.insert(j_arr.begin(), json::object());
|
||||||
|
json j_obj = json::object();
|
||||||
|
j_obj["key"] = j_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
|
||||||
|
{
|
||||||
|
json j_arr = json::array();
|
||||||
|
j_arr.insert(j_arr.begin(), 2, json::object());
|
||||||
|
json j_obj = json::object();
|
||||||
|
j_obj["key"] = j_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterator insert(const_iterator pos, const_iterator first, const_iterator last)
|
||||||
|
{
|
||||||
|
json j_arr = json::array();
|
||||||
|
json j_objects = {json::object(), json::object()};
|
||||||
|
j_arr.insert(j_arr.begin(), j_objects.begin(), j_objects.end());
|
||||||
|
json j_obj = json::object();
|
||||||
|
j_obj["key"] = j_arr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user