From bfc003cadf5c024b09f8538ba95d0d7bc9960ffd Mon Sep 17 00:00:00 2001
From: chenguoping <chenguopingdota@163.com>
Date: Tue, 17 Mar 2020 20:49:28 +0800
Subject: [PATCH 1/4] catch exceptions for json_point : /xx/+99

---
 include/nlohmann/detail/json_pointer.hpp | 54 ++++++------------------
 single_include/nlohmann/json.hpp         | 54 ++++++------------------
 2 files changed, 28 insertions(+), 80 deletions(-)

diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp
index 87af3423..c8fd2825 100644
--- a/include/nlohmann/detail/json_pointer.hpp
+++ b/include/nlohmann/detail/json_pointer.hpp
@@ -329,6 +329,20 @@ 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 & Sect. 7)
+        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);
 
@@ -474,14 +488,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
@@ -541,14 +547,6 @@ 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
                     {
@@ -606,14 +604,6 @@ 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
                     {
@@ -665,14 +655,6 @@ 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
                     {
@@ -724,14 +706,6 @@ 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'))
-                    {
-                        JSON_THROW(detail::parse_error::create(106, 0,
-                                                               "array index '" + reference_token +
-                                                               "' must not begin with '0'"));
-                    }
-
                     JSON_TRY
                     {
                         const auto idx = static_cast<size_type>(array_index(reference_token));
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 68916fa0..ca3e8171 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -10403,6 +10403,20 @@ 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 & Sect. 7)
+        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);
 
@@ -10548,14 +10562,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
@@ -10615,14 +10621,6 @@ 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
                     {
@@ -10680,14 +10678,6 @@ 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
                     {
@@ -10739,14 +10729,6 @@ 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
                     {
@@ -10798,14 +10780,6 @@ 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'))
-                    {
-                        JSON_THROW(detail::parse_error::create(106, 0,
-                                                               "array index '" + reference_token +
-                                                               "' must not begin with '0'"));
-                    }
-
                     JSON_TRY
                     {
                         const auto idx = static_cast<size_type>(array_index(reference_token));

From dcd3a6c62bf3bb6355faf17afc24374e077f6f20 Mon Sep 17 00:00:00 2001
From: chenguoping <chenguopingdota@163.com>
Date: Mon, 23 Mar 2020 17:24:47 +0800
Subject: [PATCH 2/4] move the catch of std::invalid_argument into
 array_index()

---
 include/nlohmann/detail/json_pointer.hpp | 79 +++++++-----------------
 single_include/nlohmann/json.hpp         | 79 +++++++-----------------
 2 files changed, 44 insertions(+), 114 deletions(-)

diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp
index c8fd2825..0acf924e 100644
--- a/include/nlohmann/detail/json_pointer.hpp
+++ b/include/nlohmann/detail/json_pointer.hpp
@@ -344,7 +344,15 @@ class json_pointer
         }
 
         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::invalid_argument&)
+        {
+            JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
+        }
 
         // check if the string was completely read
         if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
@@ -411,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;
                 }
 
@@ -496,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;
                 }
@@ -548,14 +542,7 @@ class json_pointer
                     }
 
                     // 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;
                 }
 
@@ -605,15 +592,8 @@ class json_pointer
                     }
 
                     // 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;
                 }
 
@@ -656,14 +636,7 @@ class json_pointer
                     }
 
                     // 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;
                 }
 
@@ -706,22 +679,14 @@ class json_pointer
                         return false;
                     }
 
-                    JSON_TRY
+                    const auto idx = static_cast<size_type>(array_index(reference_token));
+                    if (idx >= ptr->size())
                     {
-                        const auto idx = static_cast<size_type>(array_index(reference_token));
-                        if (idx >= ptr->size())
-                        {
-                            // index out of range
-                            return false;
-                        }
+                        // 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;
                 }
 
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index ca3e8171..5c93426e 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -10418,7 +10418,15 @@ class json_pointer
         }
 
         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::invalid_argument&)
+        {
+            JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
+        }
 
         // check if the string was completely read
         if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
@@ -10485,14 +10493,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;
                 }
 
@@ -10570,15 +10571,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;
                 }
@@ -10622,14 +10616,7 @@ class json_pointer
                     }
 
                     // 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;
                 }
 
@@ -10679,15 +10666,8 @@ class json_pointer
                     }
 
                     // 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;
                 }
 
@@ -10730,14 +10710,7 @@ class json_pointer
                     }
 
                     // 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;
                 }
 
@@ -10780,22 +10753,14 @@ class json_pointer
                         return false;
                     }
 
-                    JSON_TRY
+                    const auto idx = static_cast<size_type>(array_index(reference_token));
+                    if (idx >= ptr->size())
                     {
-                        const auto idx = static_cast<size_type>(array_index(reference_token));
-                        if (idx >= ptr->size())
-                        {
-                            // index out of range
-                            return false;
-                        }
+                        // 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;
                 }
 

From e07686f0c72fd7a13ec1b8e3a13aa0b2d2f592c8 Mon Sep 17 00:00:00 2001
From: chenguoping <chenguopingdota@163.com>
Date: Wed, 25 Mar 2020 15:56:45 +0800
Subject: [PATCH 3/4] update array_index() and add testcases

---
 include/nlohmann/detail/json_pointer.hpp |  4 ++--
 single_include/nlohmann/json.hpp         |  4 ++--
 test/src/unit-json_pointer.cpp           | 28 ++++++++++++++++++++++++
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp
index 0acf924e..ebf3ca8a 100644
--- a/include/nlohmann/detail/json_pointer.hpp
+++ b/include/nlohmann/detail/json_pointer.hpp
@@ -349,9 +349,9 @@ class json_pointer
         {
             res = std::stoi(s, &processed_chars);
         }
-        JSON_CATCH(std::invalid_argument&)
+        JSON_CATCH(std::out_of_range&)
         {
-            JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
+            JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
         }
 
         // check if the string was completely read
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 5c93426e..686cd52c 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -10423,9 +10423,9 @@ class json_pointer
         {
             res = std::stoi(s, &processed_chars);
         }
-        JSON_CATCH(std::invalid_argument&)
+        JSON_CATCH(std::out_of_range&)
         {
-            JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
+            JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
         }
 
         // check if the string was completely read
diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp
index 3cfd8dad..1655a458 100644
--- a/test/src/unit-json_pointer.cpp
+++ b/test/src/unit-json_pointer.cpp
@@ -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");

From 34cf7b7a48317573bcd119effbefe647f10cfd5e Mon Sep 17 00:00:00 2001
From: chenguoping <chenguopingdota@163.com>
Date: Tue, 7 Apr 2020 10:00:21 +0800
Subject: [PATCH 4/4] just restart ci

---
 include/nlohmann/detail/json_pointer.hpp | 2 +-
 single_include/nlohmann/json.hpp         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp
index ebf3ca8a..6bdcedd5 100644
--- a/include/nlohmann/detail/json_pointer.hpp
+++ b/include/nlohmann/detail/json_pointer.hpp
@@ -337,7 +337,7 @@ class json_pointer
                                                    "' must not begin with '0'"));
         }
 
-        // error condition (cf. RFC 6901, Sect. 4 & Sect. 7)
+        // 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"));
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 686cd52c..57a697fa 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -10411,7 +10411,7 @@ class json_pointer
                                                    "' must not begin with '0'"));
         }
 
-        // error condition (cf. RFC 6901, Sect. 4 & Sect. 7)
+        // 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"));