Commit b5cbb354 authored by Ilya Biryukov's avatar Ilya Biryukov Committed by Tobias Hieta
Browse files

[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 f722db02)
parent e6de86cb
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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_;
+27 −0
Original line number Diff line number Diff line
//===----------------------------------------------------------------------===//
//
// 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;
}