1 | // Test the behavior of malloc/calloc/realloc/new when the allocation size |
2 | // exceeds the sanitizer's allocator max allowed one. |
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: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH |
9 | // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \ |
10 | // RUN: | FileCheck %s --check-prefix=CHECK-mCRASH |
11 | // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t malloc 2>&1 \ |
12 | // RUN: | FileCheck %s --check-prefix=CHECK-NULL |
13 | // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \ |
14 | // RUN: | FileCheck %s --check-prefix=CHECK-cCRASH |
15 | // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t calloc 2>&1 \ |
16 | // RUN: | FileCheck %s --check-prefix=CHECK-NULL |
17 | // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \ |
18 | // RUN: | FileCheck %s --check-prefix=CHECK-coCRASH |
19 | // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t calloc-overflow 2>&1 \ |
20 | // RUN: | FileCheck %s --check-prefix=CHECK-NULL |
21 | // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \ |
22 | // RUN: | FileCheck %s --check-prefix=CHECK-rCRASH |
23 | // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t realloc 2>&1 \ |
24 | // RUN: | FileCheck %s --check-prefix=CHECK-NULL |
25 | // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \ |
26 | // RUN: | FileCheck %s --check-prefix=CHECK-mrCRASH |
27 | // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t realloc-after-malloc 2>&1 \ |
28 | // RUN: | FileCheck %s --check-prefix=CHECK-NULL |
29 | // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t new 2>&1 \ |
30 | // RUN: | FileCheck %s --check-prefix=CHECK-nCRASH |
31 | // RUN: %env_tool_opts=allocator_may_return_null=1 not %run %t new 2>&1 \ |
32 | // RUN: | FileCheck %s --check-prefix=CHECK-nCRASH-OOM |
33 | // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \ |
34 | // RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH |
35 | // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1 \ |
36 | // RUN: | FileCheck %s --check-prefix=CHECK-NULL |
37 | |
38 | // TODO(alekseyshl): win32 is disabled due to failing errno tests, fix it there. |
39 | // UNSUPPORTED: ubsan, target={{.*windows-msvc.*}} |
40 | |
41 | #include <assert.h> |
42 | #include <errno.h> |
43 | #include <stdio.h> |
44 | #include <stdlib.h> |
45 | #include <string.h> |
46 | #include <limits> |
47 | #include <new> |
48 | |
49 | int main(int argc, char **argv) { |
50 | assert(argc == 2); |
51 | const char *action = argv[1]; |
52 | fprintf(stderr, format: "%s:\n" , action); |
53 | |
54 | // The maximum value of all supported sanitizers (search for |
55 | // kMaxAllowedMallocSize). For ASan + LSan, ASan limit is used. |
56 | static const size_t kMaxAllowedMallocSizePlusOne = |
57 | #if __LP64__ || defined(_WIN64) |
58 | (1ULL << 40) + 1; |
59 | #else |
60 | (3UL << 30) + 1; |
61 | #endif |
62 | |
63 | void *x = nullptr; |
64 | if (!strcmp(s1: action, s2: "malloc" )) { |
65 | x = malloc(size: kMaxAllowedMallocSizePlusOne); |
66 | } else if (!strcmp(s1: action, s2: "calloc" )) { |
67 | x = calloc(nmemb: (kMaxAllowedMallocSizePlusOne / 4) + 1, size: 4); |
68 | } else if (!strcmp(s1: action, s2: "calloc-overflow" )) { |
69 | volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max(); |
70 | size_t kArraySize = 4096; |
71 | volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10; |
72 | x = calloc(nmemb: kArraySize, size: kArraySize2); |
73 | } else if (!strcmp(s1: action, s2: "realloc" )) { |
74 | x = realloc(ptr: 0, size: kMaxAllowedMallocSizePlusOne); |
75 | } else if (!strcmp(s1: action, s2: "realloc-after-malloc" )) { |
76 | char *t = (char*)malloc(size: 100); |
77 | *t = 42; |
78 | x = realloc(ptr: t, size: kMaxAllowedMallocSizePlusOne); |
79 | assert(*t == 42); |
80 | free(ptr: t); |
81 | } else if (!strcmp(s1: action, s2: "new" )) { |
82 | x = operator new(kMaxAllowedMallocSizePlusOne); |
83 | } else if (!strcmp(s1: action, s2: "new-nothrow" )) { |
84 | x = operator new(kMaxAllowedMallocSizePlusOne, std::nothrow); |
85 | } else { |
86 | assert(0); |
87 | } |
88 | |
89 | // The NULL pointer is printed differently on different systems, while (long)0 |
90 | // is always the same. |
91 | fprintf(stderr, format: "errno: %d, x: %lx\n" , errno, (long)x); |
92 | |
93 | return 0; |
94 | } |
95 | |
96 | // CHECK-mCRASH: malloc: |
97 | // CHECK-mCRASH: #{{[0-9]+.*}}allocator_returns_null.cpp |
98 | // CHECK-mCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.*allocator_returns_null.cpp.*}} in main |
99 | // CHECK-cCRASH: calloc: |
100 | // CHECK-cCRASH: #{{[0-9]+.*}}allocator_returns_null.cpp |
101 | // CHECK-cCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.*allocator_returns_null.cpp.*}} in main |
102 | // CHECK-coCRASH: calloc-overflow: |
103 | // CHECK-coCRASH: #{{[0-9]+.*}}allocator_returns_null.cpp |
104 | // CHECK-coCRASH: {{SUMMARY: .*Sanitizer: calloc-overflow.*allocator_returns_null.cpp.*}} in main |
105 | // CHECK-rCRASH: realloc: |
106 | // CHECK-rCRASH: #{{[0-9]+.*}}allocator_returns_null.cpp |
107 | // CHECK-rCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.*allocator_returns_null.cpp.*}} in main |
108 | // CHECK-mrCRASH: realloc-after-malloc: |
109 | // CHECK-mrCRASH: #{{[0-9]+.*}}allocator_returns_null.cpp |
110 | // CHECK-mrCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.*allocator_returns_null.cpp.*}} in main |
111 | // CHECK-nCRASH: new: |
112 | // CHECK-nCRASH: #{{[0-9]+.*}}allocator_returns_null.cpp |
113 | // CHECK-nCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.*allocator_returns_null.cpp.*}} in main |
114 | // CHECK-nCRASH-OOM: new: |
115 | // CHECK-nCRASH-O#{{[0-9]+.*}}allocator_returns_null.cpp |
116 | // CHECK-nCRASH-OOM: {{SUMMARY: .*Sanitizer: out-of-memory.*allocator_returns_null.cpp.*}} in main |
117 | // CHECK-nnCRASH: new-nothrow: |
118 | // CHECK-nnCRASH: #{{[0-9]+.*}}allocator_returns_null.cpp |
119 | // CHECK-nnCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.*allocator_returns_null.cpp.*}} in main |
120 | |
121 | // CHECK-NULL: {{malloc|calloc|calloc-overflow|realloc|realloc-after-malloc|new-nothrow}} |
122 | // CHECK-NULL: errno: 12, x: 0 |
123 | |