Skip to content

std::allocate_shared & std::make_shared for arrays causes new-delete-size-mismatch under asan  #68051

Closed
@rupprecht

Description

@rupprecht

The following snippet yields a new/delete type mismatch when building with sized deallocation:

int main(int argc, char *argv[]) {
    std::allocate_shared<int64_t[]>(std::allocator<int64_t>{}, 1);
}

It runs fine with -stdlib=libc++ -fsanitize=address -std=c++20, but fails when adding -fsized-deallocation. Asan stack trace:

=================================================================
==1==ERROR: AddressSanitizer: new-delete-type-mismatch on 0x504000000050 in thread T0:
  object passed to delete has wrong type:
  size of the allocated type:   40 bytes;
  size of the deallocated type: 320 bytes.
    #0 0x561aa17a18d2 in operator delete(void*, unsigned long) /root/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:164:3
    #1 0x561aa17a4f6c in void std::__1::__libcpp_operator_delete[abi:v180000]<void*, unsigned long>(void*, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/new:282:3
    #2 0x561aa17a4f0c in void std::__1::__do_deallocate_handle_size[abi:v180000]<>(void*, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/new:308:10
    #3 0x561aa17a4eb4 in std::__1::__libcpp_deallocate[abi:v180000](void*, unsigned long, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/new:322:14
    #4 0x561aa17a4e39 in std::__1::allocator<std::__1::__sp_aligned_storage<8ul>>::deallocate[abi:v180000](std::__1::__sp_aligned_storage<8ul>*, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/allocator.h:130:13
    #5 0x561aa17a4df4 in std::__1::allocator_traits<std::__1::allocator<std::__1::__sp_aligned_storage<8ul>>>::deallocate[abi:v180000](std::__1::allocator<std::__1::__sp_aligned_storage<8ul>>&, std::__1::__sp_aligned_storage<8ul>*, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/allocator_traits.h:288:13
    #6 0x561aa17a4586 in std::__1::__unbounded_array_control_block<long [], std::__1::allocator<long>>::__on_zero_shared_weak() /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/shared_ptr.h:1140:9
    #7 0x561aa17a50ee in std::__1::__shared_weak_count::__release_shared[abi:v180000]() /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/shared_ptr.h:215:9
    #8 0x561aa17a31a5 in std::__1::shared_ptr<long []>::~shared_ptr[abi:v180000]() /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/shared_ptr.h:775:23
    #9 0x561aa17a305b in main /app/example.cpp:5:5
    #10 0x7f028f312082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
    #11 0x561aa16c536d in _start (/app/output.s+0x2c36d)

0x504000000050 is located 0 bytes inside of 40-byte region [0x504000000050,0x504000000078)
allocated by thread T0 here:
    #0 0x561aa17a0c6d in operator new(unsigned long) /root/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:95:3
    #1 0x561aa17a3af4 in void* std::__1::__libcpp_operator_new[abi:v180000]<unsigned long>(unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/new:272:10
    #2 0x561aa17a3a5c in std::__1::__libcpp_allocate[abi:v180000](unsigned long, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/new:298:10
    #3 0x561aa17a399c in std::__1::allocator<std::__1::__sp_aligned_storage<8ul>>::allocate[abi:v180000](unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/allocator.h:114:38
    #4 0x561aa17a392c in std::__1::allocator_traits<std::__1::allocator<std::__1::__sp_aligned_storage<8ul>>>::allocate[abi:v180000](std::__1::allocator<std::__1::__sp_aligned_storage<8ul>>&, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/allocator_traits.h:268:20
    #5 0x561aa17a3626 in std::__1::__allocation_guard<std::__1::allocator<std::__1::__sp_aligned_storage<8ul>>>::__allocation_guard[abi:v180000]<std::__1::allocator<long>>(std::__1::allocator<long>, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/allocation_guard.h:57:18
    #6 0x561aa17a3317 in std::__1::shared_ptr<long []> std::__1::__allocate_shared_unbounded_array[abi:v180000]<long [], std::__1::allocator<long>>(std::__1::allocator<long> const&, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/shared_ptr.h:1162:39
    #7 0x561aa17a30f7 in std::__1::shared_ptr<long []> std::__1::allocate_shared[abi:v180000]<long [], std::__1::allocator<long>, void>(std::__1::allocator<long> const&, unsigned long) /opt/compiler-explorer/clang-trunk-20231002/bin/../include/c++/v1/__memory/shared_ptr.h:1301:12
    #8 0x561aa17a3052 in main /app/example.cpp:5:5
    #9 0x7f028f312082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)

SUMMARY: AddressSanitizer: new-delete-type-mismatch /root/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:164:3 in operator delete(void*, unsigned long)

Live snippet: https://godbolt.org/z/ddYr6TYb1

Note: the mismatch was found by running the std::boyer_moore_searcher example snippet on cppreference: https://godbolt.org/z/Gsx6dWPYn. Likely it has the same underlying issue, although this one does not require c++20 to reproduce.

The allocation divides by sizeof(_AlignedStorage), but the deallocation does not appear to make the same adjustment. That may be the source of the issue, which could be fixed w/ something like:

--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -1137,7 +1137,9 @@
         __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));
     }

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions