aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Biryukov <ibiryukov@google.com>2023-10-05 15:27:58 +0200
committerTobias Hieta <tobias@hieta.se>2023-11-20 09:50:27 +0100
commitb5cbb35408a3901900dc2b2ca6adda80a77ea093 (patch)
treeef8bcc9200cb983f96b5da2be987699711200028
parente6de86cb9ef868c652d8932db2c08f953f47a1e2 (diff)
downloadllvm-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.h5
-rw-r--r--libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp27
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;
+}