1 // RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
2 // RUN:     %run %t >%t.out 2>&1
3 // RUN: FileCheck %s < %t.out
4 //
5 // RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
6 // RUN:     %run %t >%t.out 2>&1
7 // RUN: FileCheck %s < %t.out
8 //
9 // REQUIRES: x86_64-target-arch
10 
11 #include <sanitizer/dfsan_interface.h>
12 #include <stdio.h>
13 #include <string.h>
14 
15 #define NOINLINE __attribute__((noinline))
16 
foo(int a,int b)17 NOINLINE int foo(int a, int b) { return a + b; }
18 
bar(int depth,void * addr,int size)19 NOINLINE void bar(int depth, void *addr, int size) {
20   if (depth) {
21     bar(depth - 1, addr, size);
22   } else {
23     dfsan_set_label(1, addr, size);
24   }
25 }
26 
baz(int depth,void * addr,int size)27 NOINLINE void baz(int depth, void *addr, int size) {
28   bar(depth, addr, size);
29 }
30 
main(int argc,char * argv[])31 int main(int argc, char *argv[]) {
32   int a = 10;
33   int b = 20;
34   baz(8, &a, sizeof(a));
35   int c = foo(a, b);
36   dfsan_print_origin_trace(&c, NULL);
37   // CHECK: Taint value 0x1 {{.*}} origin tracking ()
38   // CHECK: Origin value: {{.*}}, Taint value was stored to memory at
39   // CHECK: #0 {{.*}} in main {{.*}}origin_stack_trace.c:[[@LINE-4]]
40 
41   // CHECK: Origin value: {{.*}}, Taint value was created at
42   // CHECK: #0 {{.*}} in bar.dfsan {{.*}}origin_stack_trace.c:[[@LINE-19]]
43   // CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in bar.dfsan {{.*}}origin_stack_trace.c:[[@LINE-22]]
44   // CHECK: #9 {{.*}} in baz.dfsan {{.*}}origin_stack_trace.c:[[@LINE-16]]
45 
46   char buf[3000];
47   size_t length = dfsan_sprint_origin_trace(&c, NULL, buf, sizeof(buf));
48 
49   printf("==OUTPUT==\n\n%s==EOS==\n", buf);
50   // CHECK: ==OUTPUT==
51   // CHECK: Taint value 0x1 {{.*}} origin tracking ()
52   // CHECK: Origin value: {{.*}}, Taint value was stored to memory at
53   // CHECK: #0 {{.*}} in main {{.*}}origin_stack_trace.c:[[@LINE-18]]
54 
55   // CHECK: Origin value: {{.*}}, Taint value was created at
56   // CHECK: #0 {{.*}} in bar.dfsan {{.*}}origin_stack_trace.c:[[@LINE-33]]
57   // CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in bar.dfsan {{.*}}origin_stack_trace.c:[[@LINE-36]]
58   // CHECK: #9 {{.*}} in baz.dfsan {{.*}}origin_stack_trace.c:[[@LINE-30]]
59   // CHECK: ==EOS==
60 
61   char tinybuf[18];
62   size_t same_length = dfsan_sprint_origin_trace(&c, NULL, tinybuf, sizeof(tinybuf));
63 
64   printf("==TRUNCATED OUTPUT==\n\n%s==EOS==\n", tinybuf);
65   // CHECK: ==TRUNCATED OUTPUT==
66   // CHECK: Taint value 0x1==EOS==
67 
68   printf("Returned length: %zu\n", length);
69   printf("Actual length: %zu\n", strlen(buf));
70   printf("Returned length with truncation: %zu\n", same_length);
71 
72   // CHECK: Returned length: [[#LEN:]]
73   // CHECK: Actual length: [[#LEN]]
74   // CHECK: Returned length with truncation: [[#LEN]]
75 
76   size_t length_with_desc = dfsan_sprint_origin_trace(&c, "DESCRIPTION", buf, sizeof(buf));
77 
78   printf("==OUTPUT==\n\n%s==EOS==\n", buf);
79   // CHECK: ==OUTPUT==
80   // CHECK: Taint value 0x1 {{.*}} origin tracking (DESCRIPTION)
81   // CHECK: Origin value: {{.*}}, Taint value was stored to memory at
82   // CHECK: #0 {{.*}} in main {{.*}}origin_stack_trace.c:[[@LINE-47]]
83 
84   // CHECK: Origin value: {{.*}}, Taint value was created at
85   // CHECK: #0 {{.*}} in bar.dfsan {{.*}}origin_stack_trace.c:[[@LINE-62]]
86   // CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in bar.dfsan {{.*}}origin_stack_trace.c:[[@LINE-65]]
87   // CHECK: #9 {{.*}} in baz.dfsan {{.*}}origin_stack_trace.c:[[@LINE-59]]
88   // CHECK: ==EOS==
89 
90   printf("Returned length: %zu\n", length_with_desc);
91   // COMM: Message length is increased by 11: the length of "DESCRIPTION".
92   // CHECK: Returned length: [[#LEN + 11]]
93 
94   buf[0] = '\0';
95   length = dfsan_sprint_origin_trace(&c, NULL, buf, 0);
96   printf("Output=\"%s\"\n", buf);
97   printf("Returned length: %zu\n", length);
98   // CHECK: Output=""
99   // CHECK: Returned length: [[#LEN]]
100 }
101