| Issue |
169765
|
| Summary |
[libcxx] memset past the end of allocated memory in shared_ptr
|
| Labels |
bug,
libc++
|
| Assignees |
|
| Reporter |
s-barannikov
|
https://gcc.godbolt.org/z/a73eGf3qo
```C++
#include <memory>
int main() {
using Array = char[][3];
std::shared_ptr<Array> ptr = std::make_shared<Array>(3);
}
```
Compiled with `-stdlib=libc++ -O1 -std=c++26 -emit-llvm -fno-exceptions`
```
define dso_local noundef i32 @main() local_unnamed_addr #0 {
%1 = tail call noalias noundef nonnull dereferenceable(40) ptr @operator new(unsigned long)(i64 noundef 40) #6
store ptr getelementptr inbounds nuw inrange(-16, 24) (i8, ptr @vtable for std::__1::__shared_count, i64 16), ptr %1, align 8
%2 = getelementptr inbounds nuw i8, ptr %1, i64 8
store i64 0, ptr %2, align 8
store ptr getelementptr inbounds nuw inrange(-16, 40) (i8, ptr @vtable for std::__1::__shared_weak_count, i64 16), ptr %1, align 8
%3 = getelementptr inbounds nuw i8, ptr %1, i64 16
store i64 0, ptr %3, align 8
store ptr getelementptr inbounds nuw inrange(-16, 40) (i8, ptr @vtable for std::__1::__unbounded_array_control_block<char [][3], std::__1::allocator<char [][3]>>, i64 16), ptr %1, align 8
%4 = getelementptr inbounds nuw i8, ptr %1, i64 24
store i64 3, ptr %4, align 8
%5 = getelementptr inbounds nuw i8, ptr %1, i64 32
tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(9) %5, i8 0, i64 9, i1 false)
%6 = atomicrmw add ptr %2, i64 -1 acq_rel, align 8
%7 = icmp eq i64 %6, 0
br i1 %7, label %8, label %12
8:
%9 = load ptr, ptr %1, align 8
%10 = getelementptr inbounds nuw i8, ptr %9, i64 16
%11 = load ptr, ptr %10, align 8
tail call void %11(ptr noundef nonnull align 8 dereferenceable(24) %1) #7
tail call void @std::__1::__shared_weak_count::__release_weak()(ptr noundef nonnull align 8 dereferenceable(24) %1) #7
br label %12
12:
ret i32 0
}
```
As can be seen, `operator new` allocates 40 bytes, but `memset` overwrites 9 bytes starting from byte 32.
32 + 9 = 41 is greater than the allocation size.
I think the bug is near here: https://github.com/llvm/llvm-project/blob/3f151a3fa6ccb00523d8e0e36fa8d9046d5a936f/libcxx/include/__memory/shared_ptr.h#L809
Either `__bytes_for` should account for control block alignment, or the division should be ceiling, not sure which is correct.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs