mirror of
https://github.com/nlohmann/json.git
synced 2026-10-01 12:10:32 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
404427ab72 | ||
|
|
57890cebad |
@@ -679,19 +679,29 @@ class json_pointer
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// may throw parse_error.106/109 for a malformed index; an
|
// tokens that array_index() rejects with parse_error.106/109
|
||||||
// index that is syntactically valid but cannot be
|
// are passed on to it; all other tokens that it would reject
|
||||||
// represented (out_of_range.404/410) is treated like an
|
// with out_of_range.404/410 are detected here, so that this
|
||||||
// out-of-range index below
|
// also works without exceptions
|
||||||
typename BasicJsonType::size_type idx{};
|
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 && !(reference_token[0] >= '1' && reference_token[0] <= '9')))
|
||||||
JSON_TRY
|
|
||||||
{
|
{
|
||||||
idx = array_index<BasicJsonType>(reference_token);
|
static_cast<void>(array_index<BasicJsonType>(reference_token)); // throws parse_error.106/109
|
||||||
}
|
}
|
||||||
JSON_INTERNAL_CATCH (detail::out_of_range&)
|
if (JSON_HEDLEY_UNLIKELY(reference_token.empty() || !std::all_of(reference_token.begin(), reference_token.end(), [](const char c)
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
})))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
errno = 0; // strtoull() does not reset errno on success
|
||||||
|
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
||||||
|
const unsigned long long magnitude = std::strtoull(reference_token.data(), &p_end, 10); // NOLINT(runtime/int)
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE || magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const auto idx = static_cast<typename BasicJsonType::size_type>(magnitude);
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(idx >= ptr->m_data.m_value.array->size()))
|
if (JSON_HEDLEY_UNLIKELY(idx >= ptr->m_data.m_value.array->size()))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20291,19 +20291,29 @@ class json_pointer
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// may throw parse_error.106/109 for a malformed index; an
|
// tokens that array_index() rejects with parse_error.106/109
|
||||||
// index that is syntactically valid but cannot be
|
// are passed on to it; all other tokens that it would reject
|
||||||
// represented (out_of_range.404/410) is treated like an
|
// with out_of_range.404/410 are detected here, so that this
|
||||||
// out-of-range index below
|
// also works without exceptions
|
||||||
typename BasicJsonType::size_type idx{};
|
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 && !(reference_token[0] >= '1' && reference_token[0] <= '9')))
|
||||||
JSON_TRY
|
|
||||||
{
|
{
|
||||||
idx = array_index<BasicJsonType>(reference_token);
|
static_cast<void>(array_index<BasicJsonType>(reference_token)); // throws parse_error.106/109
|
||||||
}
|
}
|
||||||
JSON_INTERNAL_CATCH (detail::out_of_range&)
|
if (JSON_HEDLEY_UNLIKELY(reference_token.empty() || !std::all_of(reference_token.begin(), reference_token.end(), [](const char c)
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
})))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
errno = 0; // strtoull() does not reset errno on success
|
||||||
|
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
||||||
|
const unsigned long long magnitude = std::strtoull(reference_token.data(), &p_end, 10); // NOLINT(runtime/int)
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE || magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const auto idx = static_cast<typename BasicJsonType::size_type>(magnitude);
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(idx >= ptr->m_data.m_value.array->size()))
|
if (JSON_HEDLEY_UNLIKELY(idx >= ptr->m_data.m_value.array->size()))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,6 +47,21 @@ TEST_CASE("Tests with disabled exceptions")
|
|||||||
delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory)
|
delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("issue #5672 - value(json_pointer, default) must not abort for array tokens that are not a valid index")
|
||||||
|
{
|
||||||
|
const json j = {1, 2, 3};
|
||||||
|
|
||||||
|
// a syntactically valid index that is out of range for this array
|
||||||
|
CHECK(j.value("/7"_json_pointer, 42) == 42);
|
||||||
|
// a reference token that is not a number at all
|
||||||
|
CHECK(j.value("/1a"_json_pointer, 42) == 42);
|
||||||
|
// the empty reference token (JSON pointer "/")
|
||||||
|
CHECK(j.value("/"_json_pointer, 42) == 42);
|
||||||
|
// an index whose magnitude does not fit into size_type
|
||||||
|
CHECK(j.value("/99999999999999999999999"_json_pointer, 42) == 42);
|
||||||
|
CHECK(j.value("/18446744073709551615"_json_pointer, 42) == 42);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("growing an ordered_json object")
|
SECTION("growing an ordered_json object")
|
||||||
{
|
{
|
||||||
auto j = nlohmann::ordered_json::object();
|
auto j = nlohmann::ordered_json::object();
|
||||||
|
|||||||
@@ -516,6 +516,21 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j
|
|||||||
CHECK(j_array.value("/-"_json_pointer, 42) == 42);
|
CHECK(j_array.value("/-"_json_pointer, 42) == 42);
|
||||||
CHECK(j_array_const.value("/-"_json_pointer, 42) == 42);
|
CHECK(j_array_const.value("/-"_json_pointer, 42) == 42);
|
||||||
|
|
||||||
|
// Test an index with a non-digit after a valid leading digit; this is
|
||||||
|
// out_of_range (not parse_error) and must not throw (see #5672)
|
||||||
|
CHECK(j_array.value("/1a"_json_pointer, 42) == 42);
|
||||||
|
CHECK(j_array_const.value("/1a"_json_pointer, 42) == 42);
|
||||||
|
|
||||||
|
// Test the empty reference token (JSON pointer "/"); see #5672
|
||||||
|
CHECK(j_array.value("/"_json_pointer, 42) == 42);
|
||||||
|
CHECK(j_array_const.value("/"_json_pointer, 42) == 42);
|
||||||
|
|
||||||
|
// Test an index whose magnitude does not fit into size_type (see #5672)
|
||||||
|
CHECK(j_array.value("/99999999999999999999999"_json_pointer, 42) == 42);
|
||||||
|
CHECK(j_array_const.value("/99999999999999999999999"_json_pointer, 42) == 42);
|
||||||
|
CHECK(j_array.value("/18446744073709551615"_json_pointer, 42) == 42);
|
||||||
|
CHECK(j_array_const.value("/18446744073709551615"_json_pointer, 42) == 42);
|
||||||
|
|
||||||
#if !defined(JSON_NOEXCEPTION)
|
#if !defined(JSON_NOEXCEPTION)
|
||||||
// Test malformed index (non-numeric) throws parse_error
|
// Test malformed index (non-numeric) throws parse_error
|
||||||
CHECK_THROWS_WITH_AS(j_array.value("/foo"_json_pointer, 1), "[json.exception.parse_error.109] parse error: array index 'foo' is not a number", typename Json::parse_error&);
|
CHECK_THROWS_WITH_AS(j_array.value("/foo"_json_pointer, 1), "[json.exception.parse_error.109] parse error: array index 'foo' is not a number", typename Json::parse_error&);
|
||||||
|
|||||||
Reference in New Issue
Block a user