Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/rapidjson/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -1693,7 +1693,8 @@ class GenericValue {
*/
GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
RAPIDJSON_ASSERT(IsArray());
if (newCapacity > data_.a.capacity) {
if (newCapacity > data_.a.capacity && (newCapacity <= (std::numeric_limits<SizeType>::max)() / sizeof(GenericValue))
&& (newCapacity <= PTRDIFF_MAX / sizeof(GenericValue))) {
SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))));
data_.a.capacity = newCapacity;
}
Expand Down
53 changes: 53 additions & 0 deletions test/unittest/documenttest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,59 @@ TEST(Document, UTF16_Document) {
EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.GetStringLength() + 1) * sizeof(wchar_t)));
}

// Issue 1993: Potential integer overflow in GenericValue::Reserve
TEST(Document, Reserve) {
GenericDocument<UTF8<>, CrtAllocator> json1;
json1.SetArray();
CrtAllocator s_CrtAllocator;

SizeType newCapacityNormal = 10;
json1.Reserve(newCapacityNormal, s_CrtAllocator);
EXPECT_EQ(newCapacityNormal, json1.Capacity());

SizeType newCapacityNormalBigger = 20;
json1.Reserve(newCapacityNormalBigger, s_CrtAllocator);
EXPECT_EQ(newCapacityNormalBigger, json1.Capacity());

SizeType newCapacityNormalSmaller = 15;
json1.Reserve(newCapacityNormalSmaller, s_CrtAllocator);
EXPECT_EQ(newCapacityNormalBigger, json1.Capacity());

#if !RAPIDJSON_64BIT
// Create another document for enough space
GenericDocument<UTF8<>, CrtAllocator> json2;
json2.SetArray();

// PTRDIFF_MAX if bigger than (std::numeric_limits<SizeType>::max)() in 64BIT environment
SizeType newCapacityBoundary = PTRDIFF_MAX / sizeof(GenericValue<UTF8<>>);
json2.Reserve(newCapacityBoundary, s_CrtAllocator);
EXPECT_EQ(newCapacityBoundary, json2.Capacity());
#endif

// Create another document for enough space
GenericDocument<UTF8<>, CrtAllocator> json3;
json3.SetArray();
#if !RAPIDJSON_64BIT
SizeType oldCapacity = json3.Capacity();
#endif

SizeType newCapacityMaxSize = (std::numeric_limits<SizeType>::max)() / sizeof(GenericValue<UTF8<>>);
json3.Reserve(newCapacityMaxSize, s_CrtAllocator);
#if RAPIDJSON_64BIT
EXPECT_EQ(newCapacityMaxSize, json3.Capacity());
#else
EXPECT_EQ(oldCapacity, json3.Capacity());
#endif

SizeType newCapacityLarge = (std::numeric_limits<SizeType>::max)();
json3.Reserve(newCapacityLarge, s_CrtAllocator);
#if RAPIDJSON_64BIT
EXPECT_EQ(newCapacityMaxSize, json3.Capacity());
#else
EXPECT_EQ(oldCapacity, json3.Capacity());
#endif
}

#if RAPIDJSON_HAS_CXX11_RVALUE_REFS

#if 0 // Many old compiler does not support these. Turn it off temporaily.
Expand Down