Issue 170092
Summary [libc++] std::vector<bool> uninitialized read since version 21
Labels libc++
Assignees
Reporter hahn-absint
    We have a tool that detects runtime errors due to undefined behavior.
Since an update of libc++ 21 (from 20), for the following code, we now get uninitialized variable warnings.

```
#include <vector>

int main() {
 std::vector<bool> v;
    v.reserve(32);
    // *v.__begin_ was initialized with libc++ 20, and is no more with libc++ 21
 v.push_back(1);
    // push_back trigger operator=(bool) bit masking, reading uninitialized *__seg_ (aka *v.__begin_)
    // if (__x)
    // *__seg_ |= __mask_;
}
```

In libc++ 20, reserve initializes the data via `__construct_at_end`:
```
vector<bool, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n)
```
with this line:
```
this->__begin_[0] = __storage_type(0);
```

In libc++ 21, this code is no longer there.
Note that for the above example, the new if-branch
```
  if (end().__ctz_ != 0) // Ensure uninitialized leading bits in the last word are set to zero
```
is never entered as reserve keeps the size of the vector at 0, hence `__ctz_` is 0 too.

Not sure whether this will cause issues in practice, but according to the C++ 17 standard ([dcl.init]p12), without initialization, the object with dynamic storage duration has indeterminate value.
Reading indeterminate values is undefined except for some special cases, that I think do not apply here.

The issue might be related to this pull request https://github.com/llvm/llvm-project/pull/119632

P.S.: The above example also fails with only the push_back without the reserve.
The reserve is then triggered by the push_back.
I wrote the example in a way, to highlight the point where is initialization is missing.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to