diff --git a/CHANGELOG.md b/CHANGELOG.md index fa22e144..3cd8e60b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ ArduinoJson: change log ======================= +HEAD +---- + +* Fix crash with tiny Flash strings (issue #2170) + v7.4.0 (2025-04-09) ------ diff --git a/extras/tests/JsonDocument/set.cpp b/extras/tests/JsonDocument/set.cpp index 1205acf5..88c33bbc 100644 --- a/extras/tests/JsonDocument/set.cpp +++ b/extras/tests/JsonDocument/set.cpp @@ -87,6 +87,13 @@ TEST_CASE("JsonDocument::set()") { }); } + SECTION("Flash tiny string") { // issue #2170 + doc.set(F("abc")); + + REQUIRE(doc.as() == "abc"_s); + REQUIRE(spy.log() == AllocatorLog{}); + } + #ifdef HAS_VARIABLE_LENGTH_ARRAY SECTION("VLA") { size_t i = 16; diff --git a/src/ArduinoJson/Memory/StringBuffer.hpp b/src/ArduinoJson/Memory/StringBuffer.hpp index 91a1cd15..4d5caa75 100644 --- a/src/ArduinoJson/Memory/StringBuffer.hpp +++ b/src/ArduinoJson/Memory/StringBuffer.hpp @@ -41,7 +41,7 @@ class StringBuffer { ARDUINOJSON_ASSERT(node_ != nullptr); const char* s = node_->data; if (isTinyString(s, size_)) - data->setTinyString(s, static_cast(size_)); + data->setTinyString(adaptString(s, size_)); else data->setOwnedString(commitStringNode()); } diff --git a/src/ArduinoJson/Memory/StringBuilder.hpp b/src/ArduinoJson/Memory/StringBuilder.hpp index 7ed77a7d..db6c3544 100644 --- a/src/ArduinoJson/Memory/StringBuilder.hpp +++ b/src/ArduinoJson/Memory/StringBuilder.hpp @@ -31,7 +31,7 @@ class StringBuilder { char* p = node_->data; if (isTinyString(p, size_)) { - variant->setTinyString(p, static_cast(size_)); + variant->setTinyString(adaptString(p, size_)); return; } diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index a790bfaf..6b0d474b 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -526,12 +526,20 @@ class VariantData { content_.asLinkedString = s; } - void setTinyString(const char* s, uint8_t n) { + template + void setTinyString(const TAdaptedString& s) { ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first - ARDUINOJSON_ASSERT(s); + ARDUINOJSON_ASSERT(s.size() <= tinyStringMaxLength); + type_ = VariantType::TinyString; - for (uint8_t i = 0; i < n; i++) - content_.asTinyString[i] = s[i]; + + auto n = uint8_t(s.size()); + for (uint8_t i = 0; i < n; i++) { + char c = s[i]; + ARDUINOJSON_ASSERT(c != 0); // no NUL in tiny string + content_.asTinyString[i] = c; + } + content_.asTinyString[n] = 0; } diff --git a/src/ArduinoJson/Variant/VariantImpl.hpp b/src/ArduinoJson/Variant/VariantImpl.hpp index 812624ff..98289ed0 100644 --- a/src/ArduinoJson/Variant/VariantImpl.hpp +++ b/src/ArduinoJson/Variant/VariantImpl.hpp @@ -32,7 +32,7 @@ inline bool VariantData::setString(TAdaptedString value, } if (isTinyString(value, value.size())) { - setTinyString(value.data(), uint8_t(value.size())); + setTinyString(value); return true; }