1*c27415ffSFangrui Song // RUN: %clangxx_scudo %s -o %t 2f7c5c0d8SMitch Phillips // RUN: %run %t valid 2>&1 3f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1 4f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t invalid 2>&1 | FileCheck %s 5f7c5c0d8SMitch Phillips 6f7c5c0d8SMitch Phillips // Tests that the C++17 aligned new/delete operators are working as expected. 7f7c5c0d8SMitch Phillips // Currently we do not check the consistency of the alignment on deallocation, 8f7c5c0d8SMitch Phillips // so this just tests that the APIs work. 9f7c5c0d8SMitch Phillips 10f7c5c0d8SMitch Phillips #include <assert.h> 11f7c5c0d8SMitch Phillips #include <stdint.h> 12f7c5c0d8SMitch Phillips #include <stdio.h> 13f7c5c0d8SMitch Phillips #include <string.h> 14f7c5c0d8SMitch Phillips 15f7c5c0d8SMitch Phillips // Define all new/delete to not depend on the version provided by the platform. 16f7c5c0d8SMitch Phillips 17f7c5c0d8SMitch Phillips namespace std { 18f7c5c0d8SMitch Phillips struct nothrow_t {}; 19f7c5c0d8SMitch Phillips static const nothrow_t nothrow; 20f7c5c0d8SMitch Phillips enum class align_val_t : size_t {}; 21f7c5c0d8SMitch Phillips } // namespace std 22f7c5c0d8SMitch Phillips 23f7c5c0d8SMitch Phillips void *operator new(size_t); 24f7c5c0d8SMitch Phillips void *operator new[](size_t); 25f7c5c0d8SMitch Phillips void *operator new(size_t, std::nothrow_t const &); 26f7c5c0d8SMitch Phillips void *operator new[](size_t, std::nothrow_t const &); 27f7c5c0d8SMitch Phillips void *operator new(size_t, std::align_val_t); 28f7c5c0d8SMitch Phillips void *operator new[](size_t, std::align_val_t); 29f7c5c0d8SMitch Phillips void *operator new(size_t, std::align_val_t, std::nothrow_t const &); 30f7c5c0d8SMitch Phillips void *operator new[](size_t, std::align_val_t, std::nothrow_t const &); 31f7c5c0d8SMitch Phillips 32f7c5c0d8SMitch Phillips void operator delete(void *) throw(); 33f7c5c0d8SMitch Phillips void operator delete[](void *) throw(); 34f7c5c0d8SMitch Phillips void operator delete(void *, std::nothrow_t const &); 35f7c5c0d8SMitch Phillips void operator delete[](void *, std::nothrow_t const &); 36f7c5c0d8SMitch Phillips void operator delete(void *, size_t) throw(); 37f7c5c0d8SMitch Phillips void operator delete[](void *, size_t) throw(); 38f7c5c0d8SMitch Phillips void operator delete(void *, std::align_val_t) throw(); 39f7c5c0d8SMitch Phillips void operator delete[](void *, std::align_val_t) throw(); 40f7c5c0d8SMitch Phillips void operator delete(void *, std::align_val_t, std::nothrow_t const &); 41f7c5c0d8SMitch Phillips void operator delete[](void *, std::align_val_t, std::nothrow_t const &); 42f7c5c0d8SMitch Phillips void operator delete(void *, size_t, std::align_val_t) throw(); 43f7c5c0d8SMitch Phillips void operator delete[](void *, size_t, std::align_val_t) throw(); 44f7c5c0d8SMitch Phillips 45f7c5c0d8SMitch Phillips template <typename T> 46f7c5c0d8SMitch Phillips inline T *break_optimization(T *arg) { 47f7c5c0d8SMitch Phillips __asm__ __volatile__("" 48f7c5c0d8SMitch Phillips : 49f7c5c0d8SMitch Phillips : "r"(arg) 50f7c5c0d8SMitch Phillips : "memory"); 51f7c5c0d8SMitch Phillips return arg; 52f7c5c0d8SMitch Phillips } 53f7c5c0d8SMitch Phillips 54f7c5c0d8SMitch Phillips struct S12 { 55f7c5c0d8SMitch Phillips int a, b, c; 56f7c5c0d8SMitch Phillips }; 57f7c5c0d8SMitch Phillips struct alignas(128) S12_128 { 58f7c5c0d8SMitch Phillips int a, b, c; 59f7c5c0d8SMitch Phillips }; 60f7c5c0d8SMitch Phillips struct alignas(256) S12_256 { 61f7c5c0d8SMitch Phillips int a, b, c; 62f7c5c0d8SMitch Phillips }; 63f7c5c0d8SMitch Phillips struct alignas(512) S1024_512 { 64f7c5c0d8SMitch Phillips char a[1024]; 65f7c5c0d8SMitch Phillips }; 66f7c5c0d8SMitch Phillips struct alignas(1024) S1024_1024 { 67f7c5c0d8SMitch Phillips char a[1024]; 68f7c5c0d8SMitch Phillips }; 69f7c5c0d8SMitch Phillips 70f7c5c0d8SMitch Phillips int main(int argc, char **argv) { 71f7c5c0d8SMitch Phillips assert(argc == 2); 72f7c5c0d8SMitch Phillips 73f7c5c0d8SMitch Phillips if (!strcmp(argv[1], "valid")) { 74f7c5c0d8SMitch Phillips // Standard use case. 75f7c5c0d8SMitch Phillips delete break_optimization(new S12); 76f7c5c0d8SMitch Phillips delete break_optimization(new S12_128); 77f7c5c0d8SMitch Phillips delete[] break_optimization(new S12_128[4]); 78f7c5c0d8SMitch Phillips delete break_optimization(new S12_256); 79f7c5c0d8SMitch Phillips delete break_optimization(new S1024_512); 80f7c5c0d8SMitch Phillips delete[] break_optimization(new S1024_512[4]); 81f7c5c0d8SMitch Phillips delete break_optimization(new S1024_1024); 82f7c5c0d8SMitch Phillips 83f7c5c0d8SMitch Phillips // Call directly the aligned versions of the operators. 84f7c5c0d8SMitch Phillips const size_t alignment = 1U << 8; 85f7c5c0d8SMitch Phillips void *p = operator new(1, static_cast<std::align_val_t>(alignment)); 86f7c5c0d8SMitch Phillips assert((reinterpret_cast<uintptr_t>(p) & (alignment - 1)) == 0); 87f7c5c0d8SMitch Phillips operator delete(p, static_cast<std::align_val_t>(alignment)); 88f7c5c0d8SMitch Phillips } 89f7c5c0d8SMitch Phillips if (!strcmp(argv[1], "invalid")) { 90f7c5c0d8SMitch Phillips // Alignment must be a power of 2. 91f7c5c0d8SMitch Phillips const size_t alignment = (1U << 8) - 1; 92f7c5c0d8SMitch Phillips void *p = operator new(1, static_cast<std::align_val_t>(alignment), 93f7c5c0d8SMitch Phillips std::nothrow); 94f7c5c0d8SMitch Phillips // CHECK: Scudo ERROR: invalid allocation alignment 95f7c5c0d8SMitch Phillips assert(!p); 96f7c5c0d8SMitch Phillips } 97f7c5c0d8SMitch Phillips 98f7c5c0d8SMitch Phillips return 0; 99f7c5c0d8SMitch Phillips } 100