Merge pull request #2203 from t-b/use-unsigned-indizies-for-array-index-in-json-pointer
Use unsigned indizies for array index in json pointer
This commit is contained in:
commit
4bfe4add20
4 changed files with 73 additions and 34 deletions
|
|
@ -3,6 +3,7 @@
|
|||
#include <algorithm> // all_of
|
||||
#include <cassert> // assert
|
||||
#include <cctype> // isdigit
|
||||
#include <limits> // max
|
||||
#include <numeric> // accumulate
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
|
|
@ -325,10 +326,15 @@ class json_pointer
|
|||
|
||||
@return integer representation of @a s
|
||||
|
||||
@throw parse_error.106 if an array index begins with '0'
|
||||
@throw parse_error.109 if an array index begins not with a digit
|
||||
@throw out_of_range.404 if string @a s could not be converted to an integer
|
||||
@throw out_of_range.410 if an array index exceeds size_type
|
||||
*/
|
||||
static int array_index(const std::string& s)
|
||||
static typename BasicJsonType::size_type array_index(const std::string& s)
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
|
||||
// error condition (cf. RFC 6901, Sect. 4)
|
||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and s[0] == '0'))
|
||||
{
|
||||
|
|
@ -344,10 +350,10 @@ class json_pointer
|
|||
}
|
||||
|
||||
std::size_t processed_chars = 0;
|
||||
int res = 0;
|
||||
unsigned long long res = 0;
|
||||
JSON_TRY
|
||||
{
|
||||
res = std::stoi(s, &processed_chars);
|
||||
res = std::stoull(s, &processed_chars);
|
||||
}
|
||||
JSON_CATCH(std::out_of_range&)
|
||||
{
|
||||
|
|
@ -360,7 +366,14 @@ class json_pointer
|
|||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
|
||||
}
|
||||
|
||||
return res;
|
||||
// only triggered on special platforms (like 32bit), see also
|
||||
// https://github.com/nlohmann/json/pull/2203
|
||||
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
return static_cast<size_type>(res);
|
||||
}
|
||||
|
||||
json_pointer top() const
|
||||
|
|
@ -419,7 +432,7 @@ class json_pointer
|
|||
case detail::value_t::array:
|
||||
{
|
||||
// create an entry in the array
|
||||
result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
|
||||
result = &result->operator[](array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -497,8 +510,7 @@ class json_pointer
|
|||
else
|
||||
{
|
||||
// convert array index to number; unchecked access
|
||||
ptr = &ptr->operator[](
|
||||
static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->operator[](array_index(reference_token));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -542,7 +554,7 @@ class json_pointer
|
|||
}
|
||||
|
||||
// note: at performs range check
|
||||
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->at(array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -592,8 +604,7 @@ class json_pointer
|
|||
}
|
||||
|
||||
// use unchecked array access
|
||||
ptr = &ptr->operator[](
|
||||
static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->operator[](array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -636,7 +647,7 @@ class json_pointer
|
|||
}
|
||||
|
||||
// note: at performs range check
|
||||
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->at(array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -700,7 +711,7 @@ class json_pointer
|
|||
}
|
||||
}
|
||||
|
||||
const auto idx = static_cast<size_type>(array_index(reference_token));
|
||||
const auto idx = array_index(reference_token);
|
||||
if (idx >= ptr->size())
|
||||
{
|
||||
// index out of range
|
||||
|
|
|
|||
|
|
@ -8207,7 +8207,7 @@ class basic_json
|
|||
else
|
||||
{
|
||||
const auto idx = json_pointer::array_index(last_path);
|
||||
if (JSON_HEDLEY_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
|
||||
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
|
||||
{
|
||||
// avoid undefined behavior
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
|
||||
|
|
@ -8250,7 +8250,7 @@ class basic_json
|
|||
else if (parent.is_array())
|
||||
{
|
||||
// note erase performs range check
|
||||
parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
|
||||
parent.erase(json_pointer::array_index(last_path));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue