1 // Check that the stack trace debugging API works and returns correct 2 // malloc and free stacks. 3 // RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s 4 5 // FIXME: Figure out why allocation/free stack traces may be too short on ARM. 6 // REQUIRES: stable-runtime 7 8 #if _WIN64 9 #define PTR "%llx" 10 #else 11 #define PTR "%lx" 12 #endif 13 14 #include <sanitizer/asan_interface.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 18 char *mem; 19 void func1() { 20 mem = (char *)malloc(10); 21 } 22 23 void func2() { 24 free(mem); 25 } 26 27 int main() { 28 // Disable stderr buffering. Needed on Windows. 29 setvbuf(stderr, NULL, _IONBF, 0); 30 31 func1(); 32 func2(); 33 34 void *trace[100]; 35 size_t num_frames = 100; 36 int thread_id; 37 num_frames = __asan_get_alloc_stack(mem, trace, num_frames, &thread_id); 38 39 fprintf(stderr, "alloc stack retval %s\n", (num_frames > 0 && num_frames < 10) 40 ? "ok" : ""); 41 // CHECK: alloc stack retval ok 42 fprintf(stderr, "thread id = %d\n", thread_id); 43 // CHECK: thread id = 0 44 fprintf(stderr, "0x" PTR "\n", trace[0]); 45 // CHECK: 0x{{0*}}[[ALLOC_FRAME_0:[0-9a-f]+]] 46 fprintf(stderr, "0x" PTR "\n", trace[1]); 47 // CHECK: 0x{{0*}}[[ALLOC_FRAME_1:[0-9a-f]+]] 48 49 num_frames = 100; 50 num_frames = __asan_get_free_stack(mem, trace, num_frames, &thread_id); 51 52 fprintf(stderr, "free stack retval %s\n", (num_frames > 0 && num_frames < 10) 53 ? "ok" : ""); 54 // CHECK: free stack retval ok 55 fprintf(stderr, "thread id = %d\n", thread_id); 56 // CHECK: thread id = 0 57 fprintf(stderr, "0x" PTR "\n", trace[0]); 58 // CHECK: 0x{{0*}}[[FREE_FRAME_0:[0-9a-f]+]] 59 fprintf(stderr, "0x" PTR "\n", trace[1]); 60 // CHECK: 0x{{0*}}[[FREE_FRAME_1:[0-9a-f]+]] 61 62 mem[0] = 'A'; // BOOM 63 64 // CHECK: ERROR: AddressSanitizer: heap-use-after-free 65 // CHECK: WRITE of size 1 at 0x{{.*}} 66 // CHECK: freed by thread T0 here: 67 // CHECK: #0 0x{{0*}}[[FREE_FRAME_0]] 68 // CHECK: #1 0x{{0*}}[[FREE_FRAME_1]] 69 // CHECK: previously allocated by thread T0 here: 70 // CHECK: #0 0x{{0*}}[[ALLOC_FRAME_0]] 71 // CHECK: #1 0x{{0*}}[[ALLOC_FRAME_1]] 72 73 return 0; 74 } 75