| 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