Compare commits

..

9 Commits

26 changed files with 108 additions and 92 deletions

View File

@ -1,6 +1,12 @@
ArduinoJson: change log
=======================
v6.19.1 (2022-01-14)
-------
* Fix crash when adding an object member in a too small `JsonDocument`
* Fix filter not working in zero-copy mode (issue #1697)
v6.19.0 (2022-01-08)
-------
@ -24,7 +30,6 @@ v6.19.0 (2022-01-08)
* Avoid including `Arduino.h` when all its features are disabled (issue #1692, PR #1693 by @paulocsanz)
* Assume `PROGMEM` is available as soon as `ARDUINO` is defined (consequence of #1693)
v6.18.5 (2021-09-28)
-------

View File

@ -10,7 +10,7 @@ if(ESP_PLATFORM)
return()
endif()
project(ArduinoJson VERSION 6.19.0)
project(ArduinoJson VERSION 6.19.1)
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
include(CTest)

View File

@ -7,8 +7,8 @@
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
[![LGTM Grade](https://img.shields.io/lgtm/grade/cpp/github/bblanchon/ArduinoJson?label=quality&logo=lgtm)](https://lgtm.com/projects/g/bblanchon/ArduinoJson/)
[![Coveralls branch](https://img.shields.io/coveralls/github/bblanchon/ArduinoJson/6.x?logo=coveralls)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
[![Arduino Library Manager](https://img.shields.io/static/v1?label=Arduino&message=v6.19.0&logo=arduino&logoColor=white&color=blue)](https://www.ardu-badge.com/ArduinoJson/6.19.0)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/bblanchon/library/ArduinoJson.svg?version=6.19.0)](https://registry.platformio.org/packages/libraries/bblanchon/ArduinoJson?version=6.19.0)
[![Arduino Library Manager](https://img.shields.io/static/v1?label=Arduino&message=v6.19.1&logo=arduino&logoColor=white&color=blue)](https://www.ardu-badge.com/ArduinoJson/6.19.1)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/bblanchon/library/ArduinoJson.svg?version=6.19.1)](https://registry.platformio.org/packages/libraries/bblanchon/ArduinoJson?version=6.19.1)
[![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat&logo=github)](https://github.com/bblanchon/ArduinoJson/stargazers)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/bblanchon?logo=github)](https://github.com/sponsors/bblanchon)

View File

@ -1,4 +1,4 @@
version: 6.19.0.{build}
version: 6.19.1.{build}
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022

View File

@ -8,7 +8,7 @@ CHANGELOG="$2"
cat << END
## Changes
$(awk '/\* /{ FOUND=1; print; next } { if (FOUND) exit}' "$CHANGELOG")
$(awk '/\* /{ FOUND=1 } /^[[:space:]]*$/ { if(FOUND) exit } { if(FOUND) print }' "$CHANGELOG")
[View version history](https://github.com/bblanchon/ArduinoJson/blob/$TAG/CHANGELOG.md)
END

View File

@ -2,6 +2,8 @@
set -eu
which awk sed jq 7z curl perl >/dev/null
cd "$(dirname "$0")/../.."
if ! git diff --quiet --exit-code; then

View File

@ -667,6 +667,20 @@ TEST_CASE("Filtering") {
}
}
TEST_CASE("Zero-copy mode") { // issue #1697
char input[] = "{\"include\":42,\"exclude\":666}";
StaticJsonDocument<256> filter;
filter["include"] = true;
StaticJsonDocument<256> doc;
DeserializationError err =
deserializeJson(doc, input, DeserializationOption::Filter(filter));
REQUIRE(err == DeserializationError::Ok);
CHECK(doc.as<std::string>() == "{\"include\":42}");
}
TEST_CASE("Overloads") {
StaticJsonDocument<256> doc;
StaticJsonDocument<256> filter;

View File

@ -279,6 +279,22 @@ TEST_CASE("deserialize JSON object") {
REQUIRE(err == DeserializationError::Ok);
REQUIRE(doc["a"] == 2);
}
SECTION("Repeated key with zero copy mode") { // issue #1697
char input[] = "{a:{b:{c:1}},a:2}";
DeserializationError err = deserializeJson(doc, input);
REQUIRE(err == DeserializationError::Ok);
REQUIRE(doc["a"] == 2);
}
SECTION("NUL in keys") { // we don't support NULs in keys
DeserializationError err =
deserializeJson(doc, "{\"x\\u0000a\":1,\"x\\u0000b\":2}");
REQUIRE(err == DeserializationError::Ok);
REQUIRE(doc.as<std::string>() == "{\"x\":2}");
}
}
SECTION("Should clear the JsonObject") {

View File

@ -35,6 +35,12 @@ TEST_CASE("JsonDocument::overflowed()") {
CHECK(doc.overflowed() == false);
}
SECTION("returns true after a failed member add") {
StaticJsonDocument<1> doc;
doc["example"] = true;
CHECK(doc.overflowed() == true);
}
SECTION("returns true after a failed deserialization") {
StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
deserializeJson(doc, "[\"example\"]");

View File

@ -18,7 +18,7 @@ TEST_CASE("StringCopier") {
str.append("hello");
REQUIRE(str.isValid() == true);
REQUIRE(std::string(str.str()) == "hello");
REQUIRE(str.str() == "hello");
REQUIRE(pool.overflowed() == false);
}

View File

@ -1027,6 +1027,20 @@ TEST_CASE("deserializeMsgPack() filter") {
}
}
TEST_CASE("Zero-copy mode") { // issue #1697
char input[] = "\x82\xA7include\x01\xA6ignore\x02";
StaticJsonDocument<256> filter;
filter["include"] = true;
StaticJsonDocument<256> doc;
DeserializationError err =
deserializeMsgPack(doc, input, 18, DeserializationOption::Filter(filter));
CHECK(err == DeserializationError::Ok);
CHECK(doc.as<std::string>() == "{\"include\":1}");
}
TEST_CASE("Overloads") {
StaticJsonDocument<256> doc;
StaticJsonDocument<256> filter;

View File

@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"version": "6.19.0",
"version": "6.19.1",
"authors": {
"name": "Benoit Blanchon",
"url": "https://blog.benoitblanchon.fr"

View File

@ -1,5 +1,5 @@
name=ArduinoJson
version=6.19.0
version=6.19.1
author=Benoit Blanchon <blog.benoitblanchon.fr>
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
sentence=A simple and efficient JSON library for embedded C++.

View File

@ -231,7 +231,7 @@ class JsonDeserializer {
return false;
}
typename TStringStorage::string_type key = _stringStorage.str();
String key = _stringStorage.str();
TFilter memberFilter = filter[key.c_str()];

View File

@ -62,12 +62,12 @@ class MemoryPool {
template <typename TAdaptedString>
const char* saveString(TAdaptedString str) {
if (str.isNull())
return CopiedString();
return 0;
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
const char* existingCopy = findString(str);
if (existingCopy)
return CopiedString(existingCopy, str.size());
return existingCopy;
#endif
size_t n = str.size();
@ -77,7 +77,7 @@ class MemoryPool {
stringGetChars(str, newCopy, n);
newCopy[n] = 0; // force null-terminator
}
return CopiedString(newCopy, n);
return newCopy;
}
void getFreeZone(char** zoneStart, size_t* zoneSize) const {
@ -89,14 +89,14 @@ class MemoryPool {
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
const char* dup = findString(adaptString(_left, len));
if (dup)
return CopiedString(dup, len);
return dup;
#endif
const char* str = _left;
_left += len;
*_left++ = 0;
checkInvariants();
return CopiedString(str, len);
return str;
}
void markAsOverflowed() {

View File

@ -48,6 +48,11 @@ class MsgPackDeserializer {
bool allowValue = filter.allowValue();
if (allowValue) {
// callers pass a null pointer only when value must be ignored
ARDUINOJSON_ASSERT(variant != 0);
}
switch (code) {
case 0xc0:
// already null
@ -417,11 +422,13 @@ class MsgPackDeserializer {
if (!readKey())
return false;
typename TStringStorage::string_type key = _stringStorage.str();
String key = _stringStorage.str();
TFilter memberFilter = filter[key.c_str()];
VariantData *member;
if (memberFilter.allow()) {
ARDUINOJSON_ASSERT(object);
// Save key in memory pool.
// This MUST be done before adding the slot.
key = _stringStorage.save();

View File

@ -10,8 +10,6 @@ namespace ARDUINOJSON_NAMESPACE {
class StringCopier {
public:
typedef CopiedString string_type;
StringCopier(MemoryPool& pool) : _pool(&pool) {}
void startString() {
@ -21,10 +19,10 @@ class StringCopier {
_pool->markAsOverflowed();
}
string_type save() {
String save() {
ARDUINOJSON_ASSERT(_ptr);
ARDUINOJSON_ASSERT(_size < _capacity); // needs room for the terminator
return string_type(_pool->saveStringFromFreeZone(_size), _size);
return String(_pool->saveStringFromFreeZone(_size), _size, false);
}
void append(const char* s) {
@ -50,11 +48,11 @@ class StringCopier {
return _size;
}
string_type str() const {
String str() const {
ARDUINOJSON_ASSERT(_ptr);
ARDUINOJSON_ASSERT(_size < _capacity);
_ptr[_size] = 0;
return string_type(_ptr, _size);
return String(_ptr, _size, false);
}
private:

View File

@ -5,23 +5,20 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Strings/StoredString.hpp>
#include <ArduinoJson/Strings/String.hpp>
namespace ARDUINOJSON_NAMESPACE {
class StringMover {
public:
typedef LinkedString string_type;
StringMover(char* ptr) : _writePtr(ptr) {}
void startString() {
_startPtr = _writePtr;
}
FORCE_INLINE string_type save() {
_writePtr[0] = 0; // terminator
string_type s = str();
FORCE_INLINE String save() {
String s = str();
_writePtr++;
return s;
}
@ -34,8 +31,9 @@ class StringMover {
return true;
}
string_type str() const {
return string_type(_startPtr, size());
String str() const {
_writePtr[0] = 0; // terminator
return String(_startPtr, size(), true);
}
size_t size() const {

View File

@ -5,7 +5,6 @@
#pragma once
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Strings/StoredString.hpp>
#include <ArduinoJson/Strings/String.hpp>
namespace ARDUINOJSON_NAMESPACE {
@ -13,15 +12,13 @@ namespace ARDUINOJSON_NAMESPACE {
struct LinkStringStoragePolicy {
template <typename TAdaptedString, typename TCallback>
bool store(TAdaptedString str, MemoryPool *, TCallback callback) {
LinkedString storedString(str.data(), str.size());
String storedString(str.data(), str.size(), true);
callback(storedString);
return !str.isNull();
}
};
struct CopyStringStoragePolicy {
typedef CopiedString TResult;
template <typename TAdaptedString, typename TCallback>
bool store(TAdaptedString str, MemoryPool *pool, TCallback callback);
};

View File

@ -1,35 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <bool linked>
class StoredString {
public:
StoredString() : _data(0), _size(0) {}
StoredString(const char* p, size_t n) : _data(p), _size(n) {}
operator const char*() const {
return _data;
}
const char* c_str() const {
return _data;
}
size_t size() const {
return _size;
}
private:
const char* _data;
size_t _size;
};
typedef StoredString<true> LinkedString;
typedef StoredString<false> CopiedString;
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -206,9 +206,9 @@ class MemoryPoolPrint : public Print {
pool->getFreeZone(&_string, &_capacity);
}
CopiedString str() {
String str() {
ARDUINOJSON_ASSERT(_size < _capacity);
return CopiedString(_pool->saveStringFromFreeZone(_size), _size);
return String(_pool->saveStringFromFreeZone(_size), _size, false);
}
size_t write(uint8_t c) {

View File

@ -26,6 +26,8 @@ struct SlotKeySetter {
template <typename TAdaptedString, typename TStoragePolicy>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
TStoragePolicy storage) {
if (!var)
return false;
return storage.store(key, pool, SlotKeySetter(var));
}

View File

@ -208,16 +208,12 @@ class VariantData {
setType(VALUE_IS_NULL);
}
void setString(CopiedString s) {
void setString(String s) {
ARDUINOJSON_ASSERT(s);
setType(VALUE_IS_OWNED_STRING);
_content.asString.data = s.c_str();
_content.asString.size = s.size();
}
void setString(LinkedString s) {
ARDUINOJSON_ASSERT(s);
setType(VALUE_IS_LINKED_STRING);
if (s.isStatic())
setType(VALUE_IS_LINKED_STRING);
else
setType(VALUE_IS_OWNED_STRING);
_content.asString.data = s.c_str();
_content.asString.size = s.size();
}

View File

@ -174,7 +174,7 @@ template <typename TAdaptedString, typename TCallback>
bool CopyStringStoragePolicy::store(TAdaptedString str, MemoryPool *pool,
TCallback callback) {
const char *copy = pool->saveString(str);
CopiedString storedString(copy, str.size());
String storedString(copy, str.size(), false);
callback(storedString);
return copy != 0;
}

View File

@ -7,7 +7,6 @@
#include <ArduinoJson/Polyfills/integer.hpp>
#include <ArduinoJson/Polyfills/limits.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/StoredString.hpp>
#include <ArduinoJson/Variant/VariantContent.hpp>
namespace ARDUINOJSON_NAMESPACE {
@ -77,15 +76,12 @@ class VariantSlot {
_next = VariantSlotDiff(slot - this);
}
void setKey(CopiedString k) {
void setKey(String k) {
ARDUINOJSON_ASSERT(k);
_flags |= OWNED_KEY_BIT;
_key = k.c_str();
}
void setKey(LinkedString k) {
ARDUINOJSON_ASSERT(k);
_flags &= VALUE_MASK;
if (k.isStatic())
_flags &= VALUE_MASK;
else
_flags |= OWNED_KEY_BIT;
_key = k.c_str();
}

View File

@ -4,7 +4,7 @@
#pragma once
#define ARDUINOJSON_VERSION "6.19.0"
#define ARDUINOJSON_VERSION "6.19.1"
#define ARDUINOJSON_VERSION_MAJOR 6
#define ARDUINOJSON_VERSION_MINOR 19
#define ARDUINOJSON_VERSION_REVISION 0
#define ARDUINOJSON_VERSION_REVISION 1