340 lines · cpp
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 7typedef __SIZE_TYPE__ size;8 9struct locale_t {10 void* dummy;11} locale;12 13static const char A[] = "abc";14static const unsigned char U[] = "abc";15static const unsigned char V[] = "xyz";16static const wchar_t W[] = L"abc";17 18int strlen(const char *);19 20int memcmp(const void *, const void *, size);21int wmemcmp(const wchar_t *, const wchar_t *, size);22int memicmp(const void *, const void *, size);23int _memicmp(const void *, const void *, size);24int _memicmp_l(const void *, const void *, size, locale_t);25 26int strcmp(const char *, const char *);27int strncmp(const char *, const char *, size);28int strcasecmp(const char *, const char *);29int strncasecmp(const char *, const char *, size);30int stricmp(const char *, const char *);31int strcmpi(const char *, const char *);32int strnicmp(const char *, const char *, size);33int _stricmp(const char *, const char * );34int _strnicmp(const char *, const char *, size);35int _stricmp_l(const char *, const char *, locale_t);36int _strnicmp_l(const char *, const char *, size, locale_t);37 38int wcscmp(const wchar_t *, const wchar_t *);39int wcsncmp(const wchar_t *, const wchar_t *, size);40int wcscasecmp(const wchar_t *, const wchar_t *);41int wcsicmp(const wchar_t *, const wchar_t *);42int wcsnicmp(const wchar_t *, const wchar_t *, size);43int _wcsicmp(const wchar_t *, const wchar_t *);44int _wcsnicmp(const wchar_t *, const wchar_t *, size);45int _wcsicmp_l(const wchar_t *, const wchar_t *, locale_t);46int _wcsnicmp_l(const wchar_t *, const wchar_t *, size, locale_t);47 48int _mbscmp(const unsigned char *, const unsigned char *);49int _mbsncmp(const unsigned char *, const unsigned char *, size);50int _mbsnbcmp(const unsigned char *, const unsigned char *, size);51int _mbsnbicmp(const unsigned char *, const unsigned char *, size);52int _mbsicmp(const unsigned char *, const unsigned char *);53int _mbsnicmp(const unsigned char *, const unsigned char *, size);54int _mbscmp_l(const unsigned char *, const unsigned char *, locale_t);55int _mbsncmp_l(const unsigned char *, const unsigned char *, size, locale_t);56int _mbsicmp_l(const unsigned char *, const unsigned char *, locale_t);57int _mbsnicmp_l(const unsigned char *, const unsigned char *, size, locale_t);58int _mbsnbcmp_l(const unsigned char *, const unsigned char *, size, locale_t);59int _mbsnbicmp_l(const unsigned char *, const unsigned char *, size, locale_t);60 61int 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 result71 // 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 constant76 77 if (strcmp(A, "a") == -1)78 return 0;79 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant80 81 if (strcmp(A, "a") == true)82 return 0;83 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant84 85 if (strcmp(A, "a") < '0')86 return 0;87 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant88 89 if (strcmp(A, "a") < 0.)90 return 0;91 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast92 93 return 1;94}95 96int test_valid_patterns() {97 // The following cases are valid.98 if (strcmp(A, "a") < 0)99 return 0;100 if (strcmp(A, "a") == 0)101 return 0;102 if (strcmp(A, "a") <= 0)103 return 0;104 105 if (wcscmp(W, L"a") < 0)106 return 0;107 if (wcscmp(W, L"a") == 0)108 return 0;109 if (wcscmp(W, L"a") <= 0)110 return 0;111 112 return 1;113}114 115int test_implicit_compare_with_functions() {116 117 if (memcmp(A, "a", 1))118 return 0;119 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memcmp' is called without explicitly comparing result120 // CHECK-FIXES: if (memcmp(A, "a", 1) != 0)121 122 if (wmemcmp(W, L"a", 1))123 return 0;124 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wmemcmp' is called without explicitly comparing result125 // CHECK-FIXES: if (wmemcmp(W, L"a", 1) != 0)126 127 if (memicmp(A, "a", 1))128 return 0;129 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memicmp' is called without explicitly comparing result130 // CHECK-FIXES: if (memicmp(A, "a", 1) != 0)131 132 if (_memicmp(A, "a", 1))133 return 0;134 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp' is called without explicitly comparing result135 // CHECK-FIXES: if (_memicmp(A, "a", 1) != 0)136 137 if (_memicmp_l(A, "a", 1, locale))138 return 0;139 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp_l' is called without explicitly comparing result140 // CHECK-FIXES: if (_memicmp_l(A, "a", 1, locale) != 0)141 142 if (strcmp(A, "a"))143 return 0;144 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result145 // CHECK-FIXES: if (strcmp(A, "a") != 0)146 147 if (strncmp(A, "a", 1))148 return 0;149 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncmp' is called without explicitly comparing result150 // CHECK-FIXES: if (strncmp(A, "a", 1) != 0)151 152 if (strcasecmp(A, "a"))153 return 0;154 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcasecmp' is called without explicitly comparing result155 // CHECK-FIXES: if (strcasecmp(A, "a") != 0)156 157 if (strncasecmp(A, "a", 1))158 return 0;159 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncasecmp' is called without explicitly comparing result160 // CHECK-FIXES: if (strncasecmp(A, "a", 1) != 0)161 162 if (stricmp(A, "a"))163 return 0;164 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'stricmp' is called without explicitly comparing result165 // CHECK-FIXES: if (stricmp(A, "a") != 0)166 167 if (strcmpi(A, "a"))168 return 0;169 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmpi' is called without explicitly comparing result170 // CHECK-FIXES: if (strcmpi(A, "a") != 0)171 172 if (_stricmp(A, "a"))173 return 0;174 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp' is called without explicitly comparing result175 // CHECK-FIXES: if (_stricmp(A, "a") != 0)176 177 if (strnicmp(A, "a", 1))178 return 0;179 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strnicmp' is called without explicitly comparing result180 // CHECK-FIXES: if (strnicmp(A, "a", 1) != 0)181 182 if (_strnicmp(A, "a", 1))183 return 0;184 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp' is called without explicitly comparing result185 // CHECK-FIXES: if (_strnicmp(A, "a", 1) != 0)186 187 if (_stricmp_l(A, "a", locale))188 return 0;189 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp_l' is called without explicitly comparing result190 // CHECK-FIXES: if (_stricmp_l(A, "a", locale) != 0)191 192 if (_strnicmp_l(A, "a", 1, locale))193 return 0;194 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp_l' is called without explicitly comparing result195 // CHECK-FIXES: if (_strnicmp_l(A, "a", 1, locale) != 0)196 197 if (wcscmp(W, L"a"))198 return 0;199 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscmp' is called without explicitly comparing result200 // CHECK-FIXES: if (wcscmp(W, L"a") != 0)201 202 if (wcsncmp(W, L"a", 1))203 return 0;204 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsncmp' is called without explicitly comparing result205 // CHECK-FIXES: if (wcsncmp(W, L"a", 1) != 0)206 207 if (wcscasecmp(W, L"a"))208 return 0;209 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscasecmp' is called without explicitly comparing result210 // CHECK-FIXES: if (wcscasecmp(W, L"a") != 0)211 212 if (wcsicmp(W, L"a"))213 return 0;214 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsicmp' is called without explicitly comparing result215 // CHECK-FIXES: if (wcsicmp(W, L"a") != 0)216 217 if (_wcsicmp(W, L"a"))218 return 0;219 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp' is called without explicitly comparing result220 // CHECK-FIXES: if (_wcsicmp(W, L"a") != 0)221 222 if (_wcsicmp_l(W, L"a", locale))223 return 0;224 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp_l' is called without explicitly comparing result225 // CHECK-FIXES: if (_wcsicmp_l(W, L"a", locale) != 0)226 227 if (wcsnicmp(W, L"a", 1))228 return 0;229 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsnicmp' is called without explicitly comparing result230 // CHECK-FIXES: if (wcsnicmp(W, L"a", 1) != 0)231 232 if (_wcsnicmp(W, L"a", 1))233 return 0;234 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp' is called without explicitly comparing result235 // CHECK-FIXES: if (_wcsnicmp(W, L"a", 1) != 0)236 237 if (_wcsnicmp_l(W, L"a", 1, locale))238 return 0;239 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp_l' is called without explicitly comparing result240 // CHECK-FIXES: if (_wcsnicmp_l(W, L"a", 1, locale) != 0)241 242 if (_mbscmp(U, V))243 return 0;244 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp' is called without explicitly comparing result245 // CHECK-FIXES: if (_mbscmp(U, V) != 0)246 247 if (_mbsncmp(U, V, 1))248 return 0;249 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp' is called without explicitly comparing result250 // CHECK-FIXES: if (_mbsncmp(U, V, 1) != 0)251 252 if (_mbsnbcmp(U, V, 1))253 return 0;254 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp' is called without explicitly comparing result255 // CHECK-FIXES: if (_mbsnbcmp(U, V, 1) != 0)256 257 if (_mbsnbicmp(U, V, 1))258 return 0;259 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp' is called without explicitly comparing result260 // CHECK-FIXES: if (_mbsnbicmp(U, V, 1) != 0)261 262 if (_mbsicmp(U, V))263 return 0;264 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp' is called without explicitly comparing result265 // CHECK-FIXES: if (_mbsicmp(U, V) != 0)266 267 if (_mbsnicmp(U, V, 1))268 return 0;269 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp' is called without explicitly comparing result270 // CHECK-FIXES: if (_mbsnicmp(U, V, 1) != 0)271 272 if (_mbscmp_l(U, V, locale))273 return 0;274 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp_l' is called without explicitly comparing result275 // CHECK-FIXES: if (_mbscmp_l(U, V, locale) != 0)276 277 if (_mbsncmp_l(U, V, 1, locale))278 return 0;279 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp_l' is called without explicitly comparing result280 // CHECK-FIXES: if (_mbsncmp_l(U, V, 1, locale) != 0)281 282 if (_mbsicmp_l(U, V, locale))283 return 0;284 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp_l' is called without explicitly comparing result285 // CHECK-FIXES: if (_mbsicmp_l(U, V, locale) != 0)286 287 if (_mbsnicmp_l(U, V, 1, locale))288 return 0;289 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp_l' is called without explicitly comparing result290 // CHECK-FIXES: if (_mbsnicmp_l(U, V, 1, locale) != 0)291 292 if (_mbsnbcmp_l(U, V, 1, locale))293 return 0;294 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp_l' is called without explicitly comparing result295 // CHECK-FIXES: if (_mbsnbcmp_l(U, V, 1, locale) != 0)296 297 if (_mbsnbicmp_l(U, V, 1, locale))298 return 0;299 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp_l' is called without explicitly comparing result300 // CHECK-FIXES: if (_mbsnbicmp_l(U, V, 1, locale) != 0)301 302 return 1;303}304 305int strcmp_wrapper1(const char* a, const char* b) {306 return strcmp(a, b);307}308 309int strcmp_wrapper2(const char* a, const char* b) {310 return (a && b) ? strcmp(a, b) : 0;311}312 313#define macro_strncmp(s1, s2, n) \314 (__extension__ (__builtin_constant_p (n) \315 && ((__builtin_constant_p (s1) \316 && strlen (s1) < ((size) (n))) \317 || (__builtin_constant_p (s2) \318 && strlen (s2) < ((size) (n)))) \319 ? strcmp (s1, s2) : strncmp (s1, s2, n)))320 321int strncmp_macro(const char* a, const char* b) {322 if (macro_strncmp(a, b, 4))323 return 0;324 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result325 326 if (macro_strncmp(a, b, 4) == 2)327 return 0;328 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant329 330 if (macro_strncmp(a, b, 4) <= .0)331 return 0;332 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast333 334 if (macro_strncmp(a, b, 4) + 0)335 return 0;336 // CHECK-MESSAGES: [[@LINE-2]]:7: warning: results of function 'strcmp' used by operator '+'337 338 return 1;339}340