diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 053be8f744..c683d2522f 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -3695,15 +3695,25 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (idx >= m_value.array->size()) { #if JSON_DIAGNOSTICS - // remember array size before resizing - const auto previous_size = m_value.array->size(); + // remember array size & capacity before resizing + const auto old_size = m_value.array->size(); + const auto old_capacity = m_value.array->capacity(); #endif m_value.array->resize(idx + 1); #if JSON_DIAGNOSTICS - // set parent for values added above - set_parents(begin() + static_cast(previous_size), static_cast(idx + 1 - previous_size)); + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + } + else + { + // set parent for values added above + set_parents(begin() + static_cast(old_size), static_cast(idx + 1 - old_size)); + } #endif + assert_invariant(); } return m_value.array->operator[](idx); diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 9c27aabbe5..5899a79450 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -21101,15 +21101,25 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (idx >= m_value.array->size()) { #if JSON_DIAGNOSTICS - // remember array size before resizing - const auto previous_size = m_value.array->size(); + // remember array size & capacity before resizing + const auto old_size = m_value.array->size(); + const auto old_capacity = m_value.array->capacity(); #endif m_value.array->resize(idx + 1); #if JSON_DIAGNOSTICS - // set parent for values added above - set_parents(begin() + static_cast(previous_size), static_cast(idx + 1 - previous_size)); + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + } + else + { + // set parent for values added above + set_parents(begin() + static_cast(old_size), static_cast(idx + 1 - old_size)); + } #endif + assert_invariant(); } return m_value.array->operator[](idx); diff --git a/test/src/unit-diagnostics.cpp b/test/src/unit-diagnostics.cpp index 8e4f2ffc36..4feee29c87 100644 --- a/test/src/unit-diagnostics.cpp +++ b/test/src/unit-diagnostics.cpp @@ -234,4 +234,21 @@ TEST_CASE("Better diagnostics") root.push_back(lower); } } + + SECTION("Regression test for https://github.com/nlohmann/json/issues/3032") + { + // reference operator[](size_type idx) + { + json j_arr = json::array(); + j_arr[0] = 0; + j_arr[1] = 1; + j_arr[2] = 2; + j_arr[3] = 3; + j_arr[4] = 4; + j_arr[5] = 5; + j_arr[6] = 6; + j_arr[7] = 7; + json j_arr_copy = j_arr; + } + } }