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