1 | // Test the behavior of malloc/calloc/realloc/new when the allocation size |
2 | // exceeds the HWASan allocator's 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 0 and set errno to |
5 | // the appropriate error code. |
6 | // |
7 | // RUN: %clangxx_hwasan -O0 %s -o %t |
8 | // RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH |
9 | // RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \ |
10 | // RUN: | FileCheck %s --check-prefix=CHECK-mCRASH |
11 | // RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t malloc 2>&1 \ |
12 | // RUN: | FileCheck %s --check-prefix=CHECK-mNULL |
13 | // RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \ |
14 | // RUN: | FileCheck %s --check-prefix=CHECK-cCRASH |
15 | // RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t calloc 2>&1 \ |
16 | // RUN: | FileCheck %s --check-prefix=CHECK-cNULL |
17 | // RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \ |
18 | // RUN: | FileCheck %s --check-prefix=CHECK-coCRASH |
19 | // RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t calloc-overflow 2>&1 \ |
20 | // RUN: | FileCheck %s --check-prefix=CHECK-coNULL |
21 | // RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \ |
22 | // RUN: | FileCheck %s --check-prefix=CHECK-rCRASH |
23 | // RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t realloc 2>&1 \ |
24 | // RUN: | FileCheck %s --check-prefix=CHECK-rNULL |
25 | // RUN: %env_hwasan_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_hwasan_opts=allocator_may_return_null=1 %run %t realloc-after-malloc 2>&1 \ |
28 | // RUN: | FileCheck %s --check-prefix=CHECK-mrNULL |
29 | // RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t new 2>&1 \ |
30 | // RUN: | FileCheck %s --check-prefix=CHECK-nCRASH |
31 | // RUN: %env_hwasan_opts=allocator_may_return_null=1 not %run %t new 2>&1 \ |
32 | // RUN: | FileCheck %s --check-prefix=CHECK-nCRASH-OOM |
33 | // RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \ |
34 | // RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH |
35 | // RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1 \ |
36 | // RUN: | FileCheck %s --check-prefix=CHECK-nnNULL |
37 | |
38 | // TODO(alekseyshl): Fix it. |
39 | // UNSUPPORTED: android |
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 | static const size_t kMaxAllowedMallocSizePlusOne = (1UL << 40) + 1; |
55 | |
56 | void *x = nullptr; |
57 | if (!strcmp(s1: action, s2: "malloc" )) { |
58 | x = malloc(size: kMaxAllowedMallocSizePlusOne); |
59 | } else if (!strcmp(s1: action, s2: "calloc" )) { |
60 | x = calloc(nmemb: (kMaxAllowedMallocSizePlusOne / 4) + 1, size: 4); |
61 | } else if (!strcmp(s1: action, s2: "calloc-overflow" )) { |
62 | volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max(); |
63 | size_t kArraySize = 4096; |
64 | volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10; |
65 | x = calloc(nmemb: kArraySize, size: kArraySize2); |
66 | } else if (!strcmp(s1: action, s2: "realloc" )) { |
67 | x = realloc(ptr: 0, size: kMaxAllowedMallocSizePlusOne); |
68 | } else if (!strcmp(s1: action, s2: "realloc-after-malloc" )) { |
69 | char *t = (char*)malloc(size: 100); |
70 | *t = 42; |
71 | x = realloc(ptr: t, size: kMaxAllowedMallocSizePlusOne); |
72 | assert(*t == 42); |
73 | free(ptr: t); |
74 | } else if (!strcmp(s1: action, s2: "new" )) { |
75 | x = operator new(kMaxAllowedMallocSizePlusOne); |
76 | } else if (!strcmp(s1: action, s2: "new-nothrow" )) { |
77 | x = operator new(kMaxAllowedMallocSizePlusOne, std::nothrow); |
78 | } else { |
79 | assert(0); |
80 | } |
81 | |
82 | fprintf(stderr, format: "errno: %d\n" , errno); |
83 | |
84 | free(ptr: x); |
85 | |
86 | return x != nullptr; |
87 | } |
88 | |
89 | // CHECK-mCRASH: malloc: |
90 | // CHECK-mCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big {{.*}} in main |
91 | // CHECK-cCRASH: calloc: |
92 | // CHECK-cCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big {{.*}} in main |
93 | // CHECK-coCRASH: calloc-overflow: |
94 | // CHECK-coCRASH: SUMMARY: HWAddressSanitizer: calloc-overflow {{.*}} in main |
95 | // CHECK-rCRASH: realloc: |
96 | // CHECK-rCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big {{.*}} in main |
97 | // CHECK-mrCRASH: realloc-after-malloc: |
98 | // CHECK-mrCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big {{.*}} in main |
99 | // CHECK-nCRASH: new: |
100 | // CHECK-nCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big {{.*}} in main |
101 | // CHECK-nCRASH-OOM: new: |
102 | // CHECK-nCRASH-OOM: SUMMARY: HWAddressSanitizer: out-of-memory {{.*}} in main |
103 | // CHECK-nnCRASH: new-nothrow: |
104 | // CHECK-nnCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big {{.*}} in main |
105 | |
106 | // CHECK-mNULL: malloc: |
107 | // CHECK-mNULL: errno: 12 |
108 | // CHECK-cNULL: calloc: |
109 | // CHECK-cNULL: errno: 12 |
110 | // CHECK-coNULL: calloc-overflow: |
111 | // CHECK-coNULL: errno: 12 |
112 | // CHECK-rNULL: realloc: |
113 | // CHECK-rNULL: errno: 12 |
114 | // CHECK-mrNULL: realloc-after-malloc: |
115 | // CHECK-mrNULL: errno: 12 |
116 | // CHECK-nnNULL: new-nothrow: |
117 | |