Skip to content

[StaticAnalyzer] A Static Analyzer bug related to initializing [[__no_unique_address__]] fields #137252

Open
@ziqingluo-90

Description

@ziqingluo-90

Hi Static Analyzer Developers,

I was investigating a downstream bug arose from C++ standard library changes.
There is a minimal reproducer:

// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus -verify %s

namespace std {
  struct default_delete {
  };

  template <class _Tp, class _Dp = default_delete >
  class unique_ptr {
    [[__no_unique_address__]]  _Tp * __ptr_;
    [[__no_unique_address__]] _Dp __deleter_;

  public:
    explicit unique_ptr(_Tp* __p) noexcept
      : __ptr_(__p),
        __deleter_() {}

    ~unique_ptr() {
      delete __ptr_;
    }
  };
}

struct X {};

int main()
{
    std::unique_ptr<X> a(new X());          // leak reported                                                                                                                                           
    return 0;
}

From what I observed, the two fields __ptr_ and __deleter_ have overlapping MemRegions (Same base and both have 0 offset) because of [[no_unique_address]]. Then, at the unique_ptr constructor call, CSA simulates the following two steps:

  1. assigning __p to __ptr_; and then
  2. assigning 0 to __deleter_.

Since the two fields have overlapping MemRegions, the second assignment removes the binding of __ptr_. So later the destructor is not able to delete the allocated object properly. Resulting a false leak report.

If one removes [[no_unique_address]] from __deleter_'s declaration, the false report goes away.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions