Przeglądaj źródła

Fix crash with tiny Flash strings (issue #2170)

Benoit Blanchon 9 miesięcy temu
rodzic
commit
deab127a2f

+ 5 - 0
CHANGELOG.md

@@ -1,6 +1,11 @@
 ArduinoJson: change log
 =======================
 
+HEAD
+----
+
+* Fix crash with tiny Flash strings (issue #2170)
+
 v7.4.0 (2025-04-09)
 ------
 

+ 7 - 0
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<const char*>() == "abc"_s);
+    REQUIRE(spy.log() == AllocatorLog{});
+  }
+
 #ifdef HAS_VARIABLE_LENGTH_ARRAY
   SECTION("VLA") {
     size_t i = 16;

+ 1 - 1
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<uint8_t>(size_));
+      data->setTinyString(adaptString(s, size_));
     else
       data->setOwnedString(commitStringNode());
   }

+ 1 - 1
src/ArduinoJson/Memory/StringBuilder.hpp

@@ -31,7 +31,7 @@ class StringBuilder {
 
     char* p = node_->data;
     if (isTinyString(p, size_)) {
-      variant->setTinyString(p, static_cast<uint8_t>(size_));
+      variant->setTinyString(adaptString(p, size_));
       return;
     }
 

+ 12 - 4
src/ArduinoJson/Variant/VariantData.hpp

@@ -526,12 +526,20 @@ class VariantData {
     content_.asLinkedString = s;
   }
 
-  void setTinyString(const char* s, uint8_t n) {
+  template <typename TAdaptedString>
+  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;
   }
 

+ 1 - 1
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;
   }