From 23e66713a43e80a54b0b4e37791f1dfbd136ef93 Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Wed, 4 Oct 2023 18:14:13 +0200 Subject: [PATCH 1/4] [libc++] Use correct size for deallocation of arrays in shared_ptr Fixes #68051. Current implementation passes the number of `_AlignedStorage` objects when it calls to `allocate` and the number of **bytes** on deallocate. This only applies to allocations that allocate control block and the storage together, i.e. `make_shared` and `allocate_shared`. Found by ASan. --- libcxx/include/__memory/shared_ptr.h | 5 ++-- .../libcxx/memory/shared_ptr_array.pass.cpp | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index 33a1b95a31ddb..d9ddb8a17be27 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -1137,7 +1137,8 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count __alloc_.~_Alloc(); size_t __size = __unbounded_array_control_block::__bytes_for(__count_); _AlignedStorage* __storage = reinterpret_cast<_AlignedStorage*>(this); - allocator_traits<_StorageAlloc>::deallocate(__tmp, _PointerTraits::pointer_to(*__storage), __size); + allocator_traits<_StorageAlloc>::deallocate( + __tmp, _PointerTraits::pointer_to(*__storage), __size / sizeof(_AlignedStorage)); } _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_; @@ -1220,7 +1221,7 @@ struct __bounded_array_control_block<_Tp[_Count], _Alloc> _ControlBlockAlloc __tmp(__alloc_); __alloc_.~_Alloc(); - allocator_traits<_ControlBlockAlloc>::deallocate(__tmp, _PointerTraits::pointer_to(*this), sizeof(*this)); + allocator_traits<_ControlBlockAlloc>::deallocate(__tmp, _PointerTraits::pointer_to(*this), 1); } _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_; diff --git a/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp new file mode 100644 index 0000000000000..f885c7344e41b --- /dev/null +++ b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// REQUIRES: -fsized-deallocation +// ADDITIONAL_COMPILE_FLAGS: -fsized-deallocation + +// This test will fail with ASan if the implementation passes different sizes +// to corresponding allocation and deallocation functions. + +#include + +int main() { + std::allocate_shared(std::allocator{}, 10); + std::make_shared(10); + + std::allocate_shared(std::allocator{}); + std::make_shared(); +} From 000d933843289a0c78780ee59ac280f6fa63ba7c Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Wed, 4 Oct 2023 18:49:05 +0200 Subject: [PATCH 2/4] fixup! [libc++] Use correct size for deallocation of arrays in shared_ptr Reformat the test file. --- libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp index f885c7344e41b..04f534a37165d 100644 --- a/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp +++ b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp @@ -17,9 +17,9 @@ #include int main() { - std::allocate_shared(std::allocator{}, 10); - std::make_shared(10); + std::allocate_shared(std::allocator{}, 10); + std::make_shared(10); - std::allocate_shared(std::allocator{}); - std::make_shared(); + std::allocate_shared(std::allocator{}); + std::make_shared(); } From 7e79214e0d14854261039bca87088800980c2dcf Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Thu, 5 Oct 2023 10:54:23 +0200 Subject: [PATCH 3/4] fixup! [libc++] Use correct size for deallocation of arrays in shared_ptr - use full signature in main - return 0 --- libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp index 04f534a37165d..bbc7811352281 100644 --- a/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp +++ b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp @@ -16,10 +16,12 @@ #include -int main() { +int main(int, char**) { std::allocate_shared(std::allocator{}, 10); std::make_shared(10); std::allocate_shared(std::allocator{}); std::make_shared(); + + return 0; } From 049fa20792b706781c9b02e17e01c5bfbc81744a Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Thu, 5 Oct 2023 11:00:04 +0200 Subject: [PATCH 4/4] fixup! [libc++] Use correct size for deallocation of arrays in shared_ptr use int instead of int64_t to avoid the need for an include --- libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp index bbc7811352281..772198304b415 100644 --- a/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp +++ b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp @@ -17,11 +17,11 @@ #include int main(int, char**) { - std::allocate_shared(std::allocator{}, 10); - std::make_shared(10); + std::allocate_shared(std::allocator{}, 10); + std::make_shared(10); - std::allocate_shared(std::allocator{}); - std::make_shared(); + std::allocate_shared(std::allocator{}); + std::make_shared(); return 0; }