[libcxx-commits] [libcxx] [libc++] Use correct size for deallocation of arrays in shared_ptr (PR #68233)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Oct 4 09:46:21 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/68233.diff


2 Files Affected:

- (modified) libcxx/include/__memory/shared_ptr.h (+3-2) 
- (added) libcxx/test/libcxx/memory/shared_ptr_array.pass.cpp (+25) 


``````````diff
diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index 33a1b95a31ddbd5..d9ddb8a17be273f 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 000000000000000..f885c7344e41b9b
--- /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 <memory>
+
+int main() {
+    std::allocate_shared<int64_t[]>(std::allocator<int64_t>{}, 10);
+    std::make_shared<int64_t[]>(10);
+
+    std::allocate_shared<int64_t[10]>(std::allocator<int64_t>{});
+    std::make_shared<int64_t[10]>();
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/68233


More information about the libcxx-commits mailing list