1 // Test the behavior of malloc/calloc/realloc/new when the allocation size 2 // exceeds the configured max_allocation_size_mb flag. 3 // By default (allocator_may_return_null=0) the process should crash. With 4 // allocator_may_return_null=1 the allocator should return nullptr and set errno 5 // to the appropriate error code. 6 // 7 // RUN: %clangxx -O0 %s -o %t 8 // RUN: %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-NOTNULL 9 // RUN: %env_tool_opts=max_allocation_size_mb=3 %run %t malloc 2>&1 \ 10 // RUN: | FileCheck %s --check-prefix=CHECK-NOTNULL 11 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0 \ 12 // RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH 13 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \ 14 // RUN: %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-NULL 15 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0 \ 16 // RUN: not %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-cCRASH 17 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \ 18 // RUN: %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-NULL 19 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0 \ 20 // RUN: not %run %t realloc 2>&1 | FileCheck %s --check-prefix=CHECK-rCRASH 21 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \ 22 // RUN: %run %t realloc 2>&1 | FileCheck %s --check-prefix=CHECK-NULL 23 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0 \ 24 // RUN: not %run %t realloc-after-malloc 2>&1 \ 25 // RUN: | FileCheck %s --check-prefix=CHECK-mrCRASH 26 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \ 27 // RUN: %run %t realloc-after-malloc 2>&1 \ 28 // RUN: | FileCheck %s --check-prefix=CHECK-NULL 29 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0 \ 30 // RUN: not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-nCRASH 31 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \ 32 // RUN: not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-nCRASH-OOM 33 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0 \ 34 // RUN: not %run %t new-nothrow 2>&1 \ 35 // RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH 36 // RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \ 37 // RUN: %run %t new-nothrow 2>&1 | FileCheck %s --check-prefix=CHECK-NULL 38 39 // win32 is disabled due to failing errno tests. 40 // UNSUPPORTED: ubsan, windows-msvc 41 42 #include <assert.h> 43 #include <errno.h> 44 #include <limits> 45 #include <new> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 50 static void *allocate(const char *Action, size_t Size) { 51 if (!strcmp(Action, "malloc")) 52 return malloc(Size); 53 if (!strcmp(Action, "calloc")) 54 return calloc((Size + 3) / 4, 4); 55 if (!strcmp(Action, "realloc")) 56 return realloc(nullptr, Size); 57 if (!strcmp(Action, "realloc-after-malloc")) { 58 void *P = malloc(100); 59 if (void *Ret = realloc(P, Size)) 60 return Ret; 61 free(P); 62 return nullptr; 63 } 64 if (!strcmp(Action, "new")) 65 return ::operator new(Size); 66 if (!strcmp(Action, "new-nothrow")) 67 return ::operator new(Size, std::nothrow); 68 assert(0); 69 } 70 71 static void deallocate(const char *Action, void *Ptr) { 72 if (!strcmp(Action, "malloc") || !strcmp(Action, "calloc") || 73 !strcmp(Action, "realloc") || !strcmp(Action, "realloc-after-malloc")) 74 return free(Ptr); 75 if (!strcmp(Action, "new")) 76 return ::operator delete(Ptr); 77 if (!strcmp(Action, "new-nothrow")) 78 return ::operator delete(Ptr, std::nothrow); 79 assert(0); 80 } 81 82 int main(int Argc, char **Argv) { 83 assert(Argc == 2); 84 const char *Action = Argv[1]; 85 fprintf(stderr, "%s:\n", Action); 86 87 constexpr size_t MaxAllocationSize = size_t{2} << 20; 88 89 // Should succeed when max_allocation_size_mb is set. 90 void *volatile P = allocate(Action, MaxAllocationSize); 91 assert(P); 92 deallocate(Action, P); 93 94 // Should fail when max_allocation_size_mb is set. 95 P = allocate(Action, MaxAllocationSize + 1); 96 // The NULL pointer is printed differently on different systems, while (long)0 97 // is always the same. 98 fprintf(stderr, "errno: %d, P: %lx\n", errno, (long)P); 99 deallocate(Action, P); 100 101 // Should succeed when max_allocation_size_mb is set. 102 P = allocate(Action, MaxAllocationSize); 103 assert(P); 104 deallocate(Action, P); 105 106 return 0; 107 } 108 109 // CHECK-mCRASH: malloc: 110 // CHECK-mCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} 111 // CHECK-cCRASH: calloc: 112 // CHECK-cCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} 113 // CHECK-rCRASH: realloc: 114 // CHECK-rCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} 115 // CHECK-mrCRASH: realloc-after-malloc: 116 // CHECK-mrCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} 117 // CHECK-nCRASH: new: 118 // CHECK-nCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} 119 // CHECK-nCRASH-OOM: new: 120 // CHECK-nCRASH-OOM: {{SUMMARY: .*Sanitizer: out-of-memory}} 121 // CHECK-nnCRASH: new-nothrow: 122 // CHECK-nnCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} 123 124 // CHECK-NULL: {{malloc|calloc|calloc-overflow|realloc|realloc-after-malloc|new-nothrow}} 125 // CHECK-NULL: errno: 12, P: 0 126 // 127 // CHECK-NOTNULL-NOT: P: 0 128