1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
2 
3 void clang_analyzer_eval(int);
4 void clang_analyzer_warnIfReached();
5 
6 typedef __typeof(sizeof(int)) size_t;
7 void *malloc(size_t);
8 void free(void *);
9 
loop_which_iterates_limit_times_not_widened()10 void loop_which_iterates_limit_times_not_widened() {
11   int i;
12   int x = 1;
13   // Check loop isn't widened by checking x isn't invalidated
14   for (i = 0; i < 1; ++i) {}
15   clang_analyzer_eval(x == 1); // expected-warning {{TRUE}}
16   for (i = 0; i < 2; ++i) {}
17   clang_analyzer_eval(x == 1); // expected-warning {{TRUE}}
18   for (i = 0; i < 3; ++i) {}
19   // FIXME loss of precision as a result of evaluating the widened loop body
20   //       *instead* of the last iteration.
21   clang_analyzer_eval(x == 1); // expected-warning {{UNKNOWN}}
22 }
23 
24 int a_global;
25 
loop_evaluated_before_widening()26 void loop_evaluated_before_widening() {
27   int i;
28   a_global = 1;
29   for (i = 0; i < 10; ++i) {
30     if (i == 2) {
31       // True before widening then unknown after.
32       clang_analyzer_eval(a_global == 1); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}}
33     }
34   }
35   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
36 }
37 
warnings_after_loop()38 void warnings_after_loop() {
39   int i;
40   for (i = 0; i < 10; ++i) {}
41   char *m = (char*)malloc(12);
42 } // expected-warning {{Potential leak of memory pointed to by 'm'}}
43 
for_loop_exits()44 void for_loop_exits() {
45   int i;
46   for (i = 0; i < 10; ++i) {}
47   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
48 }
49 
while_loop_exits()50 void while_loop_exits() {
51   int i = 0;
52   while (i < 10) {++i;}
53   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
54 }
55 
do_while_loop_exits()56 void do_while_loop_exits() {
57   int i = 0;
58   do {++i;} while (i < 10);
59   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
60 }
61 
loop_body_is_widened()62 void loop_body_is_widened() {
63   int i = 0;
64   while (i < 100) {
65     if (i > 10) {
66       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
67     }
68     ++i;
69   }
70   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
71 }
72 
invariably_infinite_loop()73 void invariably_infinite_loop() {
74   int i = 0;
75   while (1) { ++i; }
76   clang_analyzer_warnIfReached(); // no-warning
77 }
78 
invariably_infinite_break_loop()79 void invariably_infinite_break_loop() {
80   int i = 0;
81   while (1) {
82     ++i;
83     int x = 1;
84     if (!x) break;
85   }
86   clang_analyzer_warnIfReached(); // no-warning
87 }
88 
reachable_break_loop()89 void reachable_break_loop() {
90   int i = 0;
91   while (1) {
92     ++i;
93     if (i == 100) break;
94   }
95   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
96 }
97 
condition_constrained_true_in_loop()98 void condition_constrained_true_in_loop() {
99   int i = 0;
100   while (i < 50) {
101     clang_analyzer_eval(i < 50); // expected-warning {{TRUE}}
102     ++i;
103   }
104   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
105 }
106 
condition_constrained_false_after_loop()107 void condition_constrained_false_after_loop() {
108   int i = 0;
109   while (i < 50) {
110     ++i;
111   }
112   clang_analyzer_eval(i >= 50); // expected-warning {{TRUE}}
113   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
114 }
115 
multiple_exit_test()116 void multiple_exit_test() {
117   int x = 0;
118   int i = 0;
119   while (i < 50) {
120     if (x) {
121       i = 10;
122       break;
123     }
124     ++i;
125   }
126   // Reachable by 'normal' exit
127   if (i == 50) clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
128   // Reachable by break point
129   if (i == 10) clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
130   // Not reachable
131   if (i < 10) clang_analyzer_warnIfReached(); // no-warning
132   if (i > 10 && i < 50) clang_analyzer_warnIfReached(); // no-warning
133 }
134 
pointer_doesnt_leak_from_loop()135 void pointer_doesnt_leak_from_loop() {
136   int *h_ptr = (int *) malloc(sizeof(int));
137   for (int i = 0; i < 2; ++i) {}
138   for (int i = 0; i < 10; ++i) {} // no-warning
139   free(h_ptr);
140 }
141 
142 int g_global;
143 
unknown_after_loop(int s_arg)144 void unknown_after_loop(int s_arg) {
145   g_global = 0;
146   s_arg = 1;
147   int s_local = 2;
148   int *h_ptr = malloc(sizeof(int));
149 
150   for (int i = 0; i < 10; ++i) {}
151 
152   clang_analyzer_eval(g_global); // expected-warning {{UNKNOWN}}
153   clang_analyzer_eval(s_arg); // expected-warning {{UNKNOWN}}
154   clang_analyzer_eval(s_local); // expected-warning {{UNKNOWN}}
155   clang_analyzer_eval(h_ptr == 0); // expected-warning {{UNKNOWN}}
156   free(h_ptr);
157 }
158 
variable_bound_exiting_loops_widened(int x)159 void variable_bound_exiting_loops_widened(int x) {
160   int i = 0;
161   int t = 1;
162   while (i < x) {
163     ++i;
164   }
165   clang_analyzer_eval(t == 1); // expected-warning {{TRUE}} // expected-warning {{UNKNOWN}}
166 }
167 
nested_loop_outer_widen()168 void nested_loop_outer_widen() {
169   int i = 0, j = 0;
170   for (i = 0; i < 10; i++) {
171     clang_analyzer_eval(i < 10); // expected-warning {{TRUE}}
172     for (j = 0; j < 2; j++) {
173       clang_analyzer_eval(j < 2); // expected-warning {{TRUE}}
174     }
175     clang_analyzer_eval(j >= 2); // expected-warning {{TRUE}}
176   }
177   clang_analyzer_eval(i >= 10); // expected-warning {{TRUE}}
178 }
179 
nested_loop_inner_widen()180 void nested_loop_inner_widen() {
181   int i = 0, j = 0;
182   for (i = 0; i < 2; i++) {
183     clang_analyzer_eval(i < 2); // expected-warning {{TRUE}}
184     for (j = 0; j < 10; j++) {
185       clang_analyzer_eval(j < 10); // expected-warning {{TRUE}}
186     }
187     clang_analyzer_eval(j >= 10); // expected-warning {{TRUE}}
188   }
189   clang_analyzer_eval(i >= 2); // expected-warning {{TRUE}}
190 }
191