mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-06-25 01:11:35 +02:00
Fix operator[](variant)
ignoring NUL characters
This commit is contained in:
@ -6,6 +6,7 @@ HEAD
|
||||
|
||||
* Forbid `deserializeJson(JsonArray|JsonObject, ...)` (issue #2135)
|
||||
* Fix VLA support in `JsonDocument::set()`
|
||||
* Fix `operator[](variant)` ignoring NUL characters
|
||||
|
||||
v7.2.0 (2024-09-18)
|
||||
------
|
||||
|
@ -12,27 +12,40 @@ TEST_CASE("JsonDocument::operator[]") {
|
||||
const JsonDocument& cdoc = doc;
|
||||
|
||||
SECTION("object") {
|
||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||
doc["abc"_s] = "ABC";
|
||||
doc["abc\0d"_s] = "ABCD";
|
||||
|
||||
SECTION("const char*") {
|
||||
REQUIRE(doc["hello"] == "world");
|
||||
REQUIRE(cdoc["hello"] == "world");
|
||||
REQUIRE(doc["abc"] == "ABC");
|
||||
REQUIRE(cdoc["abc"] == "ABC");
|
||||
}
|
||||
|
||||
SECTION("std::string") {
|
||||
REQUIRE(doc["hello"_s] == "world");
|
||||
REQUIRE(cdoc["hello"_s] == "world");
|
||||
REQUIRE(doc["abc"_s] == "ABC");
|
||||
REQUIRE(cdoc["abc"_s] == "ABC");
|
||||
REQUIRE(doc["abc\0d"_s] == "ABCD");
|
||||
REQUIRE(cdoc["abc\0d"_s] == "ABCD");
|
||||
}
|
||||
|
||||
SECTION("JsonVariant") {
|
||||
doc["key"] = "hello";
|
||||
REQUIRE(doc[doc["key"]] == "world");
|
||||
REQUIRE(cdoc[cdoc["key"]] == "world");
|
||||
doc["key1"] = "abc";
|
||||
doc["key2"] = "abc\0d"_s;
|
||||
doc["key3"] = "foo";
|
||||
|
||||
CHECK(doc[doc["key1"]] == "ABC");
|
||||
CHECK(doc[doc["key2"]] == "ABCD");
|
||||
CHECK(doc[doc["key3"]] == nullptr);
|
||||
CHECK(doc[doc["key4"]] == nullptr);
|
||||
|
||||
CHECK(cdoc[cdoc["key1"]] == "ABC");
|
||||
CHECK(cdoc[cdoc["key2"]] == "ABCD");
|
||||
CHECK(cdoc[cdoc["key3"]] == nullptr);
|
||||
CHECK(cdoc[cdoc["key4"]] == nullptr);
|
||||
}
|
||||
|
||||
SECTION("supports operator|") {
|
||||
REQUIRE((doc["hello"] | "nope") == "world"_s);
|
||||
REQUIRE((doc["world"] | "nope") == "nope"_s);
|
||||
REQUIRE((doc["abc"] | "nope") == "ABC"_s);
|
||||
REQUIRE((doc["def"] | "nope") == "nope"_s);
|
||||
}
|
||||
|
||||
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
||||
@ -46,7 +59,6 @@ TEST_CASE("JsonDocument::operator[]") {
|
||||
|
||||
REQUIRE(doc[vla] == "world");
|
||||
REQUIRE(cdoc[vla] == "world");
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -253,9 +253,15 @@ TEST_CASE("JsonObject::operator[]") {
|
||||
|
||||
SECTION("JsonVariant") {
|
||||
obj["hello"] = "world";
|
||||
doc["key"] = "hello";
|
||||
obj["a\0b"_s] = "ABC";
|
||||
|
||||
REQUIRE(obj[obj["key"]] == "world");
|
||||
REQUIRE(obj[obj["foo"]] == nullptr);
|
||||
doc["key1"] = "hello";
|
||||
doc["key2"] = "a\0b"_s;
|
||||
doc["key3"] = "foo";
|
||||
|
||||
REQUIRE(obj[obj["key1"]] == "world");
|
||||
REQUIRE(obj[obj["key2"]] == "ABC");
|
||||
REQUIRE(obj[obj["key3"]] == nullptr);
|
||||
REQUIRE(obj[obj["key4"]] == nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
TEST_CASE("JsonObjectConst::operator[]") {
|
||||
JsonDocument doc;
|
||||
doc["hello"] = "world";
|
||||
doc["a\0b"_s] = "ABC";
|
||||
JsonObjectConst obj = doc.as<JsonObjectConst>();
|
||||
|
||||
SECTION("supports const char*") {
|
||||
@ -19,6 +20,7 @@ TEST_CASE("JsonObjectConst::operator[]") {
|
||||
|
||||
SECTION("supports std::string") {
|
||||
REQUIRE(obj["hello"_s] == "world"); // issue #2019
|
||||
REQUIRE(obj["a\0b"_s] == "ABC");
|
||||
}
|
||||
|
||||
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
||||
@ -28,13 +30,17 @@ TEST_CASE("JsonObjectConst::operator[]") {
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
|
||||
REQUIRE("world"_s == obj[vla]);
|
||||
REQUIRE(obj[vla] == "world"_s);
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("supports JsonVariant") {
|
||||
doc["key"] = "hello";
|
||||
REQUIRE(obj[obj["key"]] == "world");
|
||||
REQUIRE(obj[obj["foo"]] == nullptr);
|
||||
doc["key1"] = "hello";
|
||||
doc["key2"] = "a\0b"_s;
|
||||
doc["key3"] = "foo";
|
||||
REQUIRE(obj[obj["key1"]] == "world");
|
||||
REQUIRE(obj[obj["key2"]] == "ABC");
|
||||
REQUIRE(obj[obj["key3"]] == nullptr);
|
||||
REQUIRE(obj[obj["key4"]] == nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -116,12 +116,19 @@ TEST_CASE("JsonVariant::operator[]") {
|
||||
}
|
||||
|
||||
SECTION("use JsonVariant as key") {
|
||||
object["a"] = "a";
|
||||
object["b"] = "b";
|
||||
object["c"] = "b";
|
||||
object["a"] = "A";
|
||||
object["ab"] = "AB";
|
||||
object["ab\0c"_s] = "ABC";
|
||||
object["key1"] = "a";
|
||||
object["key2"] = "ab";
|
||||
object["key3"] = "ab\0c"_s;
|
||||
object["key4"] = "foo";
|
||||
|
||||
REQUIRE(var[var["c"]] == "b");
|
||||
REQUIRE(var[var["d"]].isNull());
|
||||
REQUIRE(var[var["key1"]] == "A");
|
||||
REQUIRE(var[var["key2"]] == "AB");
|
||||
REQUIRE(var[var["key3"]] == "ABC");
|
||||
REQUIRE(var[var["key4"]].isNull());
|
||||
REQUIRE(var[var["key5"]].isNull());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,20 +50,22 @@ TEST_CASE("JsonVariantConst::operator[]") {
|
||||
|
||||
SECTION("object") {
|
||||
JsonObject object = doc.to<JsonObject>();
|
||||
object["a"] = "A";
|
||||
object["b"] = "B";
|
||||
object["ab"_s] = "AB";
|
||||
object["abc"_s] = "ABC";
|
||||
object["abc\0d"_s] = "ABCD";
|
||||
|
||||
SECTION("supports const char*") {
|
||||
REQUIRE("A"_s == var["a"]);
|
||||
REQUIRE("B"_s == var["b"]);
|
||||
REQUIRE(var["c"].isNull());
|
||||
REQUIRE(var["ab"] == "AB"_s);
|
||||
REQUIRE(var["abc"] == "ABC"_s);
|
||||
REQUIRE(var["def"].isNull());
|
||||
REQUIRE(var[0].isNull());
|
||||
}
|
||||
|
||||
SECTION("supports std::string") {
|
||||
REQUIRE("A"_s == var["a"_s]);
|
||||
REQUIRE("B"_s == var["b"_s]);
|
||||
REQUIRE(var["c"_s].isNull());
|
||||
REQUIRE(var["ab"_s] == "AB"_s);
|
||||
REQUIRE(var["abc"_s] == "ABC"_s);
|
||||
REQUIRE(var["abc\0d"_s] == "ABCD"_s);
|
||||
REQUIRE(var["def"_s].isNull());
|
||||
}
|
||||
|
||||
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
||||
@ -71,16 +73,23 @@ TEST_CASE("JsonVariantConst::operator[]") {
|
||||
SECTION("supports VLA") {
|
||||
size_t i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "a");
|
||||
strcpy(vla, "abc");
|
||||
|
||||
REQUIRE("A"_s == var[vla]);
|
||||
REQUIRE(var[vla] == "ABC"_s);
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("supports JsonVariant") {
|
||||
object["c"] = "b";
|
||||
REQUIRE(var[var["c"]] == "B");
|
||||
REQUIRE(var[var["d"]].isNull());
|
||||
object["key1"] = "ab";
|
||||
object["key2"] = "abc";
|
||||
object["key3"] = "abc\0d"_s;
|
||||
object["key4"] = "foo";
|
||||
|
||||
REQUIRE(var[var["key1"]] == "AB"_s);
|
||||
REQUIRE(var[var["key2"]] == "ABC"_s);
|
||||
REQUIRE(var[var["key3"]] == "ABCD"_s);
|
||||
REQUIRE(var[var["key4"]].isNull());
|
||||
REQUIRE(var[var["key5"]].isNull());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,8 +239,8 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
|
||||
operator[](const TVariant& key) const {
|
||||
if (key.template is<const char*>())
|
||||
return operator[](key.template as<const char*>());
|
||||
if (key.template is<JsonString>())
|
||||
return operator[](key.template as<JsonString>());
|
||||
if (key.template is<size_t>())
|
||||
return operator[](key.template as<size_t>());
|
||||
return {};
|
||||
|
@ -121,10 +121,10 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
||||
// https://arduinojson.org/v7/api/jsonobject/subscript/
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value,
|
||||
detail::MemberProxy<JsonObject, const char*>>
|
||||
detail::MemberProxy<JsonObject, JsonString>>
|
||||
operator[](const TVariant& key) const {
|
||||
if (key.template is<const char*>())
|
||||
return {*this, key.template as<const char*>()};
|
||||
if (key.template is<JsonString>())
|
||||
return {*this, key.template as<JsonString>()};
|
||||
else
|
||||
return {*this, nullptr};
|
||||
}
|
||||
|
@ -121,8 +121,8 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
||||
template <typename TVariant>
|
||||
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
|
||||
operator[](const TVariant& key) const {
|
||||
if (key.template is<const char*>())
|
||||
return operator[](key.template as<const char*>());
|
||||
if (key.template is<JsonString>())
|
||||
return operator[](key.template as<JsonString>());
|
||||
else
|
||||
return JsonVariantConst();
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ class JsonVariantConst : public detail::VariantTag,
|
||||
if (key.template is<size_t>())
|
||||
return operator[](key.template as<size_t>());
|
||||
else
|
||||
return operator[](key.template as<const char*>());
|
||||
return operator[](key.template as<JsonString>());
|
||||
}
|
||||
|
||||
// DEPRECATED: use obj[key].is<T>() instead
|
||||
|
@ -207,7 +207,7 @@ class VariantRefBase : public VariantTag {
|
||||
if (key.template is<size_t>())
|
||||
return operator[](key.template as<size_t>());
|
||||
else
|
||||
return operator[](key.template as<const char*>());
|
||||
return operator[](key.template as<JsonString>());
|
||||
}
|
||||
|
||||
// DEPRECATED: use add<JsonVariant>() instead
|
||||
|
Reference in New Issue
Block a user