1 | // RUN: %check_clang_tidy %s bugprone-suspicious-string-compare %t -- \ |
2 | // RUN: -config='{CheckOptions: \ |
3 | // RUN: {bugprone-suspicious-string-compare.WarnOnImplicitComparison: true, \ |
4 | // RUN: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison: true}}' \ |
5 | // RUN: -- |
6 | |
7 | typedef __SIZE_TYPE__ size; |
8 | |
9 | struct locale_t { |
10 | void* dummy; |
11 | } locale; |
12 | |
13 | static const char A[] = "abc" ; |
14 | static const unsigned char U[] = "abc" ; |
15 | static const unsigned char V[] = "xyz" ; |
16 | static const wchar_t W[] = L"abc" ; |
17 | |
18 | int strlen(const char *); |
19 | |
20 | int memcmp(const void *, const void *, size); |
21 | int wmemcmp(const wchar_t *, const wchar_t *, size); |
22 | int memicmp(const void *, const void *, size); |
23 | int _memicmp(const void *, const void *, size); |
24 | int _memicmp_l(const void *, const void *, size, locale_t); |
25 | |
26 | int strcmp(const char *, const char *); |
27 | int strncmp(const char *, const char *, size); |
28 | int strcasecmp(const char *, const char *); |
29 | int strncasecmp(const char *, const char *, size); |
30 | int stricmp(const char *, const char *); |
31 | int strcmpi(const char *, const char *); |
32 | int strnicmp(const char *, const char *, size); |
33 | int _stricmp(const char *, const char * ); |
34 | int _strnicmp(const char *, const char *, size); |
35 | int _stricmp_l(const char *, const char *, locale_t); |
36 | int _strnicmp_l(const char *, const char *, size, locale_t); |
37 | |
38 | int wcscmp(const wchar_t *, const wchar_t *); |
39 | int wcsncmp(const wchar_t *, const wchar_t *, size); |
40 | int wcscasecmp(const wchar_t *, const wchar_t *); |
41 | int wcsicmp(const wchar_t *, const wchar_t *); |
42 | int wcsnicmp(const wchar_t *, const wchar_t *, size); |
43 | int _wcsicmp(const wchar_t *, const wchar_t *); |
44 | int _wcsnicmp(const wchar_t *, const wchar_t *, size); |
45 | int _wcsicmp_l(const wchar_t *, const wchar_t *, locale_t); |
46 | int _wcsnicmp_l(const wchar_t *, const wchar_t *, size, locale_t); |
47 | |
48 | int _mbscmp(const unsigned char *, const unsigned char *); |
49 | int _mbsncmp(const unsigned char *, const unsigned char *, size); |
50 | int _mbsnbcmp(const unsigned char *, const unsigned char *, size); |
51 | int _mbsnbicmp(const unsigned char *, const unsigned char *, size); |
52 | int _mbsicmp(const unsigned char *, const unsigned char *); |
53 | int _mbsnicmp(const unsigned char *, const unsigned char *, size); |
54 | int _mbscmp_l(const unsigned char *, const unsigned char *, locale_t); |
55 | int _mbsncmp_l(const unsigned char *, const unsigned char *, size, locale_t); |
56 | int _mbsicmp_l(const unsigned char *, const unsigned char *, locale_t); |
57 | int _mbsnicmp_l(const unsigned char *, const unsigned char *, size, locale_t); |
58 | int _mbsnbcmp_l(const unsigned char *, const unsigned char *, size, locale_t); |
59 | int _mbsnbicmp_l(const unsigned char *, const unsigned char *, size, locale_t); |
60 | |
61 | int test_warning_patterns() { |
62 | if (strcmp(A, "a" )) |
63 | return 0; |
64 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result [bugprone-suspicious-string-compare] |
65 | // CHECK-FIXES: if (strcmp(A, "a") != 0) |
66 | |
67 | if (strcmp(A, "a" ) == 0 || |
68 | strcmp(A, "b" )) |
69 | return 0; |
70 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result |
71 | // CHECK-FIXES: strcmp(A, "b") != 0) |
72 | |
73 | if (strcmp(A, "a" ) == 1) |
74 | return 0; |
75 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
76 | |
77 | if (strcmp(A, "a" ) == -1) |
78 | return 0; |
79 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
80 | |
81 | if (strcmp(A, "a" ) == true) |
82 | return 0; |
83 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
84 | |
85 | if (strcmp(A, "a" ) < '0') |
86 | return 0; |
87 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
88 | |
89 | if (strcmp(A, "a" ) < 0.) |
90 | return 0; |
91 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast |
92 | } |
93 | |
94 | int test_valid_patterns() { |
95 | // The following cases are valid. |
96 | if (strcmp(A, "a" ) < 0) |
97 | return 0; |
98 | if (strcmp(A, "a" ) == 0) |
99 | return 0; |
100 | if (strcmp(A, "a" ) <= 0) |
101 | return 0; |
102 | |
103 | if (wcscmp(W, L"a" ) < 0) |
104 | return 0; |
105 | if (wcscmp(W, L"a" ) == 0) |
106 | return 0; |
107 | if (wcscmp(W, L"a" ) <= 0) |
108 | return 0; |
109 | |
110 | return 1; |
111 | } |
112 | |
113 | int test_implicit_compare_with_functions() { |
114 | |
115 | if (memcmp(A, "a" , 1)) |
116 | return 0; |
117 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memcmp' is called without explicitly comparing result |
118 | // CHECK-FIXES: memcmp(A, "a", 1) != 0) |
119 | |
120 | if (wmemcmp(W, L"a" , 1)) |
121 | return 0; |
122 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wmemcmp' is called without explicitly comparing result |
123 | // CHECK-FIXES: wmemcmp(W, L"a", 1) != 0) |
124 | |
125 | if (memicmp(A, "a" , 1)) |
126 | return 0; |
127 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memicmp' is called without explicitly comparing result |
128 | // CHECK-FIXES: memicmp(A, "a", 1) != 0) |
129 | |
130 | if (_memicmp(A, "a" , 1)) |
131 | return 0; |
132 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp' is called without explicitly comparing result |
133 | // CHECK-FIXES: _memicmp(A, "a", 1) != 0) |
134 | |
135 | if (_memicmp_l(A, "a" , 1, locale)) |
136 | return 0; |
137 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp_l' is called without explicitly comparing result |
138 | // CHECK-FIXES: _memicmp_l(A, "a", 1, locale) != 0) |
139 | |
140 | if (strcmp(A, "a" )) |
141 | return 0; |
142 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result |
143 | // CHECK-FIXES: strcmp(A, "a") != 0) |
144 | |
145 | if (strncmp(A, "a" , 1)) |
146 | return 0; |
147 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncmp' is called without explicitly comparing result |
148 | // CHECK-FIXES: strncmp(A, "a", 1) != 0) |
149 | |
150 | if (strcasecmp(A, "a" )) |
151 | return 0; |
152 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcasecmp' is called without explicitly comparing result |
153 | // CHECK-FIXES: strcasecmp(A, "a") != 0) |
154 | |
155 | if (strncasecmp(A, "a" , 1)) |
156 | return 0; |
157 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncasecmp' is called without explicitly comparing result |
158 | // CHECK-FIXES: strncasecmp(A, "a", 1) != 0) |
159 | |
160 | if (stricmp(A, "a" )) |
161 | return 0; |
162 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'stricmp' is called without explicitly comparing result |
163 | // CHECK-FIXES: stricmp(A, "a") != 0) |
164 | |
165 | if (strcmpi(A, "a" )) |
166 | return 0; |
167 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmpi' is called without explicitly comparing result |
168 | // CHECK-FIXES: strcmpi(A, "a") != 0) |
169 | |
170 | if (_stricmp(A, "a" )) |
171 | return 0; |
172 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp' is called without explicitly comparing result |
173 | // CHECK-FIXES: _stricmp(A, "a") != 0) |
174 | |
175 | if (strnicmp(A, "a" , 1)) |
176 | return 0; |
177 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strnicmp' is called without explicitly comparing result |
178 | // CHECK-FIXES: strnicmp(A, "a", 1) != 0) |
179 | |
180 | if (_strnicmp(A, "a" , 1)) |
181 | return 0; |
182 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp' is called without explicitly comparing result |
183 | // CHECK-FIXES: _strnicmp(A, "a", 1) != 0) |
184 | |
185 | if (_stricmp_l(A, "a" , locale)) |
186 | return 0; |
187 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp_l' is called without explicitly comparing result |
188 | // CHECK-FIXES: _stricmp_l(A, "a", locale) != 0) |
189 | |
190 | if (_strnicmp_l(A, "a" , 1, locale)) |
191 | return 0; |
192 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp_l' is called without explicitly comparing result |
193 | // CHECK-FIXES: _strnicmp_l(A, "a", 1, locale) != 0) |
194 | |
195 | if (wcscmp(W, L"a" )) |
196 | return 0; |
197 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscmp' is called without explicitly comparing result |
198 | // CHECK-FIXES: wcscmp(W, L"a") != 0) |
199 | |
200 | if (wcsncmp(W, L"a" , 1)) |
201 | return 0; |
202 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsncmp' is called without explicitly comparing result |
203 | // CHECK-FIXES: wcsncmp(W, L"a", 1) != 0) |
204 | |
205 | if (wcscasecmp(W, L"a" )) |
206 | return 0; |
207 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscasecmp' is called without explicitly comparing result |
208 | // CHECK-FIXES: wcscasecmp(W, L"a") != 0) |
209 | |
210 | if (wcsicmp(W, L"a" )) |
211 | return 0; |
212 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsicmp' is called without explicitly comparing result |
213 | // CHECK-FIXES: wcsicmp(W, L"a") != 0) |
214 | |
215 | if (_wcsicmp(W, L"a" )) |
216 | return 0; |
217 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp' is called without explicitly comparing result |
218 | // CHECK-FIXES: _wcsicmp(W, L"a") != 0) |
219 | |
220 | if (_wcsicmp_l(W, L"a" , locale)) |
221 | return 0; |
222 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp_l' is called without explicitly comparing result |
223 | // CHECK-FIXES: _wcsicmp_l(W, L"a", locale) != 0) |
224 | |
225 | if (wcsnicmp(W, L"a" , 1)) |
226 | return 0; |
227 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsnicmp' is called without explicitly comparing result |
228 | // CHECK-FIXES: wcsnicmp(W, L"a", 1) != 0) |
229 | |
230 | if (_wcsnicmp(W, L"a" , 1)) |
231 | return 0; |
232 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp' is called without explicitly comparing result |
233 | // CHECK-FIXES: _wcsnicmp(W, L"a", 1) != 0) |
234 | |
235 | if (_wcsnicmp_l(W, L"a" , 1, locale)) |
236 | return 0; |
237 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp_l' is called without explicitly comparing result |
238 | // CHECK-FIXES: _wcsnicmp_l(W, L"a", 1, locale) != 0) |
239 | |
240 | if (_mbscmp(U, V)) |
241 | return 0; |
242 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp' is called without explicitly comparing result |
243 | // CHECK-FIXES: _mbscmp(U, V) != 0) |
244 | |
245 | if (_mbsncmp(U, V, 1)) |
246 | return 0; |
247 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp' is called without explicitly comparing result |
248 | // CHECK-FIXES: _mbsncmp(U, V, 1) != 0) |
249 | |
250 | if (_mbsnbcmp(U, V, 1)) |
251 | return 0; |
252 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp' is called without explicitly comparing result |
253 | // CHECK-FIXES: _mbsnbcmp(U, V, 1) != 0) |
254 | |
255 | if (_mbsnbicmp(U, V, 1)) |
256 | return 0; |
257 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp' is called without explicitly comparing result |
258 | // CHECK-FIXES: _mbsnbicmp(U, V, 1) != 0) |
259 | |
260 | if (_mbsicmp(U, V)) |
261 | return 0; |
262 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp' is called without explicitly comparing result |
263 | // CHECK-FIXES: _mbsicmp(U, V) != 0) |
264 | |
265 | if (_mbsnicmp(U, V, 1)) |
266 | return 0; |
267 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp' is called without explicitly comparing result |
268 | // CHECK-FIXES: _mbsnicmp(U, V, 1) != 0) |
269 | |
270 | if (_mbscmp_l(U, V, locale)) |
271 | return 0; |
272 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp_l' is called without explicitly comparing result |
273 | // CHECK-FIXES: _mbscmp_l(U, V, locale) != 0) |
274 | |
275 | if (_mbsncmp_l(U, V, 1, locale)) |
276 | return 0; |
277 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp_l' is called without explicitly comparing result |
278 | // CHECK-FIXES: _mbsncmp_l(U, V, 1, locale) != 0) |
279 | |
280 | if (_mbsicmp_l(U, V, locale)) |
281 | return 0; |
282 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp_l' is called without explicitly comparing result |
283 | // CHECK-FIXES: _mbsicmp_l(U, V, locale) != 0) |
284 | |
285 | if (_mbsnicmp_l(U, V, 1, locale)) |
286 | return 0; |
287 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp_l' is called without explicitly comparing result |
288 | // CHECK-FIXES: _mbsnicmp_l(U, V, 1, locale) != 0) |
289 | |
290 | if (_mbsnbcmp_l(U, V, 1, locale)) |
291 | return 0; |
292 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp_l' is called without explicitly comparing result |
293 | // CHECK-FIXES: _mbsnbcmp_l(U, V, 1, locale) != 0) |
294 | |
295 | if (_mbsnbicmp_l(U, V, 1, locale)) |
296 | return 0; |
297 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp_l' is called without explicitly comparing result |
298 | // CHECK-FIXES: _mbsnbicmp_l(U, V, 1, locale) != 0) |
299 | |
300 | return 1; |
301 | } |
302 | |
303 | int strcmp_wrapper1(const char* a, const char* b) { |
304 | return strcmp(a, b); |
305 | } |
306 | |
307 | int strcmp_wrapper2(const char* a, const char* b) { |
308 | return (a && b) ? strcmp(a, b) : 0; |
309 | } |
310 | |
311 | #define macro_strncmp(s1, s2, n) \ |
312 | (__extension__ (__builtin_constant_p (n) \ |
313 | && ((__builtin_constant_p (s1) \ |
314 | && strlen (s1) < ((size) (n))) \ |
315 | || (__builtin_constant_p (s2) \ |
316 | && strlen (s2) < ((size) (n)))) \ |
317 | ? strcmp (s1, s2) : strncmp (s1, s2, n))) |
318 | |
319 | int strncmp_macro(const char* a, const char* b) { |
320 | if (macro_strncmp(a, b, 4)) |
321 | return 0; |
322 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result |
323 | |
324 | if (macro_strncmp(a, b, 4) == 2) |
325 | return 0; |
326 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
327 | |
328 | if (macro_strncmp(a, b, 4) <= .0) |
329 | return 0; |
330 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast |
331 | |
332 | if (macro_strncmp(a, b, 4) + 0) |
333 | return 0; |
334 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: results of function 'strcmp' used by operator '+' |
335 | |
336 | return 1; |
337 | } |
338 | |