MessagePack reader: reject an array/map 32 length equal to SIZE_MAX

On a platform with a 32-bit std::size_t, an array 32 or map 32 length of
0xFFFFFFFF equals unknown_size(), so start_array()/start_object() were
told the size was unknown and skipped the max_size() check. Route both
through the CBOR length check, renamed get_container_size(), which
already rejects that value.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-11-02 18:25:06 +01:00
1 parent db73a6044f
commit da6d21ae24
4 files changed
+39 -15

No files matched your search

@@ -1024,7 +1024,7 @@ class binary_reader
{
std::uint64_t len{};
std::size_t size{};
return get_cbor_argument(len) && get_cbor_container_size(len, size, "array") && enter_cbor_array(size);
return get_cbor_argument(len) && get_container_size(len, size, "array") && enter_cbor_array(size);
}
case 0x9F: // array (indefinite length)
@@ -1064,7 +1064,7 @@ class binary_reader
{
std::uint64_t len{};
std::size_t size{};
return get_cbor_argument(len) && get_cbor_container_size(len, size, "map") && enter_object(size);
return get_cbor_argument(len) && get_container_size(len, size, "map") && enter_object(size);
}
case 0xBF: // map (indefinite length)
@@ -1700,7 +1700,7 @@ class binary_reader
}
/*!
@brief narrow a definite CBOR array/map length to std::size_t
@brief narrow a definite CBOR or MessagePack array/map length to std::size_t
A definite length is rejected if it does not fit in std::size_t or if it
equals detail::unknown_size(), which is reserved to mark an indefinite-
@@ -1713,7 +1713,7 @@ class binary_reader
@param[in] context "array" or "map", for the error message
@return whether the length is usable
*/
bool get_cbor_container_size(const std::uint64_t len, std::size_t& result, const char* context)
bool get_container_size(const std::uint64_t len, std::size_t& result, const char* context)
{
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(len) || len == detail::unknown_size()))
{
@@ -2305,7 +2305,8 @@ class binary_reader
case 0xDD: // array 32
{
std::uint32_t len{};
return get_number(len) && enter_msgpack_array(conditional_static_cast<std::size_t>(len));
std::size_t size{};
return get_number(len) && get_container_size(len, size, "array") && enter_msgpack_array(size);
}
case 0xDE: // map 16
@@ -2317,7 +2318,8 @@ class binary_reader
case 0xDF: // map 32
{
std::uint32_t len{};
return get_number(len) && enter_object(conditional_static_cast<std::size_t>(len));
std::size_t size{};
return get_number(len) && get_container_size(len, size, "map") && enter_object(size);
}
// negative fixint
@@ -3128,7 +3130,7 @@ class binary_reader
A count equal to npos is rejected: npos marks a container whose count is
not known, so a count of that value would be read as "no count" (compare
get_cbor_container_size()). No container can hold that many elements.
get_container_size()). No container can hold that many elements.
@param[in] count the count read from the input
@param[out] result set to @a count unless it is rejected