Safer GenericValue& operator=(GenericValue& rhs).

When rhs is a sub-Value of *this, destroying *this also destroys/frees
rhs, thus the following RawAssign(rhs) crashes.

Address this by saving/moving rhs to a temporary first, which clears rhs
and avoids its destruction with *this.

The crash can be reproduced in test Value.MergeDuplicateKey by using the
CrtAllocator instead of the default Document's MemoryPoolAllocator.
This commit is contained in:
ylavic 2019-04-27 03:41:19 +02:00
parent 1c2c8e085a
commit c033292aea

View File

@ -916,8 +916,13 @@ public:
*/ */
GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
if (RAPIDJSON_LIKELY(this != &rhs)) { 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(); this->~GenericValue();
RawAssign(rhs); RawAssign(temp);
} }
return *this; return *this;
} }