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

Reply via email to