154 lines · cpp
1// Test the behavior of malloc/calloc/realloc/new when the allocation size2// exceeds the configured max_allocation_size_mb flag.3// By default (allocator_may_return_null=0) the process should crash. With4// allocator_may_return_null=1 the allocator should return nullptr and set errno5// to the appropriate error code.6//7// RUN: %clangxx -O0 %s -o %t8// RUN: %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-NOTNULL9// RUN: %env_tool_opts=max_allocation_size_mb=3 %run %t malloc 2>&1 \10// RUN: | FileCheck %s --check-prefix=CHECK-NOTNULL11// 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-mCRASH13// 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-NULL15// 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-cCRASH17// 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-NULL19// 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-rCRASH21// 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-NULL23// 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-mrCRASH26// 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-NULL29// 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-nCRASH31// 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-OOM33// 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-nnCRASH36// 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-NULL38// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=0:fast_unwind_on_malloc=0 \39// RUN: not %run %t strndup 2>&1 | FileCheck %s --check-prefix=CHECK-sCRASH40// RUN: %env_tool_opts=max_allocation_size_mb=2:allocator_may_return_null=1 \41// RUN: %run %t strndup 2>&1 | FileCheck %s --check-prefix=CHECK-NULL42 43// win32 is disabled due to failing errno tests.44// UNSUPPORTED: ubsan, target={{.*windows-msvc.*}}45 46// Symbolizer needs to allocated memory when reporting.47// UNSUPPORTED: internal_symbolizer48 49#include <assert.h>50#include <errno.h>51#include <limits>52#include <new>53#include <stdio.h>54#include <stdlib.h>55#include <string.h>56 57constexpr size_t MaxAllocationSize = size_t{2} << 20;58 59static void *allocate(const char *Action, size_t Size) {60 if (!strcmp(Action, "malloc"))61 return malloc(Size);62 if (!strcmp(Action, "calloc"))63 return calloc((Size + 3) / 4, 4);64 if (!strcmp(Action, "realloc"))65 return realloc(nullptr, Size);66 if (!strcmp(Action, "realloc-after-malloc")) {67 void *P = malloc(100);68 if (void *Ret = realloc(P, Size))69 return Ret;70 free(P);71 return nullptr;72 }73 if (!strcmp(Action, "new"))74 return ::operator new(Size);75 if (!strcmp(Action, "new-nothrow"))76 return ::operator new(Size, std::nothrow);77 if (!strcmp(Action, "strndup")) {78 static char pstr[MaxAllocationSize + 1] = {'a'};79 for (size_t i = 0; i < MaxAllocationSize + 1; i++)80 pstr[i] = 'a';81 if (Size == MaxAllocationSize)82 pstr[MaxAllocationSize - 1] = '\0';83 return strndup(pstr, Size);84 }85 assert(0);86}87 88static void deallocate(const char *Action, void *Ptr) {89 if (!strcmp(Action, "malloc") || !strcmp(Action, "calloc") ||90 !strcmp(Action, "realloc") || !strcmp(Action, "realloc-after-malloc") ||91 !strcmp(Action, "strndup"))92 return free(Ptr);93 if (!strcmp(Action, "new"))94 return ::operator delete(Ptr);95 if (!strcmp(Action, "new-nothrow"))96 return ::operator delete(Ptr, std::nothrow);97 assert(0);98}99 100int main(int Argc, char **Argv) {101 assert(Argc == 2);102 const char *Action = Argv[1];103 fprintf(stderr, "%s:\n", Action);104 105 // Should succeed when max_allocation_size_mb is set.106 void *volatile P = allocate(Action, MaxAllocationSize);107 assert(P);108 deallocate(Action, P);109 110 // Should fail when max_allocation_size_mb is set.111 P = allocate(Action, MaxAllocationSize + 1);112 // The NULL pointer is printed differently on different systems, while (long)0113 // is always the same.114 fprintf(stderr, "errno: %d, P: %lx\n", errno, (long)P);115 deallocate(Action, P);116 117 // Should succeed when max_allocation_size_mb is set.118 P = allocate(Action, MaxAllocationSize);119 assert(P);120 deallocate(Action, P);121 122 return 0;123}124 125// CHECK-mCRASH: malloc:126// CHECK-mCRASH: #{{[0-9]+.*}}max_allocation_size.cpp127// CHECK-mCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.* in allocate}}128// CHECK-cCRASH: calloc:129// CHECK-cCRASH: #{{[0-9]+.*}}max_allocation_size.cpp130// CHECK-cCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.* in allocate}}131// CHECK-rCRASH: realloc:132// CHECK-rCRASH: #{{[0-9]+.*}}max_allocation_size.cpp133// CHECK-rCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.* in allocate}}134// CHECK-mrCRASH: realloc-after-malloc:135// CHECK-mrCRASH: #{{[0-9]+.*}}max_allocation_size.cpp136// CHECK-mrCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.* in allocate}}137// CHECK-nCRASH: new:138// CHECK-nCRASH: #{{[0-9]+.*}}max_allocation_size.cpp139// CHECK-nCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.* in allocate}}140// CHECK-nCRASH-OOM: new:141// CHECK-nCRASH-OOM: #{{[0-9]+.*}}max_allocation_size.cpp142// CHECK-nCRASH-OOM: {{SUMMARY: .*Sanitizer: out-of-memory.* in allocate}}143// CHECK-nnCRASH: new-nothrow:144// CHECK-nnCRASH: #{{[0-9]+.*}}max_allocation_size.cpp145// CHECK-nnCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.* in allocate}}146// CHECK-sCRASH: strndup:147// CHECK-sCRASH: #{{[0-9]+.*}}max_allocation_size.cpp148// CHECK-sCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big.*}}149 150// CHECK-NULL: {{malloc|calloc|calloc-overflow|realloc|realloc-after-malloc|new-nothrow|strndup}}151// CHECK-NULL: errno: 12, P: 0152//153// CHECK-NOTNULL-NOT: P: 0154