forked from bblanchon/ArduinoJson
Fix integer overflow in MsgPackDeserializer
This commit is contained in:
@ -112,6 +112,15 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 2") {
|
|||||||
REQUIRE(err == DeserializationError::NoMemory);
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://oss-fuzz.com/testcase?key=5354792971993088
|
||||||
|
SECTION("doesn't overflow if binary size == 0xFFFF") {
|
||||||
|
auto input = "\xc5\xff\xff"_s;
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("returns Ok if extension size <= 65531") {
|
SECTION("returns Ok if extension size <= 65531") {
|
||||||
auto input = "\xc8\xff\xfb\x01" + std::string(65531, '?');
|
auto input = "\xc8\xff\xfb\x01" + std::string(65531, '?');
|
||||||
|
|
||||||
@ -120,7 +129,7 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 2") {
|
|||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("returns NoMemory if binary size >= 65532") {
|
SECTION("returns NoMemory if extension size >= 65532") {
|
||||||
auto input = "\xc8\xff\xfc\x01" + std::string(65532, '?');
|
auto input = "\xc8\xff\xfc\x01" + std::string(65532, '?');
|
||||||
|
|
||||||
auto err = deserializeMsgPack(doc, input);
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
@ -72,6 +72,23 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 4") {
|
|||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://oss-fuzz.com/testcase?key=5354792971993088
|
||||||
|
SECTION("doesn't overflow if binary size == 0xFFFFFFFF") {
|
||||||
|
auto input = "\xc6\xff\xff\xff\xff"_s;
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("doesn't overflow if string size == 0xFFFFFFFF") {
|
||||||
|
auto input = "\xdb\xff\xff\xff\xff???????????????????"_s;
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err != DeserializationError::Ok);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("bin 32 deserialization") {
|
SECTION("bin 32 deserialization") {
|
||||||
|
@ -35,8 +35,10 @@ struct StringNode {
|
|||||||
static StringNode* create(size_t length, Allocator* allocator) {
|
static StringNode* create(size_t length, Allocator* allocator) {
|
||||||
if (length > maxLength)
|
if (length > maxLength)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
auto node = reinterpret_cast<StringNode*>(
|
auto size = sizeForLength(length);
|
||||||
allocator->allocate(sizeForLength(length)));
|
if (size < length) // integer overflow
|
||||||
|
return nullptr; // (not testable on 64-bit)
|
||||||
|
auto node = reinterpret_cast<StringNode*>(allocator->allocate(size));
|
||||||
if (node) {
|
if (node) {
|
||||||
node->length = length_type(length);
|
node->length = length_type(length);
|
||||||
node->references = 1;
|
node->references = 1;
|
||||||
|
@ -198,8 +198,13 @@ class MsgPackDeserializer {
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
uint32_t size32 = 0;
|
||||||
for (size_t i = 0; i < sizeBytes; i++)
|
for (size_t i = 0; i < sizeBytes; i++)
|
||||||
size = (size << 8) | header[i + 1];
|
size32 = (size32 << 8) | header[i + 1];
|
||||||
|
|
||||||
|
size = size_t(size32);
|
||||||
|
if (size < size32) // integer overflow
|
||||||
|
return DeserializationError::NoMemory; // (not testable on 32/64-bit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// array 16, 32 and fixarray
|
// array 16, 32 and fixarray
|
||||||
@ -366,7 +371,11 @@ class MsgPackDeserializer {
|
|||||||
DeserializationError::Code readRawString(VariantData* variant,
|
DeserializationError::Code readRawString(VariantData* variant,
|
||||||
const void* header,
|
const void* header,
|
||||||
uint8_t headerSize, size_t n) {
|
uint8_t headerSize, size_t n) {
|
||||||
char* p = stringBuffer_.reserve(headerSize + n);
|
auto totalSize = size_t(headerSize + n);
|
||||||
|
if (totalSize < n) // integer overflow
|
||||||
|
return DeserializationError::NoMemory; // (not testable on 64-bit)
|
||||||
|
|
||||||
|
char* p = stringBuffer_.reserve(totalSize);
|
||||||
if (!p)
|
if (!p)
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user