From 38de588582eb1b2892a4b0cdb124bae2c23ba156 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 5 Sep 2026 16:42:38 +0200 Subject: [PATCH] Reject array insert(pos, first, last) iterators not pointing into an array The array-range insert() overload checked that pos fits the current value and that first/last share the same owning value, but never verified that value is itself an array. Passing iterators from an object, a primitive, or null handed value-initialized (singular) std::vector iterators straight to array_t::insert(), which is undefined behavior. Add the missing is_array() check, mirroring the equivalent check already present in the object-range insert() overload. Signed-off-by: Niels Lohmann --- docs/mkdocs/docs/api/basic_json/insert.md | 2 ++ include/nlohmann/json.hpp | 6 ++++++ single_include/nlohmann/json.hpp | 6 ++++++ tests/src/unit-modifiers.cpp | 14 ++++++++++++++ 4 files changed, 28 insertions(+) diff --git a/docs/mkdocs/docs/api/basic_json/insert.md b/docs/mkdocs/docs/api/basic_json/insert.md index 14d5823c1..fcb1e6e44 100644 --- a/docs/mkdocs/docs/api/basic_json/insert.md +++ b/docs/mkdocs/docs/api/basic_json/insert.md @@ -88,6 +88,8 @@ Strong exception safety: if an exception occurs, the original value stays intact do not belong to the same JSON value; example: `"iterators do not fit"` - Throws [`invalid_iterator.211`](../../home/exceptions.md#jsonexceptioninvalid_iterator211) if `first` or `last` are iterators into container for which insert is called; example: `"passed iterators may not belong to container"` + - Throws [`invalid_iterator.202`](../../home/exceptions.md#jsonexceptioninvalid_iterator202) if `first` or `last` + do not point to an array; example: `"iterators first and last must point to arrays"` 4. The function can throw the following exceptions: - Throws [`type_error.309`](../../home/exceptions.md#jsonexceptiontype_error309) if called on JSON values other than arrays; example: `"cannot use insert() with string"` diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 38090da22..c8fe2caae 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -3425,6 +3425,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this)); } + // passed iterators must belong to arrays + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_array())) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to arrays", this)); + } + // insert to array and return iterator return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 817da77d4..4a8b7282a 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -24923,6 +24923,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this)); } + // passed iterators must belong to arrays + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_array())) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to arrays", this)); + } + // insert to array and return iterator return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); } diff --git a/tests/src/unit-modifiers.cpp b/tests/src/unit-modifiers.cpp index de14b3f70..369162772 100644 --- a/tests/src/unit-modifiers.cpp +++ b/tests/src/unit-modifiers.cpp @@ -641,6 +641,20 @@ TEST_CASE("modifiers") CHECK_THROWS_WITH_AS(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()), "[json.exception.invalid_iterator.210] iterators do not fit", json::invalid_iterator&); } + + SECTION("iterators not pointing into an array") + { + json j_object2 = {{"k", 1}, {"l", 2}}; + json j_primitive = 5; + json j_null; + + CHECK_THROWS_WITH_AS(j_array.insert(j_array.begin(), j_object2.begin(), j_object2.end()), "[json.exception.invalid_iterator.202] iterators first and last must point to arrays", + json::invalid_iterator&); + CHECK_THROWS_WITH_AS(j_array.insert(j_array.begin(), j_primitive.begin(), j_primitive.end()), "[json.exception.invalid_iterator.202] iterators first and last must point to arrays", + json::invalid_iterator&); + CHECK_THROWS_WITH_AS(j_array.insert(j_array.begin(), j_null.begin(), j_null.end()), "[json.exception.invalid_iterator.202] iterators first and last must point to arrays", + json::invalid_iterator&); + } } SECTION("range for object")