Throw type_error.313 when an unflatten key is a prefix of an earlier key

With an object type that keeps the insertion order (ordered_json), a key
such as "/a" can come after "/a/b". The final assignment then replaced the
object built for "/a/b" without an error, so {"/a/b":2,"/a":1} gave
{"a":1}. json never saw this because std::map visits the shorter key first.

Throw type_error.313 if the target of the final assignment is no longer
null, as json does for the same members. A null value keeps the container,
so {"/a/b":2,"/a":null} gives {"a":{"b":2}} for both object types.

Fixes #6105.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
diff --git a/docs/mkdocs/docs/api/basic_json/unflatten.md b/docs/mkdocs/docs/api/basic_json/unflatten.md
index 8b9f2cb..6bc9b66 100644
--- a/docs/mkdocs/docs/api/basic_json/unflatten.md
+++ b/docs/mkdocs/docs/api/basic_json/unflatten.md
@@ -26,7 +26,8 @@
 - Throws [`type_error.314`](../../home/exceptions.md#jsonexceptiontype_error314) if value is not an object
 - Throws [`type_error.315`](../../home/exceptions.md#jsonexceptiontype_error315) if object values are not primitive
 - Throws [`type_error.313`](../../home/exceptions.md#jsonexceptiontype_error313) if a key (JSON pointer) leads to a
-  conflicting nesting; example: `"invalid value to unflatten"`
+  conflicting nesting, for example if a key with a value other than `#!json null` is a prefix of another key (as `/a`
+  and `/a/b`), in whichever order the keys come; example: `"invalid value to unflatten"`
 - Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in a key begins
   with '0'; example: `"array index '01' must not begin with '0'"`
 - Throws [`parse_error.107`](../../home/exceptions.md#jsonexceptionparse_error107) if a key is not empty and does not
@@ -90,3 +91,6 @@
 - Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of
   [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) for a one-character array index that is
   not a digit (e.g., `/x`) in version 3.13.0, as it already did for longer ones.
+- Throws [`type_error.313`](../../home/exceptions.md#jsonexceptiontype_error313) for a key that is a prefix of an
+  earlier key in version 3.13.0; before, an object type that keeps the insertion order (such as
+  [`ordered_json`](../ordered_json.md)) silently replaced the nested value.
diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp
index 784414a..36f8148 100644
--- a/include/nlohmann/detail/json_pointer.hpp
+++ b/include/nlohmann/detail/json_pointer.hpp
@@ -2455,6 +2455,19 @@
                 pos = end;
             }
 
+            if (JSON_HEDLEY_UNLIKELY(!current->is_null()))
+            {
+                // the key is a prefix of an earlier key (only possible if the
+                // object type does not sort its keys), so the value is the
+                // array or object built for that key: a null leaves it as it
+                // is (as when the shorter key comes first), any other value
+                // conflicts with it
+                if (element.second.is_null())
+                {
+                    continue;
+                }
+                JSON_THROW(detail::type_error::create(detail::exception_id::unflatten_invalid_value, "invalid value to unflatten", &result));
+            }
             *current = element.second;
         }
 
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 4aeb641..07ba204 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -28742,6 +28742,19 @@
                 pos = end;
             }
 
+            if (JSON_HEDLEY_UNLIKELY(!current->is_null()))
+            {
+                // the key is a prefix of an earlier key (only possible if the
+                // object type does not sort its keys), so the value is the
+                // array or object built for that key: a null leaves it as it
+                // is (as when the shorter key comes first), any other value
+                // conflicts with it
+                if (element.second.is_null())
+                {
+                    continue;
+                }
+                JSON_THROW(detail::type_error::create(detail::exception_id::unflatten_invalid_value, "invalid value to unflatten", &result));
+            }
             *current = element.second;
         }
 
diff --git a/tests/src/unit-json_pointer.cpp b/tests/src/unit-json_pointer.cpp
index 5029f91..9f0c9fb 100644
--- a/tests/src/unit-json_pointer.cpp
+++ b/tests/src/unit-json_pointer.cpp
@@ -1241,6 +1241,34 @@
     }
 
 #if !defined(JSON_NOEXCEPTION)
+    SECTION("unflatten with a key that is a prefix of an earlier key")
+    {
+        // json visits the shorter key first; ordered_json may see it last
+        CHECK_THROWS_WITH_AS(nlohmann::ordered_json::parse(R"({"/a/b":2,"/a":1})").unflatten(),
+                             "[json.exception.type_error.313] invalid value to unflatten", nlohmann::ordered_json::type_error&);
+        CHECK_THROWS_WITH_AS(nlohmann::ordered_json::parse(R"({"/a/0/b":1,"/a/0":2})").unflatten(),
+                             "[json.exception.type_error.313] invalid value to unflatten", nlohmann::ordered_json::type_error&);
+        CHECK_THROWS_WITH_AS(nlohmann::ordered_json::parse(R"({"/x":1,"":2})").unflatten(),
+                             "[json.exception.type_error.313] invalid value to unflatten", nlohmann::ordered_json::type_error&);
+
+        // the same members in the other order
+        CHECK_THROWS_WITH_AS(nlohmann::ordered_json::parse(R"({"/a":1,"/a/b":2})").unflatten(),
+                             "[json.exception.type_error.313] invalid value to unflatten", nlohmann::ordered_json::type_error&);
+        CHECK_THROWS_WITH_AS(json::parse(R"({"/a/b":2,"/a":1})").unflatten(),
+                             "[json.exception.type_error.313] invalid value to unflatten", json::type_error&);
+    }
+#endif
+
+    SECTION("unflatten with a null at a key that is a prefix of another key")
+    {
+        // the null keeps the container, whichever key comes first
+        CHECK(nlohmann::ordered_json::parse(R"({"/a/b":2,"/a":null})").unflatten() == nlohmann::ordered_json::parse(R"({"a":{"b":2}})"));
+        CHECK(nlohmann::ordered_json::parse(R"({"/a":null,"/a/b":2})").unflatten() == nlohmann::ordered_json::parse(R"({"a":{"b":2}})"));
+        CHECK(nlohmann::ordered_json::parse(R"({"/a/0":1,"/a":null})").unflatten() == nlohmann::ordered_json::parse(R"({"a":[1]})"));
+        CHECK(json::parse(R"({"/a/b":2,"/a":null})").unflatten() == json::parse(R"({"a":{"b":2}})"));
+    }
+
+#if !defined(JSON_NOEXCEPTION)
     SECTION("an object with the key \"0\" next to a non-index key does not round-trip")
     {
         // the third documented case in which j != j.flatten().unflatten()