Skip to content

Commit ce1fb03

Browse files
committed
[clang][analyzer] Improve bug reports of StdLibraryFunctionsChecker.
Add an additional explanation of what is wrong if a constraint is not satisfied, in some cases. Additionally the bug report generation is changed to use raw_ostream. Reviewed By: Szelethus, NoQ Differential Revision: https://reviews.llvm.org/D144003
1 parent ac02bf6 commit ce1fb03

8 files changed

+351
-222
lines changed

clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp

Lines changed: 207 additions & 129 deletions
Large diffs are not rendered by default.

clang/test/Analysis/std-c-library-functions-arg-constraints-note-tags.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ int clang_analyzer_getExtent(void *);
1919
// Check NotNullConstraint assumption notes.
2020
int __not_null(int *);
2121
int test_not_null_note(int *x, int y) {
22-
__not_null(x); // expected-note{{Assuming the 1st argument to '__not_null' is not NULL}}
22+
__not_null(x); // expected-note{{Assuming that the 1st argument to '__not_null' is not NULL}}
2323
if (x) // expected-note{{'x' is non-null}} \
2424
// expected-note{{Taking true branch}}
2525
if (!y) // expected-note{{Assuming 'y' is 0}} \
@@ -33,15 +33,15 @@ int test_not_null_note(int *x, int y) {
3333
// Check the RangeConstraint assumption notes.
3434
int __single_val_0(int); // [0, 0]
3535
int test_range_constraint_note(int x, int y) {
36-
__single_val_0(x); // expected-note{{Assuming the 1st argument to '__single_val_0' is zero}}
36+
__single_val_0(x); // expected-note{{Assuming that the 1st argument to '__single_val_0' is zero}}
3737
return y / x; // expected-warning{{Division by zero}} \
3838
// expected-note{{Division by zero}}
3939
}
4040

4141
// Check the BufferSizeConstraint assumption notes.
4242
int __buf_size_arg_constraint_concrete(const void *buf); // size of buf must be >= 10
4343
void test_buffer_size_note(char *buf, int y) {
44-
__buf_size_arg_constraint_concrete(buf); // expected-note {{Assuming the size of the 1st argument to '__buf_size_arg_constraint_concrete' is equal to or greater than 10}}
44+
__buf_size_arg_constraint_concrete(buf); // expected-note {{Assuming that the 1st argument to '__buf_size_arg_constraint_concrete' is a buffer with size equal to or greater than 10}}
4545
clang_analyzer_eval(clang_analyzer_getExtent(buf) >= 10); // expected-warning{{TRUE}} \
4646
// expected-note{{TRUE}}
4747

clang/test/Analysis/std-c-library-functions-arg-constraints-notes.cpp

Lines changed: 84 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
int __not_null(int *);
1616
void test_not_null(int *x) {
1717
__not_null(nullptr); // \
18-
// expected-warning{{The 1st argument to '__not_null' should not be NULL}}
18+
// expected-warning{{The 1st argument to '__not_null' is NULL but should not be NULL [}}
1919
}
2020

2121
// Check the BufferSizeConstraint violation notes.
@@ -28,19 +28,19 @@ void test_buffer_size(int x) {
2828
case 1: {
2929
char buf[9];
3030
__buf_size_arg_constraint_concrete(buf); // \
31-
// expected-warning{{The size of the 1st argument to '__buf_size_arg_constraint_concrete' should be equal to or greater than 10}}
31+
// expected-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' is out of the accepted range; It should be a buffer with size equal to or greater than 10 [}}
3232
break;
3333
}
3434
case 2: {
3535
char buf[3];
3636
__buf_size_arg_constraint(buf, 4); // \
37-
// expected-warning{{The size of the 1st argument to '__buf_size_arg_constraint' should be equal to or greater than the value of the 2nd argument}}
37+
// expected-warning{{The 1st argument to '__buf_size_arg_constraint' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument}}
3838
break;
3939
}
4040
case 3: {
4141
char buf[3];
4242
__buf_size_arg_constraint_mul(buf, 4, 2); // \
43-
// expected-warning{{The size of the 1st argument to '__buf_size_arg_constraint_mul' should be equal to or greater than the value of the 2nd argument times the 3rd argument}}
43+
// expected-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}}
4444
break;
4545
}
4646
}
@@ -78,109 +78,160 @@ int __range_out_minf_1(int); // [-inf, 1]
7878
int __range_out_1_2__4_6(int); // [1, 2], [4, 6]
7979
int __range_out_1_2__4_inf(int); // [1, 2], [4, inf]
8080

81+
int __test_case_range_1_2__4_6(int);
82+
8183
void test_range_values(int x) {
8284
switch (x) {
8385
case 0:
84-
__single_val_0(1); // expected-warning{{should be zero}}
86+
__single_val_0(1); // expected-warning{{is 1 but should be zero}}
8587
break;
8688
case 1:
87-
__single_val_1(2); // expected-warning{{should be 1}}
89+
__single_val_1(2); // expected-warning{{is 2 but should be 1}}
8890
break;
8991
case 2:
90-
__range_1_2(3); // expected-warning{{should be 1 or 2}}
92+
__range_1_2(3); // expected-warning{{is 3 but should be 1 or 2}}
9193
break;
9294
case 3:
93-
__range_m1_1(3); // expected-warning{{should be between -1 and 1}}
95+
__range_m1_1(3); // expected-warning{{is 3 but should be between -1 and 1}}
9496
break;
9597
case 4:
96-
__range_m2_m1(1); // expected-warning{{should be -2 or -1}}
98+
__range_m2_m1(1); // expected-warning{{is 1 but should be -2 or -1}}
9799
break;
98100
case 5:
99-
__range_m10_10(11); // expected-warning{{should be between -10 and 10}}
101+
__range_m10_10(11); // expected-warning{{is 11 but should be between -10 and 10}}
100102
break;
101103
case 6:
102-
__range_m10_10(-11); // expected-warning{{should be between -10 and 10}}
104+
__range_m10_10(-11); // expected-warning{{is -11 but should be between -10 and 10}}
103105
break;
104106
case 7:
105-
__range_1_2__4_6(3); // expected-warning{{should be 1 or 2 or 4, 5 or 6}}
107+
__range_1_2__4_6(3); // expected-warning{{is 3 but should be 1 or 2 or between 4 and 6}}
106108
break;
107109
case 8:
108-
__range_1_2__4_inf(3); // expected-warning{{should be 1 or 2 or >= 4}}
110+
__range_1_2__4_inf(3); // expected-warning{{is 3 but should be 1 or 2 or >= 4}}
109111
break;
110112
}
111113
}
112114

113115
void test_range_values_inf(int x) {
114116
switch (x) {
115117
case 1:
116-
__range_m1_inf(-2); // expected-warning{{should be >= -1}}
118+
__range_m1_inf(-2); // expected-warning{{is -2 but should be >= -1}}
117119
break;
118120
case 2:
119-
__range_0_inf(-1); // expected-warning{{should be >= 0}}
121+
__range_0_inf(-1); // expected-warning{{is -1 but should be >= 0}}
120122
break;
121123
case 3:
122-
__range_1_inf(0); // expected-warning{{should be > 0}}
124+
__range_1_inf(0); // expected-warning{{is 0 but should be > 0}}
123125
break;
124126
case 4:
125-
__range_minf_m1(0); // expected-warning{{should be < 0}}
127+
__range_minf_m1(0); // expected-warning{{is 0 but should be < 0}}
126128
break;
127129
case 5:
128-
__range_minf_0(1); // expected-warning{{should be <= 0}}
130+
__range_minf_0(1); // expected-warning{{is 1 but should be <= 0}}
129131
break;
130132
case 6:
131-
__range_minf_1(2); // expected-warning{{should be <= 1}}
133+
__range_minf_1(2); // expected-warning{{is 2 but should be <= 1}}
132134
break;
133135
}
134136
}
135137

136138
void test_range_values_out(int x) {
137139
switch (x) {
138140
case 0:
139-
__single_val_out_0(0); // expected-warning{{should be nonzero}}
141+
__single_val_out_0(0); // expected-warning{{is 0 but should be nonzero}}
140142
break;
141143
case 1:
142-
__single_val_out_1(1); // expected-warning{{should be not equal to 1}}
144+
__single_val_out_1(1); // expected-warning{{is 1 but should be not equal to 1}}
143145
break;
144146
case 2:
145-
__range_out_1_2(2); // expected-warning{{should be not 1 and not 2}}
147+
__range_out_1_2(2); // expected-warning{{is 2 but should be not 1 and not 2}}
146148
break;
147149
case 3:
148-
__range_out_m1_1(-1); // expected-warning{{should be not between -1 and 1}}
150+
__range_out_m1_1(-1); // expected-warning{{is -1 but should be not between -1 and 1}}
149151
break;
150152
case 4:
151-
__range_out_m2_m1(-2); // expected-warning{{should be not -2 and not -1}}
153+
__range_out_m2_m1(-2); // expected-warning{{is -2 but should be not -2 and not -1}}
152154
break;
153155
case 5:
154-
__range_out_m10_10(0); // expected-warning{{should be not between -10 and 10}}
156+
__range_out_m10_10(0); // expected-warning{{is 0 but should be not between -10 and 10}}
155157
break;
156158
case 6:
157-
__range_out_1_2__4_6(1); // expected-warning{{should be not 1 and not 2 and not between 4 and 6}}
159+
__range_out_1_2__4_6(1); // expected-warning{{is 1 but should be not 1 and not 2 and not between 4 and 6}}
158160
break;
159161
case 7:
160-
__range_out_1_2__4_inf(4); // expected-warning{{should be not 1 and not 2 and < 4}}
162+
__range_out_1_2__4_inf(4); // expected-warning{{is 4 but should be not 1 and not 2 and < 4}}
161163
break;
162164
}
163165
}
164166

165167
void test_range_values_out_inf(int x) {
166168
switch (x) {
167169
case 1:
168-
__range_out_minf_m1(-1); // expected-warning{{should be >= 0}}
170+
__range_out_minf_m1(-1); // expected-warning{{is -1 but should be >= 0}}
169171
break;
170172
case 2:
171-
__range_out_minf_0(0); // expected-warning{{should be > 0}}
173+
__range_out_minf_0(0); // expected-warning{{is 0 but should be > 0}}
172174
break;
173175
case 3:
174-
__range_out_minf_1(1); // expected-warning{{should be > 1}}
176+
__range_out_minf_1(1); // expected-warning{{is 1 but should be > 1}}
175177
break;
176178
case 4:
177-
__range_out_m1_inf(-1); // expected-warning{{should be < -1}}
179+
__range_out_m1_inf(-1); // expected-warning{{is -1 but should be < -1}}
178180
break;
179181
case 5:
180-
__range_out_0_inf(0); // expected-warning{{should be < 0}}
182+
__range_out_0_inf(0); // expected-warning{{is 0 but should be < 0}}
181183
break;
182184
case 6:
183-
__range_out_1_inf(1); // expected-warning{{should be <= 0}}
185+
__range_out_1_inf(1); // expected-warning{{is 1 but should be <= 0}}
184186
break;
185187
}
186188
}
189+
190+
void test_explanation(int x, int y) {
191+
switch (y) {
192+
case 1:
193+
if (x > 0)
194+
__single_val_0(x); // expected-warning{{is > 0 but should be zero [}}
195+
return;
196+
case 2:
197+
if (x < 0)
198+
__single_val_0(x); // expected-warning{{is < 0 but should be zero [}}
199+
return;
200+
case 3:
201+
if (x < -1)
202+
__single_val_0(x); // expected-warning{{is < 0 but should be zero [}}
203+
return;
204+
case 4:
205+
if (x != 0)
206+
__single_val_0(x); // expected-warning{{is out of the accepted range; It should be zero [}}
207+
return;
208+
case 5:
209+
if (x == 3)
210+
__range_1_2__4_6(x); // expected-warning{{is 3 but should be 1 or 2 or between 4 and 6 [}}
211+
return;
212+
case 6:
213+
if (x > 6)
214+
__range_1_2__4_6(x); // expected-warning{{is >= 7 but should be 1 or 2 or between 4 and 6 [}}
215+
return;
216+
case 7:
217+
if (x < 1)
218+
__range_1_2__4_6(x); // expected-warning{{is <= 0 but should be 1 or 2 or between 4 and 6 [}}
219+
return;
220+
case 8:
221+
if (__test_case_range_1_2__4_6(x) == 1)
222+
__range_1_2__4_6(x); // expected-warning{{is 3 or <= 0 but should be 1 or 2 or between 4 and 6 [}}
223+
return;
224+
case 9:
225+
if (__test_case_range_1_2__4_6(x) == 2)
226+
__range_1_2__4_6(x); // expected-warning{{is 3 or >= 7 but should be 1 or 2 or between 4 and 6 [}}
227+
return;
228+
case 10:
229+
if (__test_case_range_1_2__4_6(x) == 3)
230+
__range_1_2__4_6(x); // expected-warning{{is <= 0 or >= 7 but should be 1 or 2 or between 4 and 6 [}}
231+
return;
232+
case 11:
233+
if (__test_case_range_1_2__4_6(x) == 4)
234+
__range_1_2__4_6(x); // expected-warning{{is out of the accepted range; It should be 1 or 2 or between 4 and 6 [}}
235+
return;
236+
}
237+
}

clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ void test_buf_size_concrete(void) {
1616
char buf[3]; // bugpath-note{{'buf' initialized here}}
1717
int s = 4; // bugpath-note{{'s' initialized to 4}}
1818
__buf_size_arg_constraint(buf, s); // \
19-
// bugpath-warning{{The size of the 1st argument to '__buf_size_arg_constraint' should be equal to or greater than the value of the 2nd argument}} \
20-
// bugpath-note{{The size of the 1st argument to '__buf_size_arg_constraint' should be equal to or greater than the value of the 2nd argument}}
19+
// bugpath-warning{{The 1st argument to '__buf_size_arg_constraint' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument}} \
20+
// bugpath-note{{The 1st argument to '__buf_size_arg_constraint' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument}}
2121
}
2222

2323
int __buf_size_arg_constraint_mul(const void *, size_t, size_t);
@@ -26,6 +26,6 @@ void test_buf_size_concrete_with_multiplication(void) {
2626
int s1 = 4; // bugpath-note{{'s1' initialized to 4}}
2727
int s2 = sizeof(short); // bugpath-note{{'s2' initialized to}}
2828
__buf_size_arg_constraint_mul(buf, s1, s2); // \
29-
// bugpath-warning{{The size of the 1st argument to '__buf_size_arg_constraint_mul' should be equal to or greater than the value of the 2nd argument times the 3rd argument}} \
30-
// bugpath-note{{The size of the 1st argument to '__buf_size_arg_constraint_mul' should be equal to or greater than the value of the 2nd argument times the 3rd argument}}
29+
// bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}} \
30+
// bugpath-note{{The 1st argument to '__buf_size_arg_constraint_mul' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}}
3131
}

0 commit comments

Comments
 (0)