Append terminator in saveStringFromFreeZone()

This commit is contained in:
Benoit Blanchon
2021-11-20 20:29:09 +01:00
parent 62f9b94ab1
commit 43b2e2e774
10 changed files with 58 additions and 25 deletions

View File

@ -113,3 +113,21 @@ TEST_CASE("Not enough room to save the key") {
DeserializationError::NoMemory); // fails in the second string DeserializationError::NoMemory); // fails in the second string
} }
} }
TEST_CASE("Empty memory pool") {
// NOLINTNEXTLINE(clang-analyzer-optin.portability.UnixAPI)
DynamicJsonDocument doc(0);
SECTION("Input is const char*") {
REQUIRE(deserializeJson(doc, "\"hello\"") ==
DeserializationError::NoMemory);
REQUIRE(deserializeJson(doc, "\"\"") == DeserializationError::NoMemory);
}
SECTION("Input is const char*") {
char hello[] = "\"hello\"";
REQUIRE(deserializeJson(doc, hello) == DeserializationError::Ok);
char empty[] = "\"hello\"";
REQUIRE(deserializeJson(doc, empty) == DeserializationError::Ok);
}
}

View File

@ -11,12 +11,11 @@ TEST_CASE("StringCopier") {
char buffer[4096]; char buffer[4096];
SECTION("Works when buffer is big enough") { SECTION("Works when buffer is big enough") {
MemoryPool pool(buffer, addPadding(JSON_STRING_SIZE(6))); MemoryPool pool(buffer, addPadding(JSON_STRING_SIZE(5)));
StringCopier str(pool); StringCopier str(pool);
str.startString(); str.startString();
str.append("hello"); str.append("hello");
str.append('\0');
REQUIRE(str.isValid() == true); REQUIRE(str.isValid() == true);
REQUIRE(std::string(str.str()) == "hello"); REQUIRE(std::string(str.str()) == "hello");
@ -31,6 +30,7 @@ TEST_CASE("StringCopier") {
str.append("hello world!"); str.append("hello world!");
REQUIRE(str.isValid() == false); REQUIRE(str.isValid() == false);
REQUIRE(pool.overflowed() == true);
} }
SECTION("Increases size of memory pool") { SECTION("Increases size of memory pool") {
@ -38,10 +38,19 @@ TEST_CASE("StringCopier") {
StringCopier str(pool); StringCopier str(pool);
str.startString(); str.startString();
str.append('h');
str.save(); str.save();
REQUIRE(1 == pool.size()); REQUIRE(1 == pool.size());
REQUIRE(pool.overflowed() == false);
}
SECTION("Works when memory pool is 0 bytes") {
MemoryPool pool(buffer, 0);
StringCopier str(pool);
str.startString();
REQUIRE(str.isValid() == false);
REQUIRE(pool.overflowed() == true);
} }
} }
@ -49,7 +58,6 @@ static const char* addStringToPool(MemoryPool& pool, const char* s) {
StringCopier str(pool); StringCopier str(pool);
str.startString(); str.startString();
str.append(s); str.append(s);
str.append('\0');
return str.save().c_str(); return str.save().c_str();
} }

View File

@ -18,7 +18,6 @@ static void testCodepoint(uint32_t codepoint, std::string expected) {
CAPTURE(codepoint); CAPTURE(codepoint);
Utf8::encodeCodepoint(codepoint, str); Utf8::encodeCodepoint(codepoint, str);
str.append('\0');
REQUIRE(str.str().c_str() == expected); REQUIRE(str.str().c_str() == expected);
} }

View File

@ -60,6 +60,7 @@ TEST_CASE("Printable") {
CHECK(printable.totalBytesWritten() == 7); CHECK(printable.totalBytesWritten() == 7);
CHECK(doc.overflowed() == false); CHECK(doc.overflowed() == false);
CHECK(doc.memoryUsage() == 8); CHECK(doc.memoryUsage() == 8);
CHECK(doc.as<JsonVariant>().memoryUsage() == 8);
} }
SECTION("Via Print::write(const char* size_t)") { SECTION("Via Print::write(const char* size_t)") {
@ -69,6 +70,7 @@ TEST_CASE("Printable") {
CHECK(printable.totalBytesWritten() == 7); CHECK(printable.totalBytesWritten() == 7);
CHECK(doc.overflowed() == false); CHECK(doc.overflowed() == false);
CHECK(doc.memoryUsage() == 8); CHECK(doc.memoryUsage() == 8);
CHECK(doc.as<JsonVariant>().memoryUsage() == 8);
} }
} }

View File

@ -401,8 +401,6 @@ class JsonDeserializer {
_stringStorage.append(c); _stringStorage.append(c);
} }
_stringStorage.append('\0');
if (!_stringStorage.isValid()) { if (!_stringStorage.isValid()) {
_error = DeserializationError::NoMemory; _error = DeserializationError::NoMemory;
return false; return false;
@ -426,8 +424,6 @@ class JsonDeserializer {
return false; return false;
} }
_stringStorage.append('\0');
if (!_stringStorage.isValid()) { if (!_stringStorage.isValid()) {
_error = DeserializationError::NoMemory; _error = DeserializationError::NoMemory;
return false; return false;

View File

@ -87,13 +87,14 @@ class MemoryPool {
const char* saveStringFromFreeZone(size_t len) { const char* saveStringFromFreeZone(size_t len) {
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
const char* dup = findString(adaptString(_left)); const char* dup = findString(adaptString(_left, len));
if (dup) if (dup)
return dup; return dup;
#endif #endif
const char* str = _left; const char* str = _left;
_left += len; _left += len;
*_left++ = 0;
checkInvariants(); checkInvariants();
return str; return str;
} }

View File

@ -343,7 +343,6 @@ class MsgPackDeserializer {
return false; return false;
_stringStorage.append(static_cast<char>(c)); _stringStorage.append(static_cast<char>(c));
} }
_stringStorage.append('\0');
if (!_stringStorage.isValid()) { if (!_stringStorage.isValid()) {
_error = DeserializationError::NoMemory; _error = DeserializationError::NoMemory;
return false; return false;

View File

@ -17,10 +17,13 @@ class StringCopier {
void startString() { void startString() {
_pool->getFreeZone(&_ptr, &_capacity); _pool->getFreeZone(&_ptr, &_capacity);
_size = 0; _size = 0;
if (_capacity == 0)
_pool->markAsOverflowed();
} }
string_type save() { string_type save() {
ARDUINOJSON_ASSERT(_ptr); ARDUINOJSON_ASSERT(_ptr);
ARDUINOJSON_ASSERT(_size < _capacity); // needs room for the terminator
return _pool->saveStringFromFreeZone(_size); return _pool->saveStringFromFreeZone(_size);
} }
@ -33,23 +36,24 @@ class StringCopier {
} }
void append(char c) { void append(char c) {
if (!_ptr) if (_size + 1 < _capacity)
return; _ptr[_size++] = c;
else
if (_size >= _capacity) {
_ptr = 0;
_pool->markAsOverflowed(); _pool->markAsOverflowed();
return;
}
_ptr[_size++] = c;
} }
bool isValid() { bool isValid() const {
return _ptr != 0; return !_pool->overflowed();
}
size_t size() const {
return _size;
} }
string_type str() const { string_type str() const {
ARDUINOJSON_ASSERT(_ptr);
ARDUINOJSON_ASSERT(_size < _capacity);
_ptr[_size] = 0;
return _ptr; return _ptr;
} }

View File

@ -20,7 +20,10 @@ class StringMover {
} }
FORCE_INLINE string_type save() { FORCE_INLINE string_type save() {
return _startPtr; _writePtr[0] = 0; // terminator
string_type s = str();
_writePtr++;
return s;
} }
void append(char c) { void append(char c) {
@ -35,6 +38,10 @@ class StringMover {
return string_type(_startPtr); return string_type(_startPtr);
} }
size_t size() const {
return size_t(_writePtr - _startPtr);
}
private: private:
char* _writePtr; char* _writePtr;
char* _startPtr; char* _startPtr;

View File

@ -204,8 +204,7 @@ class MemoryPoolPrint : public Print {
} }
CopiedString str() { CopiedString str() {
_string[_size++] = 0; ARDUINOJSON_ASSERT(_size < _capacity);
ARDUINOJSON_ASSERT(_size <= _capacity);
return _pool->saveStringFromFreeZone(_size); return _pool->saveStringFromFreeZone(_size);
} }