From f5a487d1b4ab20f8c08f73f3bbc343441dc77701 Mon Sep 17 00:00:00 2001 From: chenguoping Date: Mon, 13 Apr 2020 19:41:13 +0800 Subject: [PATCH] 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(),