From: Miod Vallat Date: Fri, 17 Oct 2025 14:52:36 +0000 (+0200) Subject: Bring some bugfixes from upstream (dropbox/json11). X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=466a128831ae1fd6f8873d4176669175755aa36f;p=thirdparty%2Fpdns.git Bring some bugfixes from upstream (dropbox/json11). - 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 --- diff --git a/ext/json11/json11.cpp b/ext/json11/json11.cpp index 2a7890a6cc..020ed5a545 100644 --- a/ext/json11/json11.cpp +++ b/ext/json11/json11.cpp @@ -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::parse_multi(const string &in, vector 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; } diff --git a/ext/json11/json11.hpp b/ext/json11/json11.hpp index a68394b0e0..e1567895ae 100644 --- a/ext/json11/json11.hpp +++ b/ext/json11/json11.hpp @@ -107,14 +107,14 @@ public: // Implicit constructor: map-like objects (std::map, std::unordered_map, etc) template ::value - && std::is_constructible::value, + std::is_constructible().begin()->first)>::value + && std::is_constructible().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 ::value, + std::is_constructible().begin())>::value, int>::type = 0> Json(const V & v) : Json(array(v.begin(), v.end())) {}