xref: /llvm-project/compiler-rt/test/msan/chained_origin_limits.cpp (revision 643a2080ec028bd7674206e0f97cbc7d0f132f99)
1 // This test program creates a very large number of unique histories.
2 
3 // Heap origin.
4 // RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t
5 
6 // RUN: env MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
7 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
8 
9 // RUN: env MSAN_OPTIONS=origin_history_size=2 not %run %t >%t.out 2>&1
10 // RUN: FileCheck %s --check-prefix=CHECK2 < %t.out
11 
12 // RUN: env MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1
13 // RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out
14 
15 // RUN: env MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1
16 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
17 
18 // Stack origin.
19 // RUN: %clangxx_msan -DSTACK -fsanitize-memory-track-origins=2 -O3 %s -o %t
20 
21 // RUN: env MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
22 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
23 
24 // RUN: env MSAN_OPTIONS=origin_history_size=2 not %run %t >%t.out 2>&1
25 // RUN: FileCheck %s --check-prefix=CHECK2 < %t.out
26 
27 // RUN: env MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1
28 // RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out
29 
30 // RUN: env MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1
31 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
32 
33 // Heap origin, with calls.
34 // RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t
35 
36 // RUN: env MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
37 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
38 
39 // RUN: env MSAN_OPTIONS=origin_history_size=2 not %run %t >%t.out 2>&1
40 // RUN: FileCheck %s --check-prefix=CHECK2 < %t.out
41 
42 // RUN: env MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1
43 // RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out
44 
45 // RUN: env MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1
46 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
47 
48 // Stack origin, with calls.
49 // RUN: %clangxx_msan -DSTACK -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t
50 
51 // RUN: env MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
52 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
53 
54 // RUN: env MSAN_OPTIONS=origin_history_size=2 not %run %t >%t.out 2>&1
55 // RUN: FileCheck %s --check-prefix=CHECK2 < %t.out
56 
57 // RUN: env MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1
58 // RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out
59 
60 // RUN: env MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1
61 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
62 
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include <unistd.h>
67 
68 static char *buf, *cur, *end;
69 void init() {
70   buf = new char[1000];
71 #ifdef STACK
72   char stackbuf[1000];
73   char *volatile p = stackbuf;
74   memcpy(buf, p, 1000);
75 #endif
76   cur = buf;
77   end = buf + 1000;
78 }
79 
80 void line_flush() {
81   char *p;
82   for (p = cur - 1; p >= buf; --p)
83     if (*p == '\n')
84       break;
85   if (p >= buf) {
86     size_t write_sz = p - buf + 1;
87     // write(2, buf, write_sz);
88     memmove(buf, p + 1, end - p - 1);
89     cur -= write_sz;
90   }
91 }
92 
93 void buffered_write(const char *p, size_t sz) {
94   while (sz > 0) {
95     size_t copy_sz = end - cur;
96     if (sz < copy_sz) copy_sz = sz;
97     memcpy(cur, p, copy_sz);
98     cur += copy_sz;
99     sz -= copy_sz;
100     line_flush();
101   }
102 }
103 
104 void fn1() {
105   buffered_write("a\n", 2);
106 }
107 
108 void fn2() {
109   buffered_write("a\n", 2);
110 }
111 
112 void fn3() {
113   buffered_write("a\n", 2);
114 }
115 
116 int main(void) {
117   init();
118   for (int i = 0; i < 2000; ++i) {
119     fn1();
120     fn2();
121     fn3();
122   }
123   return buf[50];
124 }
125 
126 // CHECK7: WARNING: MemorySanitizer: use-of-uninitialized-value
127 // CHECK7-NOT: Uninitialized value was stored to memory at
128 // CHECK7: Uninitialized value was stored to memory at
129 // CHECK7-NOT: Uninitialized value was stored to memory at
130 // CHECK7: Uninitialized value was stored to memory at
131 // CHECK7-NOT: Uninitialized value was stored to memory at
132 // CHECK7: Uninitialized value was stored to memory at
133 // CHECK7-NOT: Uninitialized value was stored to memory at
134 // CHECK7: Uninitialized value was stored to memory at
135 // CHECK7-NOT: Uninitialized value was stored to memory at
136 // CHECK7: Uninitialized value was stored to memory at
137 // CHECK7-NOT: Uninitialized value was stored to memory at
138 // CHECK7: Uninitialized value was stored to memory at
139 // CHECK7-NOT: Uninitialized value was stored to memory at
140 // CHECK7: Uninitialized value was created
141 
142 // CHECK2: WARNING: MemorySanitizer: use-of-uninitialized-value
143 // CHECK2-NOT: Uninitialized value was stored to memory at
144 // CHECK2: Uninitialized value was stored to memory at
145 // CHECK2-NOT: Uninitialized value was stored to memory at
146 // CHECK2: Uninitialized value was created
147 
148 // For architectures with short stack all the stacks in the chain are same
149 // because the stack trace does not contain frames upto the functions fn1, fn2,
150 // fn3 from where the uninitialized stores actually originate. Since we report
151 // uninitialized value store once for each stack frame
152 // (origin_history_per_stack_limit = 1) we expect only one instance of
153 // "Uninitialized value was stored to memory at".
154 
155 // CHECK-PER-STACK: WARNING: MemorySanitizer: use-of-uninitialized-value
156 // CHECK-PER-STACK: Uninitialized value was stored to memory at
157 // CHECK-SHORT-STACK: in __msan_memmove
158 // CHECK-FULL-STACK: in fn3
159 // CHECK-FULL-STACK: Uninitialized value was stored to memory at
160 // CHECK-FULL-STACK: in fn2
161 // CHECK-FULL-STACK: Uninitialized value was stored to memory at
162 // CHECK-FULL-STACK: in fn1
163 // CHECK-PER-STACK: Uninitialized value was created
164 
165 // CHECK-UNLIMITED: WARNING: MemorySanitizer: use-of-uninitialized-value
166 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
167 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
168 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
169 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
170 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
171 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
172 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
173 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
174 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
175 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
176 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
177 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
178 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
179 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
180 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
181 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
182 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
183 // CHECK-UNLIMITED: Uninitialized value was stored to memory at
184 // CHECK-UNLIMITED: Uninitialized value was created
185