Require the found key to equal the looked-up key when comparing objects (#5720)

For an object type whose comparator treats unequal keys as equivalent
(for example a std::map with a case-insensitive comparator),
compare_iteratively() looked up a mismatched left key in the right
object with find(), which uses the object's own comparator, and
accepted whatever entry it found without checking that the keys are
actually equal. A case-insensitive comparator then found "KEY" for
"key", so two objects nested past the recursion bound (or at every
depth with JSON_NO_THREAD_LOCAL) could compare equal even though the
object type's own operator== - and basic_json itself, below the bound
- consider them different.

Accept the found entry only if its key equals (not just compares
equivalent to) the looked-up key.

Fixes #5655.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-30 20:07:56 +02:00
committed by GitHub
parent 66877675b1
commit 2ea6d8c127
3 changed files with 52 additions and 2 deletions
+3 -1
View File
@@ -1505,7 +1505,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const auto found = (!Ordered && !detail::is_ordered_map<object_t>::value)
? rhs_object->find(current.lhs_object_it->first)
: rhs_object->cend();
if (found == rhs_object->cend())
// the object's comparator may find an entry whose
// key is only equivalent, not equal, to this one
if (found == rhs_object->cend() || !(found->first == current.lhs_object_it->first))
{
return key_result;
}