From f5a487d1b4ab20f8c08f73f3bbc343441dc77701 Mon Sep 17 00:00:00 2001 From: chenguoping Date: Mon, 13 Apr 2020 19:41:13 +0800 Subject: [PATCH 1/2] fix issue1982: contains() exceptions are incorrectly raised --- include/nlohmann/detail/json_pointer.hpp | 21 +++++++++++++++++++++ single_include/nlohmann/json.hpp | 21 +++++++++++++++++++++ test/src/unit-json_pointer.cpp | 21 +++++++++------------ 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 5e4c8a1f..41239600 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -678,6 +678,27 @@ class json_pointer // "-" always fails the range check return false; } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 and not (reference_token >= "0" and reference_token <= "9"))) + { + // invalid char + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) + { + if (JSON_HEDLEY_UNLIKELY(not (reference_token[0] > '0' and reference_token[0] <= '9'))) + { + // first char should be between '1' and '9' + return false; + } + for (std::size_t i = 1; i < reference_token.size(); i++) + { + if (JSON_HEDLEY_UNLIKELY(not (reference_token[i] >= '0' and reference_token[i] <= '9'))) + { + // other char should be between '0' and '9' + return false; + } + } + } const auto idx = static_cast(array_index(reference_token)); if (idx >= ptr->size()) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 15d069fc..9f3fe39d 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -11081,6 +11081,27 @@ class json_pointer // "-" always fails the range check return false; } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 and not (reference_token >= "0" and reference_token <= "9"))) + { + // invalid char + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) + { + if (JSON_HEDLEY_UNLIKELY(not (reference_token[0] > '0' and reference_token[0] <= '9'))) + { + // first char should be between '1' and '9' + return false; + } + for (std::size_t i = 1; i < reference_token.size(); i++) + { + if (JSON_HEDLEY_UNLIKELY(not (reference_token[i] >= '0' and reference_token[i] <= '9'))) + { + // other char should be between '0' and '9' + return false; + } + } + } const auto idx = static_cast(array_index(reference_token)); if (idx >= ptr->size()) diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index 1655a458..2cc9dac6 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -310,12 +310,11 @@ TEST_CASE("JSON pointers") CHECK_THROWS_AS(j_const.at("/01"_json_pointer), json::parse_error&); CHECK_THROWS_WITH(j_const.at("/01"_json_pointer), "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); - CHECK_THROWS_AS(j.contains("/01"_json_pointer), json::parse_error&); - CHECK_THROWS_WITH(j.contains("/01"_json_pointer), - "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); - CHECK_THROWS_AS(j_const.contains("/01"_json_pointer), json::parse_error&); - CHECK_THROWS_WITH(j_const.contains("/01"_json_pointer), - "[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'"); + + CHECK(not j.contains("/01"_json_pointer)); + CHECK(not j.contains("/01"_json_pointer)); + CHECK(not j_const.contains("/01"_json_pointer)); + CHECK(not j_const.contains("/01"_json_pointer)); // error with incorrect numbers CHECK_THROWS_AS(j["/one"_json_pointer] = 1, json::parse_error&); @@ -360,12 +359,10 @@ 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.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"); - CHECK_THROWS_AS(j_const.contains("/one"_json_pointer), json::parse_error&); - CHECK_THROWS_WITH(j_const.contains("/one"_json_pointer), - "[json.exception.parse_error.109] parse error: array index 'one' is not a number"); + CHECK(not j.contains("/one"_json_pointer)); + CHECK(not j.contains("/one"_json_pointer)); + CHECK(not j_const.contains("/one"_json_pointer)); + CHECK(not j_const.contains("/one"_json_pointer)); CHECK_THROWS_AS(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), json::parse_error&); CHECK_THROWS_WITH(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), From 8bfc692602ce25610b801e9cddfabe25d3450452 Mon Sep 17 00:00:00 2001 From: chenguoping Date: Mon, 20 Apr 2020 16:00:55 +0800 Subject: [PATCH 2/2] update condition --- include/nlohmann/detail/json_pointer.hpp | 6 +++--- single_include/nlohmann/json.hpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 41239600..421c5ec8 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -678,21 +678,21 @@ class json_pointer // "-" always fails the range check return false; } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 and not (reference_token >= "0" and reference_token <= "9"))) + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 and not ("0" <= reference_token and reference_token <= "9"))) { // invalid char return false; } if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) { - if (JSON_HEDLEY_UNLIKELY(not (reference_token[0] > '0' and reference_token[0] <= '9'))) + if (JSON_HEDLEY_UNLIKELY(not ('1' <= reference_token[0] and reference_token[0] <= '9'))) { // first char should be between '1' and '9' return false; } for (std::size_t i = 1; i < reference_token.size(); i++) { - if (JSON_HEDLEY_UNLIKELY(not (reference_token[i] >= '0' and reference_token[i] <= '9'))) + if (JSON_HEDLEY_UNLIKELY(not ('0' <= reference_token[i] and reference_token[i] <= '9'))) { // other char should be between '0' and '9' return false; diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 9f3fe39d..6ffd6d0d 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -11081,21 +11081,21 @@ class json_pointer // "-" always fails the range check return false; } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 and not (reference_token >= "0" and reference_token <= "9"))) + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 and not ("0" <= reference_token and reference_token <= "9"))) { // invalid char return false; } if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) { - if (JSON_HEDLEY_UNLIKELY(not (reference_token[0] > '0' and reference_token[0] <= '9'))) + if (JSON_HEDLEY_UNLIKELY(not ('1' <= reference_token[0] and reference_token[0] <= '9'))) { // first char should be between '1' and '9' return false; } for (std::size_t i = 1; i < reference_token.size(); i++) { - if (JSON_HEDLEY_UNLIKELY(not (reference_token[i] >= '0' and reference_token[i] <= '9'))) + if (JSON_HEDLEY_UNLIKELY(not ('0' <= reference_token[i] and reference_token[i] <= '9'))) { // other char should be between '0' and '9' return false;