diff options
author | Ilya Biryukov <ibiryukov@google.com> | 2023-10-05 15:27:58 +0200 |
---|---|---|
committer | Tobias Hieta <tobias@hieta.se> | 2023-11-20 09:50:27 +0100 |
commit | b5cbb35408a3901900dc2b2ca6adda80a77ea093 (patch) | |
tree | ef8bcc9200cb983f96b5da2be987699711200028 | |
parent | e6de86cb9ef868c652d8932db2c08f953f47a1e2 (diff) | |
download | llvm-b5cbb35408a3901900dc2b2ca6adda80a77ea093.zip llvm-b5cbb35408a3901900dc2b2ca6adda80a77ea093.tar.gz llvm-b5cbb35408a3901900dc2b2ca6adda80a77ea093.tar.bz2 |
[libc++] Use correct size for deallocation of arrays in shared_ptr (#68233)
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 under Clang combined with `-fsized-deallocation`.
(cherry picked from commit f722db02d359e29ca001b78197ee1a275f8c3d7c)
-rw-r--r-- | libcxx/include/__memory/shared_ptr.h | 5 | ||||
-rw-r--r-- | libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp | 27 |
2 files changed, 30 insertions, 2 deletions
diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index dce44a7..a5bae83 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -1134,7 +1134,8 @@ private: __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_; @@ -1217,7 +1218,7 @@ private: _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 0000000..7721983 --- /dev/null +++ b/libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 <memory> + +int main(int, char**) { + std::allocate_shared<int[]>(std::allocator<int>{}, 10); + std::make_shared<int[]>(10); + + std::allocate_shared<int[10]>(std::allocator<int>{}); + std::make_shared<int[10]>(); + + return 0; +} |