diff options
Diffstat (limited to 'test/asan/TestCases/Linux/aligned_delete_test.cc')
-rw-r--r-- | test/asan/TestCases/Linux/aligned_delete_test.cc | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/test/asan/TestCases/Linux/aligned_delete_test.cc b/test/asan/TestCases/Linux/aligned_delete_test.cc new file mode 100644 index 000000000000..5b9455e56553 --- /dev/null +++ b/test/asan/TestCases/Linux/aligned_delete_test.cc @@ -0,0 +1,168 @@ +// RUN: %clangxx_asan -std=c++1z -faligned-allocation -fsanitize-recover=address -O0 %s -o %t +// RUN: %env_asan_opts=new_delete_type_mismatch=1:halt_on_error=false:detect_leaks=false %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=new_delete_type_mismatch=0 %run %t + +// RUN: %clangxx_asan -std=c++1z -faligned-allocation -fsized-deallocation -fsanitize-recover=address -O0 %s -o %t +// RUN: %env_asan_opts=new_delete_type_mismatch=1:halt_on_error=false:detect_leaks=false %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=new_delete_type_mismatch=0 %run %t + +// REQUIRES: asan-static-runtime + +#include <stdio.h> + +// Define all new/delete to do not depend on the version provided by the +// plaform. The implementation is provided by ASan anyway. + +namespace std { +struct nothrow_t {}; +static const nothrow_t nothrow; +enum class align_val_t : size_t {}; +} // namespace std + +void *operator new(size_t); +void *operator new[](size_t); +void *operator new(size_t, std::nothrow_t const&); +void *operator new[](size_t, std::nothrow_t const&); +void *operator new(size_t, std::align_val_t); +void *operator new[](size_t, std::align_val_t); +void *operator new(size_t, std::align_val_t, std::nothrow_t const&); +void *operator new[](size_t, std::align_val_t, std::nothrow_t const&); + +void operator delete(void*) throw(); +void operator delete[](void*) throw(); +void operator delete(void*, std::nothrow_t const&); +void operator delete[](void*, std::nothrow_t const&); +void operator delete(void*, size_t) throw(); +void operator delete[](void*, size_t) throw(); +void operator delete(void*, std::align_val_t) throw(); +void operator delete[](void*, std::align_val_t) throw(); +void operator delete(void*, std::align_val_t, std::nothrow_t const&); +void operator delete[](void*, std::align_val_t, std::nothrow_t const&); +void operator delete(void*, size_t, std::align_val_t) throw(); +void operator delete[](void*, size_t, std::align_val_t) throw(); + + +template<typename T> +inline T* break_optimization(T *arg) { + __asm__ __volatile__("" : : "r" (arg) : "memory"); + return arg; +} + + +struct S12 { int a, b, c; }; +struct alignas(128) S12_128 { int a, b, c; }; +struct alignas(256) S12_256 { int a, b, c; }; +struct alignas(512) S1024_512 { char a[1024]; }; +struct alignas(1024) S1024_1024 { char a[1024]; }; + + +int main(int argc, char **argv) { + fprintf(stderr, "Testing valid cases\n"); + + delete break_optimization(new S12); + operator delete(break_optimization(new S12), std::nothrow); + delete [] break_optimization(new S12[100]); + operator delete[](break_optimization(new S12[100]), std::nothrow); + + delete break_optimization(new S12_128); + operator delete(break_optimization(new S12_128), + std::align_val_t(alignof(S12_128))); + operator delete(break_optimization(new S12_128), + std::align_val_t(alignof(S12_128)), std::nothrow); + operator delete(break_optimization(new S12_128), sizeof(S12_128), + std::align_val_t(alignof(S12_128))); + + delete [] break_optimization(new S12_128[100]); + operator delete[](break_optimization(new S12_128[100]), + std::align_val_t(alignof(S12_128))); + operator delete[](break_optimization(new S12_128[100]), + std::align_val_t(alignof(S12_128)), std::nothrow); + operator delete[](break_optimization(new S12_128[100]), sizeof(S12_128[100]), + std::align_val_t(alignof(S12_128))); + + fprintf(stderr, "Done\n"); + // CHECK: Testing valid cases + // CHECK-NEXT: Done + + // Explicit mismatched calls. + + operator delete(break_optimization(new S12_128), std::nothrow); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: 128 bytes; + // CHECK: alignment of the deallocated type: default-aligned. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + operator delete(break_optimization(new S12_128), sizeof(S12_128)); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: 128 bytes; + // CHECK: alignment of the deallocated type: default-aligned. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + operator delete[](break_optimization(new S12_128[100]), std::nothrow); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: 128 bytes; + // CHECK: alignment of the deallocated type: default-aligned. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + operator delete[](break_optimization(new S12_128[100]), sizeof(S12_128[100])); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: 128 bytes; + // CHECK: alignment of the deallocated type: default-aligned. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + // Various mismatched alignments. + + delete break_optimization(reinterpret_cast<S12*>(new S12_256)); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: 256 bytes; + // CHECK: alignment of the deallocated type: default-aligned. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + delete break_optimization(reinterpret_cast<S12_256*>(new S12)); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: default-aligned; + // CHECK: alignment of the deallocated type: 256 bytes. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + delete break_optimization(reinterpret_cast<S12_128*>(new S12_256)); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: 256 bytes; + // CHECK: alignment of the deallocated type: 128 bytes. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + delete [] break_optimization(reinterpret_cast<S12*>(new S12_256[100])); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: 256 bytes; + // CHECK: alignment of the deallocated type: default-aligned. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + delete [] break_optimization(reinterpret_cast<S12_256*>(new S12[100])); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: default-aligned; + // CHECK: alignment of the deallocated type: 256 bytes. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + delete [] break_optimization(reinterpret_cast<S12_128*>(new S12_256[100])); + // CHECK: AddressSanitizer: new-delete-type-mismatch + // CHECK: object passed to delete has wrong type: + // CHECK: alignment of the allocated type: 256 bytes; + // CHECK: alignment of the deallocated type: 128 bytes. + // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch + + // Push ASan limits, the current limitation is that it cannot differentiate + // alignments above 512 bytes. + fprintf(stderr, "Checking alignments >= 512 bytes\n"); + delete break_optimization(reinterpret_cast<S1024_512*>(new S1024_1024)); + fprintf(stderr, "Done\n"); + // CHECK: Checking alignments >= 512 bytes + // CHECK-NEXT: Done +} |