mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Fixed memory alignment, which made ESP8266 crash (issue #104)
This commit is contained in:
		| @@ -4,9 +4,10 @@ ArduinoJson: change log | ||||
| v5.0.2 | ||||
| ------ | ||||
|  | ||||
| * Fixed Clang warning "register specifier is deprecated" (issue #102) | ||||
| * Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the  | ||||
|   `StaticJsonBuffer` is too small to hold a copy of the string (issue #104) | ||||
|   `StaticJsonBuffer` is too small to hold a copy of the string | ||||
| * Fixed Clang warning "register specifier is deprecated" (issue #102) | ||||
| * Fixed memory alignment, which made ESP8266 crash (issue #104) | ||||
| * Fixed compilation on Visual Studio 2010 and 2012 (issue #107) | ||||
|  | ||||
| v5.0.1 | ||||
|   | ||||
| @@ -63,7 +63,7 @@ class BlockJsonBuffer : public JsonBuffer { | ||||
|  | ||||
|   void* allocInHead(size_t bytes) { | ||||
|     void* p = _head->data + _head->size; | ||||
|     _head->size += bytes; | ||||
|     _head->size += round_size_up(bytes); | ||||
|     return p; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -103,19 +103,33 @@ class JsonBuffer { | ||||
|   // Return a pointer to the allocated memory or NULL if allocation fails. | ||||
|   virtual void *alloc(size_t size) = 0; | ||||
|  | ||||
|  protected: | ||||
|   // Preserve aligment if nessary | ||||
|   static FORCE_INLINE size_t round_size_up(size_t bytes) { | ||||
| #if defined ARDUINO_ARCH_AVR | ||||
|     // alignment isn't needed for 8-bit AVR | ||||
|     return bytes; | ||||
| #else | ||||
|     const size_t x = sizeof(void *) - 1; | ||||
|     return (bytes + x) & ~x; | ||||
| #endif | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   char *strdup(const char *, size_t); | ||||
|  | ||||
|   // Default value of nesting limit of parseArray() and parseObject(). | ||||
|   // | ||||
|   // The nesting limit is a contain on the level of nesting allowed in the JSON | ||||
|   // The nesting limit is a contain on the level of nesting allowed in the | ||||
|   // JSON | ||||
|   // string. | ||||
|   // If set to 0, only a flat array or objects can be parsed. | ||||
|   // If set to 1, the object can contain nested arrays or objects but only 1 | ||||
|   // level deep. | ||||
|   // And bigger values will allow more level of nesting. | ||||
|   // | ||||
|   // The purpose of this feature is to prevent stack overflow that could lead to | ||||
|   // The purpose of this feature is to prevent stack overflow that could | ||||
|   // lead to | ||||
|   // a security risk. | ||||
|   static const uint8_t DEFAULT_LIMIT = 10; | ||||
| }; | ||||
|   | ||||
| @@ -21,11 +21,10 @@ class StaticJsonBuffer : public JsonBuffer { | ||||
|   size_t capacity() const { return CAPACITY; } | ||||
|   size_t size() const { return _size; } | ||||
|  | ||||
|  protected: | ||||
|   virtual void* alloc(size_t bytes) { | ||||
|     if (_size + bytes > CAPACITY) return NULL; | ||||
|     void* p = &_buffer[_size]; | ||||
|     _size += bytes; | ||||
|     _size += round_size_up(bytes); | ||||
|     return p; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -22,9 +22,9 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, InitialSizeIsZero) { | ||||
|  | ||||
| TEST_F(DynamicJsonBuffer_Basic_Tests, SizeIncreasesAfterAlloc) { | ||||
|   buffer.alloc(1); | ||||
|   ASSERT_EQ(1, buffer.size()); | ||||
|   ASSERT_LE(1, buffer.size()); | ||||
|   buffer.alloc(1); | ||||
|   ASSERT_EQ(2, buffer.size()); | ||||
|   ASSERT_LE(2, buffer.size()); | ||||
| } | ||||
|  | ||||
| TEST_F(DynamicJsonBuffer_Basic_Tests, ReturnDifferentPointer) { | ||||
| @@ -32,3 +32,12 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, ReturnDifferentPointer) { | ||||
|   void* p2 = buffer.alloc(2); | ||||
|   ASSERT_NE(p1, p2); | ||||
| } | ||||
|  | ||||
| TEST_F(DynamicJsonBuffer_Basic_Tests, Alignment) { | ||||
|   size_t mask = sizeof(void*) - 1; | ||||
|  | ||||
|   for (size_t size = 1; size <= sizeof(void*); size++) { | ||||
|     size_t addr = reinterpret_cast<size_t>(buffer.alloc(1)); | ||||
|     ASSERT_EQ(0, addr & mask); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,56 +0,0 @@ | ||||
| // Copyright Benoit Blanchon 2014-2015 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #define ARDUINOJSON_ENABLE_STD_STREAM | ||||
| #include <ArduinoJson.h> | ||||
|  | ||||
| #define SOURCE "{\"mqtt.host\":\"mqtt.test.com\",\"mqtt.port\":1883}" | ||||
|  | ||||
| #define SIZE_WITH_COPY (sizeof(SOURCE) + JSON_OBJECT_SIZE(2)) | ||||
| #define SIZE_WITHOUT_COPY (JSON_OBJECT_SIZE(2)) | ||||
|  | ||||
| template <int N, typename S> | ||||
| void mustSucceedWith(S source) { | ||||
|   StaticJsonBuffer<N> jsonBuffer; | ||||
|   ASSERT_TRUE(jsonBuffer.parseObject(source).success()); | ||||
| } | ||||
|  | ||||
| template <int N, typename S> | ||||
| void mustFailWith(S source) { | ||||
|   StaticJsonBuffer<N> jsonBuffer; | ||||
|   ASSERT_FALSE(jsonBuffer.parseObject(source).success()); | ||||
| } | ||||
|  | ||||
| TEST(Issue104, CharPtrSucceeds) { | ||||
|   char source[] = SOURCE; | ||||
|   mustSucceedWith<SIZE_WITHOUT_COPY, char *>(source); | ||||
| } | ||||
|  | ||||
| TEST(Issue104, CharPtrFails) { | ||||
|   char source[] = SOURCE; | ||||
|   mustFailWith<SIZE_WITHOUT_COPY - 1, char *>(source); | ||||
| } | ||||
|  | ||||
| TEST(Issue104, ConstCharPtrSucceeds) { | ||||
|   mustSucceedWith<SIZE_WITH_COPY, const char *>(SOURCE); | ||||
| } | ||||
|  | ||||
| TEST(Issue104, ConstCharPtrFails) { | ||||
|   mustFailWith<SIZE_WITH_COPY - 1, const char *>(SOURCE); | ||||
| } | ||||
|  | ||||
| TEST(Issue104, StringSucceeds) { | ||||
|   mustSucceedWith<SIZE_WITH_COPY, const String &>(SOURCE); | ||||
| } | ||||
|  | ||||
| TEST(Issue104, StringFails) { | ||||
|   mustFailWith<SIZE_WITH_COPY - 1, const String &>(SOURCE); | ||||
| } | ||||
|  | ||||
| TEST(Issue104, TooSmallForStrDup) { | ||||
|   mustFailWith<sizeof(SOURCE) - 1, const char *>(SOURCE); | ||||
| } | ||||
| @@ -13,11 +13,11 @@ using namespace ArduinoJson; | ||||
|  | ||||
| class StaticJsonBuffer_Basic_Tests : public testing::Test { | ||||
|  protected: | ||||
|   StaticJsonBuffer<42> buffer; | ||||
|   StaticJsonBuffer<64> buffer; | ||||
| }; | ||||
|  | ||||
| TEST_F(StaticJsonBuffer_Basic_Tests, CapacityMatchTemplateParameter) { | ||||
|   ASSERT_EQ(42, buffer.capacity()); | ||||
|   ASSERT_EQ(64, buffer.capacity()); | ||||
| } | ||||
|  | ||||
| TEST_F(StaticJsonBuffer_Basic_Tests, InitialSizeIsZero) { | ||||
| @@ -26,34 +26,43 @@ TEST_F(StaticJsonBuffer_Basic_Tests, InitialSizeIsZero) { | ||||
|  | ||||
| TEST_F(StaticJsonBuffer_Basic_Tests, GrowsAfterAlloc) { | ||||
|   buffer.alloc(1); | ||||
|   ASSERT_EQ(1, buffer.size()); | ||||
|   ASSERT_LE(1, buffer.size()); | ||||
|   buffer.alloc(1); | ||||
|   ASSERT_EQ(2, buffer.size()); | ||||
|   ASSERT_LE(2, buffer.size()); | ||||
| } | ||||
|  | ||||
| TEST_F(StaticJsonBuffer_Basic_Tests, DoesntGrowWhenFull) { | ||||
|   buffer.alloc(42); | ||||
|   buffer.alloc(64); | ||||
|   buffer.alloc(1); | ||||
|   ASSERT_EQ(42, buffer.size()); | ||||
|   ASSERT_EQ(64, buffer.size()); | ||||
| } | ||||
|  | ||||
| TEST_F(StaticJsonBuffer_Basic_Tests, DoesntGrowWhenTooSmall) { | ||||
|   buffer.alloc(43); | ||||
|   buffer.alloc(65); | ||||
|   ASSERT_EQ(0, buffer.size()); | ||||
| } | ||||
|  | ||||
| TEST_F(StaticJsonBuffer_Basic_Tests, ReturnsNonNull) { | ||||
|   void *p = buffer.alloc(42); | ||||
|   void *p = buffer.alloc(64); | ||||
|   ASSERT_NE(static_cast<void *>(0), p); | ||||
| } | ||||
|  | ||||
| TEST_F(StaticJsonBuffer_Basic_Tests, ReturnsNullWhenFull) { | ||||
|   buffer.alloc(42); | ||||
|   buffer.alloc(64); | ||||
|   void *p = buffer.alloc(1); | ||||
|   ASSERT_EQ(NULL, p); | ||||
| } | ||||
|  | ||||
| TEST_F(StaticJsonBuffer_Basic_Tests, ReturnsNullWhenTooSmall) { | ||||
|   void *p = buffer.alloc(43); | ||||
|   void *p = buffer.alloc(65); | ||||
|   ASSERT_EQ(NULL, p); | ||||
| } | ||||
|  | ||||
| TEST_F(StaticJsonBuffer_Basic_Tests, Alignment) { | ||||
|   size_t mask = sizeof(void *) - 1; | ||||
|  | ||||
|   for (size_t size = 1; size <= sizeof(void *); size++) { | ||||
|     size_t addr = reinterpret_cast<size_t>(buffer.alloc(1)); | ||||
|     ASSERT_EQ(0, addr & mask); | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user