Merge pull request #1503 from ylavic/sub_value_assignment

Fix (Sub-)Value assignment
This commit is contained in:
Milo Yip 2021-04-07 17:52:51 +08:00 committed by GitHub
commit 7d801bbe45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 3 deletions

View File

@ -916,8 +916,13 @@ public:
*/
GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
if (RAPIDJSON_LIKELY(this != &rhs)) {
// Can't destroy "this" before assigning "rhs", otherwise "rhs"
// could be used after free if it's an sub-Value of "this",
// hence the temporary danse.
GenericValue temp;
temp.RawAssign(rhs);
this->~GenericValue();
RawAssign(rhs);
RawAssign(temp);
}
return *this;
}

View File

@ -325,6 +325,8 @@ TEST(Document, Swap) {
EXPECT_TRUE(d1.IsNull());
// reset document, including allocator
// so clear o before so that it doesnt contain dangling elements
o.Clear();
Document().Swap(d2);
EXPECT_TRUE(d2.IsNull());
EXPECT_NE(&d2.GetAllocator(), &a);

View File

@ -1078,9 +1078,9 @@ static void TestArray(T& x, Allocator& allocator) {
}
TEST(Value, Array) {
Value::AllocatorType allocator;
Value x(kArrayType);
const Value& y = x;
Value::AllocatorType allocator;
EXPECT_EQ(kArrayType, x.GetType());
EXPECT_TRUE(x.IsArray());
@ -1119,6 +1119,16 @@ TEST(Value, Array) {
z.SetArray();
EXPECT_TRUE(z.IsArray());
EXPECT_TRUE(z.Empty());
// PR #1503: assign from inner Value
{
CrtAllocator a; // Free() is not a noop
GenericValue<UTF8<>, CrtAllocator> nullValue;
GenericValue<UTF8<>, CrtAllocator> arrayValue(kArrayType);
arrayValue.PushBack(nullValue, a);
arrayValue = arrayValue[0]; // shouldn't crash (use after free)
EXPECT_TRUE(arrayValue.IsNull());
}
}
TEST(Value, ArrayHelper) {
@ -1481,9 +1491,9 @@ static void TestObject(T& x, Allocator& allocator) {
}
TEST(Value, Object) {
Value::AllocatorType allocator;
Value x(kObjectType);
const Value& y = x; // const version
Value::AllocatorType allocator;
EXPECT_EQ(kObjectType, x.GetType());
EXPECT_TRUE(x.IsObject());