From c7d0063a9249acfe1bf78f633b3fb11bcadfa3a4 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 22 Oct 2021 15:18:55 +0200 Subject: [PATCH] Support NUL in serializeJson() 5570/6730 --- .../tests/JsonDocument/DynamicJsonDocument.cpp | 2 +- extras/tests/JsonSerializer/JsonVariant.cpp | 4 ++++ src/ArduinoJson/Json/JsonDeserializer.hpp | 3 ++- src/ArduinoJson/Json/TextFormatter.hpp | 4 +++- src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp | 2 +- src/ArduinoJson/StringStorage/StringCopier.hpp | 8 ++++++-- src/ArduinoJson/StringStorage/StringMover.hpp | 4 ++++ src/ArduinoJson/Variant/ConverterImpl.hpp | 4 ++-- src/ArduinoJson/Variant/VariantData.hpp | 17 +++++++++++------ 9 files changed, 34 insertions(+), 14 deletions(-) diff --git a/extras/tests/JsonDocument/DynamicJsonDocument.cpp b/extras/tests/JsonDocument/DynamicJsonDocument.cpp index 6cf953ab6..59869a9b8 100644 --- a/extras/tests/JsonDocument/DynamicJsonDocument.cpp +++ b/extras/tests/JsonDocument/DynamicJsonDocument.cpp @@ -169,7 +169,7 @@ TEST_CASE("DynamicJsonDocument assignment") { doc2 = doc1; - REQUIRE_JSON(doc2, "{\"hello\":\"world\"}"); + REQUIRE_JSON(doc1, "{\"hello\":\"world\"}"); } SECTION("Assign from JsonObject") { diff --git a/extras/tests/JsonSerializer/JsonVariant.cpp b/extras/tests/JsonSerializer/JsonVariant.cpp index 492f88621..547cf4d2e 100644 --- a/extras/tests/JsonSerializer/JsonVariant.cpp +++ b/extras/tests/JsonSerializer/JsonVariant.cpp @@ -63,6 +63,10 @@ TEST_CASE("serializeJson(JsonVariant)") { SECTION("Escape tab") { check(std::string("hello\tworld"), "\"hello\\tworld\""); } + + SECTION("NUL char") { + check(std::string("hello\0world", 11), "\"hello\\u0000world\""); + } } SECTION("SerializedValue") { diff --git a/src/ArduinoJson/Json/JsonDeserializer.hpp b/src/ArduinoJson/Json/JsonDeserializer.hpp index 1a07be866..ff9b1574a 100644 --- a/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/src/ArduinoJson/Json/JsonDeserializer.hpp @@ -346,7 +346,8 @@ class JsonDeserializer { if (!parseQuotedString()) return false; const char *value = _stringStorage.save(); - variant.setStringPointer(value, typename TStringStorage::storage_policy()); + variant.setStringPointer(value, _stringStorage.size() - 1, + typename TStringStorage::storage_policy()); return true; } diff --git a/src/ArduinoJson/Json/TextFormatter.hpp b/src/ArduinoJson/Json/TextFormatter.hpp index 8af5ce374..6a47f8638 100644 --- a/src/ArduinoJson/Json/TextFormatter.hpp +++ b/src/ArduinoJson/Json/TextFormatter.hpp @@ -53,8 +53,10 @@ class TextFormatter { if (specialChar) { writeRaw('\\'); writeRaw(specialChar); - } else { + } else if (c) { writeRaw(c); + } else { + writeRaw("\\u0000"); } } diff --git a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp index fbeb05df2..d6337fab9 100644 --- a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp @@ -331,7 +331,7 @@ class MsgPackDeserializer { bool readString(VariantData *variant, size_t n) { if (!readString(n)) return false; - variant->setStringPointer(_stringStorage.save(), + variant->setStringPointer(_stringStorage.save(), _stringStorage.size() - 1, typename TStringStorage::storage_policy()); return true; } diff --git a/src/ArduinoJson/StringStorage/StringCopier.hpp b/src/ArduinoJson/StringStorage/StringCopier.hpp index 80670aad3..2da5061fe 100644 --- a/src/ArduinoJson/StringStorage/StringCopier.hpp +++ b/src/ArduinoJson/StringStorage/StringCopier.hpp @@ -43,14 +43,18 @@ class StringCopier { _ptr[_size++] = c; } - bool isValid() { + bool isValid() const { return _ptr != 0; } - const char* c_str() { + const char* c_str() const { return _ptr; } + size_t size() const { + return _size; + } + typedef storage_policies::store_by_copy storage_policy; private: diff --git a/src/ArduinoJson/StringStorage/StringMover.hpp b/src/ArduinoJson/StringStorage/StringMover.hpp index f727a7d8f..bade12ddd 100644 --- a/src/ArduinoJson/StringStorage/StringMover.hpp +++ b/src/ArduinoJson/StringStorage/StringMover.hpp @@ -33,6 +33,10 @@ class StringMover { return _startPtr; } + size_t size() const { + return size_t(_writePtr - _startPtr); + } + typedef storage_policies::store_by_address storage_policy; private: diff --git a/src/ArduinoJson/Variant/ConverterImpl.hpp b/src/ArduinoJson/Variant/ConverterImpl.hpp index 236ed612b..91eab1e60 100644 --- a/src/ArduinoJson/Variant/ConverterImpl.hpp +++ b/src/ArduinoJson/Variant/ConverterImpl.hpp @@ -262,13 +262,13 @@ inline void convertToJson(const ::Printable& src, VariantRef dst) { if (!pool || !data) return; MemoryPoolPrint print(pool); - src.printTo(print); + size_t n = src.printTo(print); if (print.overflowed()) { pool->markAsOverflowed(); data->setNull(); return; } - data->setStringPointer(print.c_str(), storage_policies::store_by_copy()); + data->setStringPointer(print.c_str(), n, storage_policies::store_by_copy()); } #endif diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index 23977f561..189e646f9 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -228,18 +228,22 @@ class VariantData { setType(VALUE_IS_NULL); } - void setStringPointer(const char *s, storage_policies::store_by_copy) { + // TODO: why not use a JsonString for both functions? + void setStringPointer(const char *s, size_t n, + storage_policies::store_by_copy) { ARDUINOJSON_ASSERT(s != 0); setType(VALUE_IS_OWNED_STRING); _content.asString.data = s; - _content.asString.size = strlen(s); // TODO + _content.asString.size = n; } - void setStringPointer(const char *s, storage_policies::store_by_address) { + // TODO: why not use a JsonString for both functions? + void setStringPointer(const char *s, size_t n, + storage_policies::store_by_address) { ARDUINOJSON_ASSERT(s != 0); setType(VALUE_IS_LINKED_STRING); _content.asString.data = s; - _content.asString.size = strlen(s); // TODO + _content.asString.size = n; } template @@ -348,7 +352,8 @@ class VariantData { if (value.isNull()) setNull(); else - setStringPointer(value.data(), storage_policies::store_by_address()); + setStringPointer(value.data(), value.size(), + storage_policies::store_by_address()); return true; } @@ -364,7 +369,7 @@ class VariantData { setNull(); return false; } - setStringPointer(copy, storage_policies::store_by_copy()); + setStringPointer(copy, value.size(), storage_policies::store_by_copy()); return true; } };