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
49int 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

source code of compiler-rt/test/hwasan/TestCases/allocator_returns_null.cpp