]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Bring some bugfixes from upstream (dropbox/json11).
authorMiod Vallat <miod.vallat@powerdns.com>
Fri, 17 Oct 2025 14:52:36 +0000 (16:52 +0200)
committerMiod Vallat <miod.vallat@powerdns.com>
Fri, 17 Oct 2025 14:52:36 +0000 (16:52 +0200)
- change Json map/vector conversions to invoke begin() directly instead of
  using key_type/value_type/mapped_type, to prevent false positives with
  std::optional, which has a value_type member type, but is not a container
  (ec4e45219af1d7cde3d58b49ed762376fccf1ace)

- make has_shape() return true for NUL type only if element actually exists
  (e2e3a11e99672b018e0e0657867e6a3439e180cf)

- improve handling of errors in comments
  (3bafee93e6d587d5bc6ef362c3e4457688e0ed5b)

- make operator== and operator< faster by checking for node identity
  (dabb88e83ebd6d5ef765864ec6d77bb4451c115e,
   42e6e71abb460e06c83a8f17c02e9bdf7959d2e7)

Signed-off-by: Miod Vallat <miod.vallat@powerdns.com>
ext/json11/json11.cpp
ext/json11/json11.hpp

index 2a7890a6cce249f46646b0655b1348532b9159a3..020ed5a545a48f2d83a3d42806bf3570fc42ff24 100644 (file)
@@ -302,6 +302,8 @@ const Json & JsonArray::operator[] (size_t i) const {
  */
 
 bool Json::operator== (const Json &other) const {
+    if (m_ptr == other.m_ptr)
+        return true;
     if (m_ptr->type() != other.m_ptr->type())
         return false;
 
@@ -309,6 +311,8 @@ bool Json::operator== (const Json &other) const {
 }
 
 bool Json::operator< (const Json &other) const {
+    if (m_ptr == other.m_ptr)
+        return false;
     if (m_ptr->type() != other.m_ptr->type())
         return m_ptr->type() < other.m_ptr->type();
 
@@ -386,16 +390,12 @@ struct JsonParser final {
       if (str[i] == '/') {
         i++;
         if (i == str.size())
-          return fail("unexpected end of input inside comment", false);
+          return fail("unexpected end of input after start of comment", false);
         if (str[i] == '/') { // inline comment
           i++;
-          if (i == str.size())
-            return fail("unexpected end of input inside inline comment", false);
-          // advance until next line
-          while (str[i] != '\n') {
+          // advance until next line, or end of input
+          while (i < str.size() && str[i] != '\n') {
             i++;
-            if (i == str.size())
-              return fail("unexpected end of input inside inline comment", false);
           }
           comment_found = true;
         }
@@ -411,9 +411,6 @@ struct JsonParser final {
                 "unexpected end of input inside multi-line comment", false);
           }
           i += 2;
-          if (i == str.size())
-            return fail(
-              "unexpected end of input inside multi-line comment", false);
           comment_found = true;
         }
         else
@@ -432,6 +429,7 @@ struct JsonParser final {
         bool comment_found = false;
         do {
           comment_found = consume_comment();
+          if (failed) return;
           consume_whitespace();
         }
         while(comment_found);
@@ -445,6 +443,7 @@ struct JsonParser final {
      */
     char get_next_token() {
         consume_garbage();
+        if (failed) return (char)0;
         if (i == str.size())
             return fail("unexpected end of input", (char)0);
 
@@ -738,6 +737,8 @@ Json Json::parse(const string &in, string &err, JsonParse strategy) {
 
     // Check for any trailing garbage
     parser.consume_garbage();
+    if (parser.failed)
+        return Json();
     if (parser.i != in.size())
         return parser.fail("unexpected trailing " + esc(in[parser.i]));
 
@@ -754,10 +755,14 @@ vector<Json> Json::parse_multi(const string &in,
     vector<Json> json_vec;
     while (parser.i != in.size() && !parser.failed) {
         json_vec.push_back(parser.parse_json(0));
+        if (parser.failed)
+            break;
+
         // Check for another object
         parser.consume_garbage();
-        if (!parser.failed)
-            parser_stop_pos = parser.i;
+        if (parser.failed)
+            break;
+        parser_stop_pos = parser.i;
     }
     return json_vec;
 }
@@ -772,8 +777,10 @@ bool Json::has_shape(const shape & types, string & err) const {
         return false;
     }
 
+    const auto& obj_items = object_items();
     for (auto & item : types) {
-        if ((*this)[item.first].type() != item.second) {
+        const auto it = obj_items.find(item.first);
+        if (it == obj_items.cend() || it->second.type() != item.second) {
             err = "bad type for " + item.first + " in " + dump();
             return false;
         }
index a68394b0e00f7aa9df1aec97f6cd868d3ae32c21..e1567895aecbc859f2b205f63ae30c652796717c 100644 (file)
@@ -107,14 +107,14 @@ public:
 
     // Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
     template <class M, typename std::enable_if<
-        std::is_constructible<std::string, typename M::key_type>::value
-        && std::is_constructible<Json, typename M::mapped_type>::value,
+        std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value
+        && std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value,
             int>::type = 0>
     Json(const M & m) : Json(object(m.begin(), m.end())) {}
 
     // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
     template <class V, typename std::enable_if<
-        std::is_constructible<Json, typename V::value_type>::value,
+        std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value,
             int>::type = 0>
     Json(const V & v) : Json(array(v.begin(), v.end())) {}