xref: /llvm-project/compiler-rt/test/asan/TestCases/Linux/allocator_oom_test.cpp (revision 2d37e48e2439f70ed394bcca5c065ca2c8f5ae94)
1673dc3d4SNico Weber // Test the behavior of malloc/calloc/realloc when the allocation causes OOM
2673dc3d4SNico Weber // in the secondary allocator.
3673dc3d4SNico Weber // By default (allocator_may_return_null=0) the process should crash.
4673dc3d4SNico Weber // With allocator_may_return_null=1 the allocator should return 0.
5673dc3d4SNico Weber // Set the limit to 20.5T on 64 bits to account for ASan shadow memory,
6673dc3d4SNico Weber // allocator buffers etc. so that the test allocation of ~1T will trigger OOM.
7673dc3d4SNico Weber // Limit this test to Linux since we're relying on allocator internal
8673dc3d4SNico Weber // limits (shadow memory size, allocation limits etc.)
9673dc3d4SNico Weber 
10673dc3d4SNico Weber // RUN: %clangxx_asan -O0 %s -o %t
11673dc3d4SNico Weber // RUN: ulimit -v 22024290304
12673dc3d4SNico Weber // RUN: not %run %t malloc 2>&1 \
13673dc3d4SNico Weber // RUN:   | FileCheck %s --check-prefixes=CHECK-MALLOC,CHECK-CRASH
14673dc3d4SNico Weber // RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \
15673dc3d4SNico Weber // RUN:   | FileCheck %s --check-prefixes=CHECK-MALLOC,CHECK-CRASH
16673dc3d4SNico Weber // RUN: %env_asan_opts=allocator_may_return_null=1     %run %t malloc 2>&1 \
17673dc3d4SNico Weber // RUN:   | FileCheck %s --check-prefixes=CHECK-MALLOC,CHECK-NULL
18673dc3d4SNico Weber // RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \
19673dc3d4SNico Weber // RUN:   | FileCheck %s --check-prefixes=CHECK-CALLOC,CHECK-CRASH
20673dc3d4SNico Weber // RUN: %env_asan_opts=allocator_may_return_null=1     %run %t calloc 2>&1 \
21673dc3d4SNico Weber // RUN:   | FileCheck %s --check-prefixes=CHECK-CALLOC,CHECK-NULL
22673dc3d4SNico Weber // RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \
23673dc3d4SNico Weber // RUN:   | FileCheck %s --check-prefixes=CHECK-REALLOC,CHECK-CRASH
24673dc3d4SNico Weber // RUN: %env_asan_opts=allocator_may_return_null=1     %run %t realloc 2>&1 \
25673dc3d4SNico Weber // RUN:   | FileCheck %s --check-prefixes=CHECK-REALLOC,CHECK-NULL
26673dc3d4SNico Weber // RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \
27673dc3d4SNico Weber // RUN:   | FileCheck %s --check-prefixes=CHECK-MALLOC-REALLOC,CHECK-CRASH
28673dc3d4SNico Weber // RUN: %env_asan_opts=allocator_may_return_null=1     %run %t realloc-after-malloc 2>&1 \
29673dc3d4SNico Weber // RUN:   | FileCheck %s --check-prefixes=CHECK-MALLOC-REALLOC,CHECK-NULL
30673dc3d4SNico Weber 
31673dc3d4SNico Weber // ASan shadow memory on s390 is too large for this test.
32673dc3d4SNico Weber // AArch64 bots fail on this test.
33673dc3d4SNico Weber // TODO(alekseys): Android lit do not run ulimit on device.
34*2d37e48eSHarini0924 // REQUIRES: shell, shadow-scale-3
35abd09754SPaul Robinson // UNSUPPORTED: android, target={{(s390|aarch64|powerpc64le).*}}
36673dc3d4SNico Weber 
37673dc3d4SNico Weber #include <stdlib.h>
38673dc3d4SNico Weber #include <string.h>
39673dc3d4SNico Weber #include <stdio.h>
40673dc3d4SNico Weber #include <assert.h>
41673dc3d4SNico Weber 
42673dc3d4SNico Weber int main(int argc, char **argv) {
43673dc3d4SNico Weber   assert(argc == 2);
44673dc3d4SNico Weber   const char *action = argv[1];
45673dc3d4SNico Weber   fprintf(stderr, "%s:\n", action);
46673dc3d4SNico Weber 
47673dc3d4SNico Weber   // Allocate just a bit less than max allocation size enforced by ASan's
48673dc3d4SNico Weber   // allocator (currently 1T and 3G).
49673dc3d4SNico Weber   const size_t size =
50673dc3d4SNico Weber #if __LP64__
51673dc3d4SNico Weber       (1ULL << 40) - (1ULL << 30);
52673dc3d4SNico Weber #else
53673dc3d4SNico Weber       (3ULL << 30) - (1ULL << 20);
54673dc3d4SNico Weber #endif
55673dc3d4SNico Weber 
56673dc3d4SNico Weber   void *x = 0;
57673dc3d4SNico Weber 
58673dc3d4SNico Weber   if (!strcmp(action, "malloc")) {
59673dc3d4SNico Weber     x = malloc(size);
60673dc3d4SNico Weber   } else if (!strcmp(action, "calloc")) {
61673dc3d4SNico Weber     x = calloc(size / 4, 4);
62673dc3d4SNico Weber   } else if (!strcmp(action, "realloc")) {
63673dc3d4SNico Weber     x = realloc(0, size);
64673dc3d4SNico Weber   } else if (!strcmp(action, "realloc-after-malloc")) {
65673dc3d4SNico Weber     char *t = (char*)malloc(100);
66673dc3d4SNico Weber     *t = 42;
67673dc3d4SNico Weber     x = realloc(t, size);
68673dc3d4SNico Weber     assert(*t == 42);
69673dc3d4SNico Weber     free(t);
70673dc3d4SNico Weber   } else {
71673dc3d4SNico Weber     assert(0);
72673dc3d4SNico Weber   }
73673dc3d4SNico Weber 
74673dc3d4SNico Weber   // The NULL pointer is printed differently on different systems, while (long)0
75673dc3d4SNico Weber   // is always the same.
76673dc3d4SNico Weber   fprintf(stderr, "x: %lx\n", (long)x);
77673dc3d4SNico Weber   free(x);
78673dc3d4SNico Weber 
79673dc3d4SNico Weber   return x != 0;
80673dc3d4SNico Weber }
81673dc3d4SNico Weber 
82673dc3d4SNico Weber // CHECK-MALLOC: malloc:
83673dc3d4SNico Weber // CHECK-CALLOC: calloc:
84673dc3d4SNico Weber // CHECK-REALLOC: realloc:
85673dc3d4SNico Weber // CHECK-MALLOC-REALLOC: realloc-after-malloc:
86673dc3d4SNico Weber 
87673dc3d4SNico Weber // CHECK-CRASH: SUMMARY: AddressSanitizer: out-of-memory
88673dc3d4SNico Weber // CHECK-NULL: x: 0
89