Merge pull request #1990 from dota17/json_pointer

catch exceptions for json_pointer : ..../+99
pull/2054/head
Niels Lohmann 2020-04-13 13:29:33 +02:00 committed by GitHub
commit b7be613b6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 98 additions and 192 deletions

View File

@ -329,8 +329,30 @@ class json_pointer
*/
static int array_index(const std::string& s)
{
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and s[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + s +
"' must not begin with '0'"));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and not (s[0] >= '1' and s[0] <= '9')))
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
}
std::size_t processed_chars = 0;
const int res = std::stoi(s, &processed_chars);
int res = 0;
JSON_TRY
{
res = std::stoi(s, &processed_chars);
}
JSON_CATCH(std::out_of_range&)
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
}
// check if the string was completely read
if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
@ -397,14 +419,7 @@ class json_pointer
case detail::value_t::array:
{
// create an entry in the array
JSON_TRY
{
result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
break;
}
@ -474,14 +489,6 @@ class json_pointer
case detail::value_t::array:
{
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
}
if (reference_token == "-")
{
// explicitly treat "-" as index beyond the end
@ -490,15 +497,8 @@ class json_pointer
else
{
// convert array index to number; unchecked access
JSON_TRY
{
ptr = &ptr->operator[](
static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->operator[](
static_cast<size_type>(array_index(reference_token)));
}
break;
}
@ -541,23 +541,8 @@ class json_pointer
") is out of range"));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
}
// note: at performs range check
JSON_TRY
{
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
break;
}
@ -606,24 +591,9 @@ class json_pointer
") is out of range"));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
}
// use unchecked array access
JSON_TRY
{
ptr = &ptr->operator[](
static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->operator[](
static_cast<size_type>(array_index(reference_token)));
break;
}
@ -665,23 +635,8 @@ class json_pointer
") is out of range"));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
}
// note: at performs range check
JSON_TRY
{
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
break;
}
@ -724,30 +679,14 @@ class json_pointer
return false;
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
const auto idx = static_cast<size_type>(array_index(reference_token));
if (idx >= ptr->size())
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
// index out of range
return false;
}
JSON_TRY
{
const auto idx = static_cast<size_type>(array_index(reference_token));
if (idx >= ptr->size())
{
// index out of range
return false;
}
ptr = &ptr->operator[](idx);
break;
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->operator[](idx);
break;
}

View File

@ -10732,8 +10732,30 @@ class json_pointer
*/
static int array_index(const std::string& s)
{
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and s[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + s +
"' must not begin with '0'"));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and not (s[0] >= '1' and s[0] <= '9')))
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
}
std::size_t processed_chars = 0;
const int res = std::stoi(s, &processed_chars);
int res = 0;
JSON_TRY
{
res = std::stoi(s, &processed_chars);
}
JSON_CATCH(std::out_of_range&)
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
}
// check if the string was completely read
if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
@ -10800,14 +10822,7 @@ class json_pointer
case detail::value_t::array:
{
// create an entry in the array
JSON_TRY
{
result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
break;
}
@ -10877,14 +10892,6 @@ class json_pointer
case detail::value_t::array:
{
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
}
if (reference_token == "-")
{
// explicitly treat "-" as index beyond the end
@ -10893,15 +10900,8 @@ class json_pointer
else
{
// convert array index to number; unchecked access
JSON_TRY
{
ptr = &ptr->operator[](
static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->operator[](
static_cast<size_type>(array_index(reference_token)));
}
break;
}
@ -10944,23 +10944,8 @@ class json_pointer
") is out of range"));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
}
// note: at performs range check
JSON_TRY
{
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
break;
}
@ -11009,24 +10994,9 @@ class json_pointer
") is out of range"));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
}
// use unchecked array access
JSON_TRY
{
ptr = &ptr->operator[](
static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->operator[](
static_cast<size_type>(array_index(reference_token)));
break;
}
@ -11068,23 +11038,8 @@ class json_pointer
") is out of range"));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
}
// note: at performs range check
JSON_TRY
{
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
break;
}
@ -11127,30 +11082,14 @@ class json_pointer
return false;
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
const auto idx = static_cast<size_type>(array_index(reference_token));
if (idx >= ptr->size())
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
// index out of range
return false;
}
JSON_TRY
{
const auto idx = static_cast<size_type>(array_index(reference_token));
if (idx >= ptr->size())
{
// index out of range
return false;
}
ptr = &ptr->operator[](idx);
break;
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
ptr = &ptr->operator[](idx);
break;
}

View File

@ -332,6 +332,34 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_WITH(j_const.at("/one"_json_pointer) == 1,
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
CHECK_THROWS_AS(j["/+1"_json_pointer] = 1, json::parse_error&);
CHECK_THROWS_WITH(j["/+1"_json_pointer] = 1,
"[json.exception.parse_error.109] parse error: array index '+1' is not a number");
CHECK_THROWS_AS(j_const["/+1"_json_pointer] == 1, json::parse_error&);
CHECK_THROWS_WITH(j_const["/+1"_json_pointer] == 1,
"[json.exception.parse_error.109] parse error: array index '+1' is not a number");
CHECK_THROWS_AS(j["/1+1"_json_pointer] = 1, json::out_of_range&);
CHECK_THROWS_WITH(j["/1+1"_json_pointer] = 1,
"[json.exception.out_of_range.404] unresolved reference token '1+1'");
CHECK_THROWS_AS(j_const["/1+1"_json_pointer] == 1, json::out_of_range&);
CHECK_THROWS_WITH(j_const["/1+1"_json_pointer] == 1,
"[json.exception.out_of_range.404] unresolved reference token '1+1'");
CHECK_THROWS_AS(j["/111111111111111111111111"_json_pointer] = 1, json::out_of_range&);
CHECK_THROWS_WITH(j["/111111111111111111111111"_json_pointer] = 1,
"[json.exception.out_of_range.404] unresolved reference token '111111111111111111111111'");
CHECK_THROWS_AS(j_const["/111111111111111111111111"_json_pointer] == 1, json::out_of_range&);
CHECK_THROWS_WITH(j_const["/111111111111111111111111"_json_pointer] == 1,
"[json.exception.out_of_range.404] unresolved reference token '111111111111111111111111'");
CHECK_THROWS_AS(j.at("/one"_json_pointer) = 1, json::parse_error&);
CHECK_THROWS_WITH(j.at("/one"_json_pointer) = 1,
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
CHECK_THROWS_AS(j_const.at("/one"_json_pointer) == 1, json::parse_error&);
CHECK_THROWS_WITH(j_const.at("/one"_json_pointer) == 1,
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
CHECK_THROWS_AS(j.contains("/one"_json_pointer), json::parse_error&);
CHECK_THROWS_WITH(j.contains("/one"_json_pointer),
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");