Procházet zdrojové kódy

Fixed deserialization of `\u0000` (issue #1646)

Benoit Blanchon před 4 roky
rodič
revize
956e4a7cbb

+ 12 - 1
.vscode/settings.json

@@ -4,5 +4,16 @@
   "git.inputValidationLength": 80,
   "git.inputValidationSubjectLength": 72,
   "files.insertFinalNewline": true,
-  "files.trimFinalNewlines": true
+  "files.trimFinalNewlines": true,
+  "files.associations": {
+    "fstream": "cpp",
+    "iomanip": "cpp",
+    "string": "cpp",
+    "system_error": "cpp",
+    "vector": "cpp",
+    "xlocmon": "cpp",
+    "xlocnum": "cpp",
+    "xloctime": "cpp",
+    "xstring": "cpp"
+  }
 }

+ 1 - 0
CHANGELOG.md

@@ -7,6 +7,7 @@ HEAD
 * Fixed error `'dummy' may be used uninitialized` on GCC 11
 * Fixed error `expected unqualified-id before 'const'` on GCC 11 (issue #1622)
 * Filter: exact match takes precedence over wildcard (issue #1628)
+* Fixed deserialization of `\u0000` (issue #1646)
 
 v6.18.3 (2021-07-27)
 -------

+ 19 - 0
extras/tests/JsonDeserializer/string.cpp

@@ -46,6 +46,25 @@ TEST_CASE("Valid JSON strings value") {
   }
 }
 
+TEST_CASE("\\u0000") {
+  StaticJsonDocument<200> doc;
+
+  DeserializationError err = deserializeJson(doc, "\"wx\\u0000yz\"");
+  REQUIRE(err == DeserializationError::Ok);
+
+  const char* result = doc.as<const char*>();
+  CHECK(result[0] == 'w');
+  CHECK(result[1] == 'x');
+  CHECK(result[2] == 0);
+  CHECK(result[3] == 'y');
+  CHECK(result[4] == 'z');
+  CHECK(result[5] == 0);
+
+  // ArduinoJson strings doesn't store string length, so the following returns 2
+  // instead of 5 (issue #1646)
+  CHECK(doc.as<std::string>().size() == 2);
+}
+
 TEST_CASE("Truncated JSON string") {
   const char* testCases[] = {"\"hello", "\'hello", "'\\u", "'\\u00", "'\\u000"};
   const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);

+ 9 - 9
src/ArduinoJson/Json/Utf8.hpp

@@ -13,14 +13,14 @@ template <typename TStringBuilder>
 inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) {
   // this function was optimize for code size on AVR
 
-  // a buffer to store the string in reverse
-  char buf[5];
-  char* p = buf;
-
-  *(p++) = 0;
   if (codepoint32 < 0x80) {
-    *(p++) = char((codepoint32));
+    str.append(char(codepoint32));
   } else {
+    // a buffer to store the string in reverse
+    char buf[5];
+    char* p = buf;
+
+    *(p++) = 0;
     *(p++) = char((codepoint32 | 0x80) & 0xBF);
     uint16_t codepoint16 = uint16_t(codepoint32 >> 6);
     if (codepoint16 < 0x20) {  // 0x800
@@ -36,10 +36,10 @@ inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) {
         *(p++) = char(codepoint16 | 0xF0);
       }
     }
-  }
 
-  while (*(--p)) {
-    str.append(*p);
+    while (*(--p)) {
+      str.append(*p);
+    }
   }
 }
 }  // namespace Utf8