Description
The move assignment operators in RE2::Set and FilteredRE2 use a destroy-then-placement-new pattern:
RE2::Set& RE2::Set::operator=(Set&& other) {
this->~Set();
(void) new (this) Set(std::move(other));
return *this;
}
This is unsafe when this == &other (self-move-assignment). The destructor runs first, which calls Decref() on internal Regexp* pointers and frees resources. Then the move constructor reads from the already-destroyed object. This is undefined behavior and can lead to double-free.
Self-move-assignment can happen through aliased references. For example:
std::vector<RE2::Set> v = ...;
v[i] = std::move(v[j]); // if i == j
Affected Code
re2/set.cc:52-56 (RE2::Set::operator=(Set&&))
re2/filtered_re2.cc:45-48 (FilteredRE2::operator=(FilteredRE2&&))
I can open PR to submit a fix.
Description
The move assignment operators in
RE2::SetandFilteredRE2use a destroy-then-placement-new pattern:This is unsafe when
this == &other(self-move-assignment). The destructor runs first, which callsDecref()on internalRegexp*pointers and frees resources. Then the move constructor reads from the already-destroyed object. This is undefined behavior and can lead to double-free.Self-move-assignment can happen through aliased references. For example:
std::vector<RE2::Set> v = ...; v[i] = std::move(v[j]); // if i == jAffected Code
re2/set.cc:52-56(RE2::Set::operator=(Set&&))re2/filtered_re2.cc:45-48(FilteredRE2::operator=(FilteredRE2&&))I can open PR to submit a fix.