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