Reject integral keys for contains(), find(), and count() at compile time (#5705)

j.contains(0), j.find(0), and j.count(0) used to compile: the literal 0 is
a null pointer constant, so it converts to a null const char*, and the
overloads taking const typename object_t::key_type& accepted it by
constructing a std::string from that null pointer, which is undefined
behavior (a crash with both libc++ and libstdc++). value(0, default_value)
had the same problem in C++11, where the object comparator is not
transparent.

Add deleted overloads for integral arguments to contains(), find()
(const and non-const), count(), and value() so that these calls are
compile errors in every supported language mode instead of crashing.
Calls with string, string_view, json_pointer, and size-typed element
access (at(), operator[](), erase()) are unaffected.

Fixes #5657.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-30 20:07:45 +02:00
committed by GitHub
parent 5bd766aa50
commit 6ae17630a4
7 changed files with 140 additions and 3 deletions
+14
View File
@@ -2980,6 +2980,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
string_t, typename std::decay<ValueType>::type >;
public:
// an integer literal 0 would otherwise convert to a null const char* and from there to key_type
template<typename T, typename ValueType, detail::enable_if_t<std::is_integral<T>::value, int> = 0>
ValueType value(T, ValueType&&) const = delete;
/// @brief access specified object element with default value
/// @sa https://json.nlohmann.me/api/basic_json/value/
template < class ValueType, detail::enable_if_t <
@@ -3414,6 +3418,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @name lookup
/// @{
// an integer literal 0 would otherwise convert to a null const char* and from there to key_type
template<typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0>
iterator find(T) = delete;
template<typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0>
const_iterator find(T) const = delete;
template<typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0>
size_type count(T) const = delete;
template<typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0>
bool contains(T) const = delete;
/// @brief find an element in a JSON object
/// @sa https://json.nlohmann.me/api/basic_json/find/
iterator find(const typename object_t::key_type& key)