Skip to content

Bug: Self-move-assignment in RE2::Set and FilteredRE2 causes use-after-destroy #615

@MarkLee131

Description

@MarkLee131

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions