Skip to content

Commit 7d801bb

Browse files
authored
Merge pull request Tencent#1503 from ylavic/sub_value_assignment
Fix (Sub-)Value assignment
2 parents 03676c9 + 117276c commit 7d801bb

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

include/rapidjson/document.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -916,8 +916,13 @@ class GenericValue {
916916
*/
917917
GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
918918
if (RAPIDJSON_LIKELY(this != &rhs)) {
919+
// Can't destroy "this" before assigning "rhs", otherwise "rhs"
920+
// could be used after free if it's an sub-Value of "this",
921+
// hence the temporary danse.
922+
GenericValue temp;
923+
temp.RawAssign(rhs);
919924
this->~GenericValue();
920-
RawAssign(rhs);
925+
RawAssign(temp);
921926
}
922927
return *this;
923928
}

test/unittest/documenttest.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ TEST(Document, Swap) {
325325
EXPECT_TRUE(d1.IsNull());
326326

327327
// reset document, including allocator
328+
// so clear o before so that it doesnt contain dangling elements
329+
o.Clear();
328330
Document().Swap(d2);
329331
EXPECT_TRUE(d2.IsNull());
330332
EXPECT_NE(&d2.GetAllocator(), &a);

test/unittest/valuetest.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,9 +1078,9 @@ static void TestArray(T& x, Allocator& allocator) {
10781078
}
10791079

10801080
TEST(Value, Array) {
1081+
Value::AllocatorType allocator;
10811082
Value x(kArrayType);
10821083
const Value& y = x;
1083-
Value::AllocatorType allocator;
10841084

10851085
EXPECT_EQ(kArrayType, x.GetType());
10861086
EXPECT_TRUE(x.IsArray());
@@ -1119,6 +1119,16 @@ TEST(Value, Array) {
11191119
z.SetArray();
11201120
EXPECT_TRUE(z.IsArray());
11211121
EXPECT_TRUE(z.Empty());
1122+
1123+
// PR #1503: assign from inner Value
1124+
{
1125+
CrtAllocator a; // Free() is not a noop
1126+
GenericValue<UTF8<>, CrtAllocator> nullValue;
1127+
GenericValue<UTF8<>, CrtAllocator> arrayValue(kArrayType);
1128+
arrayValue.PushBack(nullValue, a);
1129+
arrayValue = arrayValue[0]; // shouldn't crash (use after free)
1130+
EXPECT_TRUE(arrayValue.IsNull());
1131+
}
11221132
}
11231133

11241134
TEST(Value, ArrayHelper) {
@@ -1481,9 +1491,9 @@ static void TestObject(T& x, Allocator& allocator) {
14811491
}
14821492

14831493
TEST(Value, Object) {
1494+
Value::AllocatorType allocator;
14841495
Value x(kObjectType);
14851496
const Value& y = x; // const version
1486-
Value::AllocatorType allocator;
14871497

14881498
EXPECT_EQ(kObjectType, x.GetType());
14891499
EXPECT_TRUE(x.IsObject());

0 commit comments

Comments
 (0)