forked from bblanchon/ArduinoJson
Fixed dangling reference in MemberProxy and ElementProxy (fixes #1120)
This commit is contained in:
@ -10,6 +10,7 @@ HEAD
|
|||||||
* Improved `deserializeMsgPack()` speed by reading several bytes at once
|
* Improved `deserializeMsgPack()` speed by reading several bytes at once
|
||||||
* Added detection of Atmel AVR8/GNU C Compiler (issue #1112)
|
* Added detection of Atmel AVR8/GNU C Compiler (issue #1112)
|
||||||
* Fixed deserializer that stopped reading at the first `0xFF` (PR #1118 by @mikee47)
|
* Fixed deserializer that stopped reading at the first `0xFF` (PR #1118 by @mikee47)
|
||||||
|
* Fixed dangling reference in copies of `MemberProxy` and `ElementProxy` (issue #1120)
|
||||||
|
|
||||||
v6.12.0 (2019-09-05)
|
v6.12.0 (2019-09-05)
|
||||||
-------
|
-------
|
||||||
|
@ -28,4 +28,59 @@ TEST_CASE("nullptr") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Issue #1120") {
|
||||||
|
StaticJsonDocument<500> doc;
|
||||||
|
constexpr char str[] =
|
||||||
|
"{\"contents\":[{\"module\":\"Packet\"},{\"module\":\"Analog\"}]}";
|
||||||
|
deserializeJson(doc, str);
|
||||||
|
|
||||||
|
SECTION("MemberProxy<std::string>::isNull()") {
|
||||||
|
SECTION("returns false") {
|
||||||
|
auto value = doc[std::string("contents")];
|
||||||
|
CHECK(value.isNull() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns true") {
|
||||||
|
auto value = doc[std::string("zontents")];
|
||||||
|
CHECK(value.isNull() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ElementProxy<MemberProxy<const char*> >::isNull()") {
|
||||||
|
SECTION("returns false") { // Issue #1120
|
||||||
|
auto value = doc["contents"][1];
|
||||||
|
CHECK(value.isNull() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns true") {
|
||||||
|
auto value = doc["contents"][2];
|
||||||
|
CHECK(value.isNull() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("MemberProxy<ElementProxy<MemberProxy>, const char*>::isNull()") {
|
||||||
|
SECTION("returns false") {
|
||||||
|
auto value = doc["contents"][1]["module"];
|
||||||
|
CHECK(value.isNull() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns true") {
|
||||||
|
auto value = doc["contents"][1]["zodule"];
|
||||||
|
CHECK(value.isNull() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("MemberProxy<ElementProxy<MemberProxy>, std::string>::isNull()") {
|
||||||
|
SECTION("returns false") {
|
||||||
|
auto value = doc["contents"][1][std::string("module")];
|
||||||
|
CHECK(value.isNull() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns true") {
|
||||||
|
auto value = doc["contents"][1][std::string("zodule")];
|
||||||
|
CHECK(value.isNull() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,4 +19,10 @@ inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
|
|||||||
return impl()->addElement().template to<ObjectRef>();
|
return impl()->addElement().template to<ObjectRef>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TArray>
|
||||||
|
inline ElementProxy<TArray> ArrayShortcuts<TArray>::operator[](
|
||||||
|
size_t index) const {
|
||||||
|
return ElementProxy<TArray>(*impl(), index);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -16,7 +16,7 @@ template <typename TArray>
|
|||||||
class ArrayShortcuts {
|
class ArrayShortcuts {
|
||||||
public:
|
public:
|
||||||
// Returns the element at specified index if the variant is an array.
|
// Returns the element at specified index if the variant is an array.
|
||||||
FORCE_INLINE ElementProxy<const TArray &> operator[](size_t index) const;
|
FORCE_INLINE ElementProxy<TArray> operator[](size_t index) const;
|
||||||
|
|
||||||
FORCE_INLINE ObjectRef createNestedObject() const;
|
FORCE_INLINE ObjectRef createNestedObject() const;
|
||||||
|
|
||||||
|
@ -161,12 +161,6 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
|||||||
const size_t _index;
|
const size_t _index;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TArray>
|
|
||||||
inline ElementProxy<const TArray&> ArrayShortcuts<TArray>::operator[](
|
|
||||||
size_t index) const {
|
|
||||||
return ElementProxy<const TArray&>(*impl(), index);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -141,11 +141,10 @@ class JsonDocument : public Visitable {
|
|||||||
// operator[](const std::string&)
|
// operator[](const std::string&)
|
||||||
// operator[](const String&)
|
// operator[](const String&)
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
FORCE_INLINE
|
FORCE_INLINE typename enable_if<IsString<TString>::value,
|
||||||
typename enable_if<IsString<TString>::value,
|
MemberProxy<JsonDocument&, TString> >::type
|
||||||
MemberProxy<JsonDocument&, const TString&> >::type
|
operator[](const TString& key) {
|
||||||
operator[](const TString& key) {
|
return MemberProxy<JsonDocument&, TString>(*this, key);
|
||||||
return MemberProxy<JsonDocument&, const TString&>(*this, key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// operator[](char*)
|
// operator[](char*)
|
||||||
|
@ -174,22 +174,6 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
|
|||||||
TStringRef _key;
|
TStringRef _key;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TObject>
|
|
||||||
template <typename TString>
|
|
||||||
inline typename enable_if<IsString<TString>::value,
|
|
||||||
MemberProxy<const TObject &, const TString &> >::type
|
|
||||||
ObjectShortcuts<TObject>::operator[](const TString &key) const {
|
|
||||||
return MemberProxy<const TObject &, const TString &>(*impl(), key);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TObject>
|
|
||||||
template <typename TString>
|
|
||||||
inline typename enable_if<IsString<TString *>::value,
|
|
||||||
MemberProxy<const TObject &, TString *> >::type
|
|
||||||
ObjectShortcuts<TObject>::operator[](TString *key) const {
|
|
||||||
return MemberProxy<const TObject &, TString *>(*impl(), key);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -49,4 +49,21 @@ inline typename enable_if<IsString<TChar*>::value, bool>::type
|
|||||||
ObjectShortcuts<TObject>::containsKey(TChar* key) const {
|
ObjectShortcuts<TObject>::containsKey(TChar* key) const {
|
||||||
return !impl()->getMember(key).isUndefined();
|
return !impl()->getMember(key).isUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TObject>
|
||||||
|
template <typename TString>
|
||||||
|
inline typename enable_if<IsString<TString*>::value,
|
||||||
|
MemberProxy<TObject, TString*> >::type
|
||||||
|
ObjectShortcuts<TObject>::operator[](TString* key) const {
|
||||||
|
return MemberProxy<TObject, TString*>(*impl(), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TObject>
|
||||||
|
template <typename TString>
|
||||||
|
inline typename enable_if<IsString<TString>::value,
|
||||||
|
MemberProxy<TObject, TString> >::type
|
||||||
|
ObjectShortcuts<TObject>::operator[](const TString& key) const {
|
||||||
|
return MemberProxy<TObject, TString>(*impl(), key);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -31,17 +31,16 @@ class ObjectShortcuts {
|
|||||||
// operator[](const std::string&) const
|
// operator[](const std::string&) const
|
||||||
// operator[](const String&) const
|
// operator[](const String&) const
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
FORCE_INLINE
|
FORCE_INLINE typename enable_if<IsString<TString>::value,
|
||||||
typename enable_if<IsString<TString>::value,
|
MemberProxy<TObject, TString> >::type
|
||||||
MemberProxy<const TObject &, const TString &> >::type
|
operator[](const TString &key) const;
|
||||||
operator[](const TString &key) const;
|
|
||||||
|
|
||||||
// operator[](char*) const
|
// operator[](char*) const
|
||||||
// operator[](const char*) const
|
// operator[](const char*) const
|
||||||
// operator[](const __FlashStringHelper*) const
|
// operator[](const __FlashStringHelper*) const
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
FORCE_INLINE typename enable_if<IsString<TChar *>::value,
|
FORCE_INLINE typename enable_if<IsString<TChar *>::value,
|
||||||
MemberProxy<const TObject &, TChar *> >::type
|
MemberProxy<TObject, TChar *> >::type
|
||||||
operator[](TChar *key) const;
|
operator[](TChar *key) const;
|
||||||
|
|
||||||
// createNestedArray(const std::string&) const
|
// createNestedArray(const std::string&) const
|
||||||
|
Reference in New Issue
Block a user