xref: /aosp_15_r20/external/compiler-rt/test/asan/TestCases/debug_stacks.cc (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
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