1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
2 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
3 // RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
4 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=alpha.security.taint,core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
5
6 //===----------------------------------------------------------------------===
7 // Declarations
8 //===----------------------------------------------------------------------===
9
10 // Some functions are so similar to each other that they follow the same code
11 // path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is
12 // defined, make sure to use the variants instead to make sure they are still
13 // checked by the analyzer.
14
15 // Some functions are implemented as builtins. These should be #defined as
16 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
17
18 // Functions that have variants and are also available as builtins should be
19 // declared carefully! See memcpy() for an example.
20
21 #ifdef USE_BUILTINS
22 # define BUILTIN(f) __builtin_ ## f
23 #else /* USE_BUILTINS */
24 # define BUILTIN(f) f
25 #endif /* USE_BUILTINS */
26
27 #define NULL 0
28 typedef typeof(sizeof(int)) size_t;
29
30 void clang_analyzer_eval(int);
31
32 int scanf(const char *restrict format, ...);
33
34 //===----------------------------------------------------------------------===
35 // strlen()
36 //===----------------------------------------------------------------------===
37
38 #define strlen BUILTIN(strlen)
39 size_t strlen(const char *s);
40
strlen_constant0()41 void strlen_constant0() {
42 clang_analyzer_eval(strlen("123") == 3); // expected-warning{{TRUE}}
43 }
44
strlen_constant1()45 void strlen_constant1() {
46 const char *a = "123";
47 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}}
48 }
49
strlen_constant2(char x)50 void strlen_constant2(char x) {
51 char a[] = "123";
52 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}}
53
54 a[0] = x;
55 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{UNKNOWN}}
56 }
57
strlen_null()58 size_t strlen_null() {
59 return strlen(0); // expected-warning{{Null pointer argument in call to string length function}}
60 }
61
strlen_fn()62 size_t strlen_fn() {
63 return strlen((char*)&strlen_fn); // expected-warning{{Argument to string length function is the address of the function 'strlen_fn', which is not a null-terminated string}}
64 }
65
strlen_nonloc()66 size_t strlen_nonloc() {
67 label:
68 return strlen((char*)&&label); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
69 }
70
strlen_subregion()71 void strlen_subregion() {
72 struct two_strings { char a[2], b[2]; };
73 extern void use_two_strings(struct two_strings *);
74
75 struct two_strings z;
76 use_two_strings(&z);
77
78 size_t a = strlen(z.a);
79 z.b[0] = 5;
80 size_t b = strlen(z.a);
81 if (a == 0)
82 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
83
84 use_two_strings(&z);
85
86 size_t c = strlen(z.a);
87 if (a == 0)
88 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
89 }
90
91 extern void use_string(char *);
strlen_argument(char * x)92 void strlen_argument(char *x) {
93 size_t a = strlen(x);
94 size_t b = strlen(x);
95 if (a == 0)
96 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
97
98 use_string(x);
99
100 size_t c = strlen(x);
101 if (a == 0)
102 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
103 }
104
105 extern char global_str[];
strlen_global()106 void strlen_global() {
107 size_t a = strlen(global_str);
108 size_t b = strlen(global_str);
109 if (a == 0) {
110 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
111 // Make sure clang_analyzer_eval does not invalidate globals.
112 clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}}
113 }
114
115 // Call a function with unknown effects, which should invalidate globals.
116 use_string(0);
117
118 size_t c = strlen(global_str);
119 if (a == 0)
120 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
121 }
122
strlen_indirect(char * x)123 void strlen_indirect(char *x) {
124 size_t a = strlen(x);
125 char *p = x;
126 char **p2 = &p;
127 size_t b = strlen(x);
128 if (a == 0)
129 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
130
131 extern void use_string_ptr(char*const*);
132 use_string_ptr(p2);
133
134 size_t c = strlen(x);
135 if (a == 0)
136 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
137 }
138
strlen_indirect2(char * x)139 void strlen_indirect2(char *x) {
140 size_t a = strlen(x);
141 char *p = x;
142 char **p2 = &p;
143 extern void use_string_ptr2(char**);
144 use_string_ptr2(p2);
145
146 size_t c = strlen(x);
147 if (a == 0)
148 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
149 }
150
strlen_liveness(const char * x)151 void strlen_liveness(const char *x) {
152 if (strlen(x) < 5)
153 return;
154 clang_analyzer_eval(strlen(x) < 5); // expected-warning{{FALSE}}
155 }
156
157 //===----------------------------------------------------------------------===
158 // strnlen()
159 //===----------------------------------------------------------------------===
160
161 size_t strnlen(const char *s, size_t maxlen);
162
strnlen_constant0()163 void strnlen_constant0() {
164 clang_analyzer_eval(strnlen("123", 10) == 3); // expected-warning{{TRUE}}
165 }
166
strnlen_constant1()167 void strnlen_constant1() {
168 const char *a = "123";
169 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}}
170 }
171
strnlen_constant2(char x)172 void strnlen_constant2(char x) {
173 char a[] = "123";
174 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}}
175 a[0] = x;
176 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{UNKNOWN}}
177 }
178
strnlen_constant4()179 void strnlen_constant4() {
180 clang_analyzer_eval(strnlen("123456", 3) == 3); // expected-warning{{TRUE}}
181 }
182
strnlen_constant5()183 void strnlen_constant5() {
184 const char *a = "123456";
185 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}}
186 }
187
strnlen_constant6(char x)188 void strnlen_constant6(char x) {
189 char a[] = "123456";
190 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}}
191 a[0] = x;
192 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{UNKNOWN}}
193 }
194
strnlen_null()195 size_t strnlen_null() {
196 return strnlen(0, 3); // expected-warning{{Null pointer argument in call to string length function}}
197 }
198
strnlen_fn()199 size_t strnlen_fn() {
200 return strnlen((char*)&strlen_fn, 3); // expected-warning{{Argument to string length function is the address of the function 'strlen_fn', which is not a null-terminated string}}
201 }
202
strnlen_nonloc()203 size_t strnlen_nonloc() {
204 label:
205 return strnlen((char*)&&label, 3); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
206 }
207
strnlen_zero()208 void strnlen_zero() {
209 clang_analyzer_eval(strnlen("abc", 0) == 0); // expected-warning{{TRUE}}
210 clang_analyzer_eval(strnlen(NULL, 0) == 0); // expected-warning{{TRUE}}
211 }
212
strnlen_compound_literal()213 size_t strnlen_compound_literal() {
214 // This used to crash because we don't model the string lengths of
215 // compound literals.
216 return strnlen((char[]) { 'a', 'b', 0 }, 1);
217 }
218
strnlen_unknown_limit(float f)219 size_t strnlen_unknown_limit(float f) {
220 // This used to crash because we don't model the integer values of floats.
221 return strnlen("abc", (int)f);
222 }
223
strnlen_is_not_strlen(char * x)224 void strnlen_is_not_strlen(char *x) {
225 clang_analyzer_eval(strnlen(x, 10) == strlen(x)); // expected-warning{{UNKNOWN}}
226 }
227
strnlen_at_limit(char * x)228 void strnlen_at_limit(char *x) {
229 size_t len = strnlen(x, 10);
230 clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}}
231 clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}}
232 clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}}
233 }
234
strnlen_at_actual(size_t limit)235 void strnlen_at_actual(size_t limit) {
236 size_t len = strnlen("abc", limit);
237 clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}}
238 // This is due to eager assertion in strnlen.
239 if (limit == 0) {
240 clang_analyzer_eval(len == 0); // expected-warning{{TRUE}}
241 } else {
242 clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}}
243 clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}}
244 }
245 }
246
247 //===----------------------------------------------------------------------===
248 // strcpy()
249 //===----------------------------------------------------------------------===
250
251 #ifdef VARIANT
252
253 #define __strcpy_chk BUILTIN(__strcpy_chk)
254 char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
255
256 #define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1)
257
258 #else /* VARIANT */
259
260 #define strcpy BUILTIN(strcpy)
261 char *strcpy(char *restrict s1, const char *restrict s2);
262
263 #endif /* VARIANT */
264
265
strcpy_null_dst(char * x)266 void strcpy_null_dst(char *x) {
267 strcpy(NULL, x); // expected-warning{{Null pointer argument in call to string copy function}}
268 }
269
strcpy_null_src(char * x)270 void strcpy_null_src(char *x) {
271 strcpy(x, NULL); // expected-warning{{Null pointer argument in call to string copy function}}
272 }
273
strcpy_fn(char * x)274 void strcpy_fn(char *x) {
275 strcpy(x, (char*)&strcpy_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
276 }
277
strcpy_fn_const(char * x)278 void strcpy_fn_const(char *x) {
279 strcpy(x, (const char*)&strcpy_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
280 }
281
282 extern int globalInt;
strcpy_effects(char * x,char * y)283 void strcpy_effects(char *x, char *y) {
284 char a = x[0];
285 if (globalInt != 42)
286 return;
287
288 clang_analyzer_eval(strcpy(x, y) == x); // expected-warning{{TRUE}}
289 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}}
290 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
291 clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}}
292 }
293
strcpy_overflow(char * y)294 void strcpy_overflow(char *y) {
295 char x[4];
296 if (strlen(y) == 4)
297 strcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
298 }
299
strcpy_no_overflow(char * y)300 void strcpy_no_overflow(char *y) {
301 char x[4];
302 if (strlen(y) == 3)
303 strcpy(x, y); // no-warning
304 }
305
306 //===----------------------------------------------------------------------===
307 // stpcpy()
308 //===----------------------------------------------------------------------===
309
310 #ifdef VARIANT
311
312 #define __stpcpy_chk BUILTIN(__stpcpy_chk)
313 char *__stpcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
314
315 #define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1)
316
317 #else /* VARIANT */
318
319 #define stpcpy BUILTIN(stpcpy)
320 char *stpcpy(char *restrict s1, const char *restrict s2);
321
322 #endif /* VARIANT */
323
324
stpcpy_effect(char * x,char * y)325 void stpcpy_effect(char *x, char *y) {
326 char a = x[0];
327
328 clang_analyzer_eval(stpcpy(x, y) == &x[strlen(y)]); // expected-warning{{TRUE}}
329 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}}
330 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
331 }
332
stpcpy_overflow(char * y)333 void stpcpy_overflow(char *y) {
334 char x[4];
335 if (strlen(y) == 4)
336 stpcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
337 }
338
stpcpy_no_overflow(char * y)339 void stpcpy_no_overflow(char *y) {
340 char x[4];
341 if (strlen(y) == 3)
342 stpcpy(x, y); // no-warning
343 }
344
345 //===----------------------------------------------------------------------===
346 // strcat()
347 //===----------------------------------------------------------------------===
348
349 #ifdef VARIANT
350
351 #define __strcat_chk BUILTIN(__strcat_chk)
352 char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen);
353
354 #define strcat(a,b) __strcat_chk(a,b,(size_t)-1)
355
356 #else /* VARIANT */
357
358 #define strcat BUILTIN(strcat)
359 char *strcat(char *restrict s1, const char *restrict s2);
360
361 #endif /* VARIANT */
362
363
strcat_null_dst(char * x)364 void strcat_null_dst(char *x) {
365 strcat(NULL, x); // expected-warning{{Null pointer argument in call to string copy function}}
366 }
367
strcat_null_src(char * x)368 void strcat_null_src(char *x) {
369 strcat(x, NULL); // expected-warning{{Null pointer argument in call to string copy function}}
370 }
371
strcat_fn(char * x)372 void strcat_fn(char *x) {
373 strcat(x, (char*)&strcat_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcat_fn', which is not a null-terminated string}}
374 }
375
strcat_effects(char * y)376 void strcat_effects(char *y) {
377 char x[8] = "123";
378 size_t orig_len = strlen(x);
379 char a = x[0];
380
381 if (strlen(y) != 4)
382 return;
383
384 clang_analyzer_eval(strcat(x, y) == x); // expected-warning{{TRUE}}
385 clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
386 }
387
strcat_overflow_0(char * y)388 void strcat_overflow_0(char *y) {
389 char x[4] = "12";
390 if (strlen(y) == 4)
391 strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
392 }
393
strcat_overflow_1(char * y)394 void strcat_overflow_1(char *y) {
395 char x[4] = "12";
396 if (strlen(y) == 3)
397 strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
398 }
399
strcat_overflow_2(char * y)400 void strcat_overflow_2(char *y) {
401 char x[4] = "12";
402 if (strlen(y) == 2)
403 strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
404 }
405
strcat_no_overflow(char * y)406 void strcat_no_overflow(char *y) {
407 char x[5] = "12";
408 if (strlen(y) == 2)
409 strcat(x, y); // no-warning
410 }
411
strcat_symbolic_dst_length(char * dst)412 void strcat_symbolic_dst_length(char *dst) {
413 strcat(dst, "1234");
414 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
415 }
416
strcat_symbolic_dst_length_taint(char * dst)417 void strcat_symbolic_dst_length_taint(char *dst) {
418 scanf("%s", dst); // Taint data.
419 strcat(dst, "1234");
420 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
421 }
422
strcat_unknown_src_length(char * src,int offset)423 void strcat_unknown_src_length(char *src, int offset) {
424 char dst[8] = "1234";
425 strcat(dst, &src[offset]);
426 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
427 }
428
429 // There is no strcat_unknown_dst_length because if we can't get a symbolic
430 // length for the "before" strlen, we won't be able to set one for "after".
431
strcat_too_big(char * dst,char * src)432 void strcat_too_big(char *dst, char *src) {
433 // We assume this can never actually happen, so we don't get a warning.
434 if (strlen(dst) != (((size_t)0) - 2))
435 return;
436 if (strlen(src) != 2)
437 return;
438 strcat(dst, src);
439 }
440
441
442 //===----------------------------------------------------------------------===
443 // strncpy()
444 //===----------------------------------------------------------------------===
445
446 #ifdef VARIANT
447
448 #define __strncpy_chk BUILTIN(__strncpy_chk)
449 char *__strncpy_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen);
450
451 #define strncpy(a,b,n) __strncpy_chk(a,b,n,(size_t)-1)
452
453 #else /* VARIANT */
454
455 #define strncpy BUILTIN(strncpy)
456 char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
457
458 #endif /* VARIANT */
459
460
strncpy_null_dst(char * x)461 void strncpy_null_dst(char *x) {
462 strncpy(NULL, x, 5); // expected-warning{{Null pointer argument in call to string copy function}}
463 }
464
strncpy_null_src(char * x)465 void strncpy_null_src(char *x) {
466 strncpy(x, NULL, 5); // expected-warning{{Null pointer argument in call to string copy function}}
467 }
468
strncpy_fn(char * x)469 void strncpy_fn(char *x) {
470 strncpy(x, (char*)&strcpy_fn, 5); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
471 }
472
strncpy_effects(char * x,char * y)473 void strncpy_effects(char *x, char *y) {
474 char a = x[0];
475
476 clang_analyzer_eval(strncpy(x, y, 5) == x); // expected-warning{{TRUE}}
477 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{UNKNOWN}}
478 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
479 }
480
strncpy_overflow(char * y)481 void strncpy_overflow(char *y) {
482 char x[4];
483 if (strlen(y) == 4)
484 strncpy(x, y, 5); // expected-warning{{Size argument is greater than the length of the destination buffer}}
485 }
486
strncpy_no_overflow(char * y)487 void strncpy_no_overflow(char *y) {
488 char x[4];
489 if (strlen(y) == 3)
490 strncpy(x, y, 5); // expected-warning{{Size argument is greater than the length of the destination buffer}}
491 }
492
strncpy_no_overflow2(char * y,int n)493 void strncpy_no_overflow2(char *y, int n) {
494 if (n <= 4)
495 return;
496
497 char x[4];
498 if (strlen(y) == 3)
499 strncpy(x, y, n); // expected-warning{{Size argument is greater than the length of the destination buffer}}
500 }
501
strncpy_truncate(char * y)502 void strncpy_truncate(char *y) {
503 char x[4];
504 if (strlen(y) == 4)
505 strncpy(x, y, 3); // no-warning
506 }
507
strncpy_no_truncate(char * y)508 void strncpy_no_truncate(char *y) {
509 char x[4];
510 if (strlen(y) == 3)
511 strncpy(x, y, 3); // no-warning
512 }
513
strncpy_exactly_matching_buffer(char * y)514 void strncpy_exactly_matching_buffer(char *y) {
515 char x[4];
516 strncpy(x, y, 4); // no-warning
517
518 // strncpy does not null-terminate, so we have no idea what the strlen is
519 // after this.
520 clang_analyzer_eval(strlen(x) > 4); // expected-warning{{UNKNOWN}}
521 }
522
strncpy_zero(char * src)523 void strncpy_zero(char *src) {
524 char dst[] = "123";
525 strncpy(dst, src, 0); // no-warning
526 }
527
strncpy_empty()528 void strncpy_empty() {
529 char dst[] = "123";
530 char src[] = "";
531 strncpy(dst, src, 4); // no-warning
532 }
533
534 //===----------------------------------------------------------------------===
535 // strncat()
536 //===----------------------------------------------------------------------===
537
538 #ifdef VARIANT
539
540 #define __strncat_chk BUILTIN(__strncat_chk)
541 char *__strncat_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen);
542
543 #define strncat(a,b,c) __strncat_chk(a,b,c, (size_t)-1)
544
545 #else /* VARIANT */
546
547 #define strncat BUILTIN(strncat)
548 char *strncat(char *restrict s1, const char *restrict s2, size_t n);
549
550 #endif /* VARIANT */
551
552
strncat_null_dst(char * x)553 void strncat_null_dst(char *x) {
554 strncat(NULL, x, 4); // expected-warning{{Null pointer argument in call to string copy function}}
555 }
556
strncat_null_src(char * x)557 void strncat_null_src(char *x) {
558 strncat(x, NULL, 4); // expected-warning{{Null pointer argument in call to string copy function}}
559 }
560
strncat_fn(char * x)561 void strncat_fn(char *x) {
562 strncat(x, (char*)&strncat_fn, 4); // expected-warning{{Argument to string copy function is the address of the function 'strncat_fn', which is not a null-terminated string}}
563 }
564
strncat_effects(char * y)565 void strncat_effects(char *y) {
566 char x[8] = "123";
567 size_t orig_len = strlen(x);
568 char a = x[0];
569
570 if (strlen(y) != 4)
571 return;
572
573 clang_analyzer_eval(strncat(x, y, strlen(y)) == x); // expected-warning{{TRUE}}
574 clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
575 }
576
strncat_overflow_0(char * y)577 void strncat_overflow_0(char *y) {
578 char x[4] = "12";
579 if (strlen(y) == 4)
580 strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
581 }
582
strncat_overflow_1(char * y)583 void strncat_overflow_1(char *y) {
584 char x[4] = "12";
585 if (strlen(y) == 3)
586 strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
587 }
588
strncat_overflow_2(char * y)589 void strncat_overflow_2(char *y) {
590 char x[4] = "12";
591 if (strlen(y) == 2)
592 strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
593 }
594
strncat_overflow_3(char * y)595 void strncat_overflow_3(char *y) {
596 char x[4] = "12";
597 if (strlen(y) == 4)
598 strncat(x, y, 2); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
599 }
strncat_no_overflow_1(char * y)600 void strncat_no_overflow_1(char *y) {
601 char x[5] = "12";
602 if (strlen(y) == 2)
603 strncat(x, y, strlen(y)); // no-warning
604 }
605
strncat_no_overflow_2(char * y)606 void strncat_no_overflow_2(char *y) {
607 char x[4] = "12";
608 if (strlen(y) == 4)
609 strncat(x, y, 1); // no-warning
610 }
611
strncat_symbolic_dst_length(char * dst)612 void strncat_symbolic_dst_length(char *dst) {
613 strncat(dst, "1234", 5);
614 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
615 }
616
strncat_symbolic_src_length(char * src)617 void strncat_symbolic_src_length(char *src) {
618 char dst[8] = "1234";
619 strncat(dst, src, 3);
620 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
621
622 char dst2[8] = "1234";
623 strncat(dst2, src, 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
624 }
625
strncat_unknown_src_length(char * src,int offset)626 void strncat_unknown_src_length(char *src, int offset) {
627 char dst[8] = "1234";
628 strncat(dst, &src[offset], 3);
629 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
630
631 char dst2[8] = "1234";
632 strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
633 }
634
635 // There is no strncat_unknown_dst_length because if we can't get a symbolic
636 // length for the "before" strlen, we won't be able to set one for "after".
637
strncat_symbolic_limit(unsigned limit)638 void strncat_symbolic_limit(unsigned limit) {
639 char dst[6] = "1234";
640 char src[] = "567";
641 strncat(dst, src, limit); // no-warning
642
643 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
644 clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}}
645 }
646
strncat_unknown_limit(float limit)647 void strncat_unknown_limit(float limit) {
648 char dst[6] = "1234";
649 char src[] = "567";
650 strncat(dst, src, (size_t)limit); // no-warning
651
652 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
653 clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}}
654 }
655
strncat_too_big(char * dst,char * src)656 void strncat_too_big(char *dst, char *src) {
657 // We assume this will never actually happen, so we don't get a warning.
658 if (strlen(dst) != (((size_t)0) - 2))
659 return;
660 if (strlen(src) != 2)
661 return;
662 strncat(dst, src, 2);
663 }
664
strncat_zero(char * src)665 void strncat_zero(char *src) {
666 char dst[] = "123";
667 strncat(dst, src, 0); // no-warning
668 }
669
strncat_empty()670 void strncat_empty() {
671 char dst[8] = "123";
672 char src[] = "";
673 strncat(dst, src, 4); // no-warning
674 }
675
676 //===----------------------------------------------------------------------===
677 // strcmp()
678 //===----------------------------------------------------------------------===
679
680 #define strcmp BUILTIN(strcmp)
681 int strcmp(const char * s1, const char * s2);
682
strcmp_constant0()683 void strcmp_constant0() {
684 clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}}
685 }
686
strcmp_constant_and_var_0()687 void strcmp_constant_and_var_0() {
688 char *x = "123";
689 clang_analyzer_eval(strcmp(x, "123") == 0); // expected-warning{{TRUE}}
690 }
691
strcmp_constant_and_var_1()692 void strcmp_constant_and_var_1() {
693 char *x = "123";
694 clang_analyzer_eval(strcmp("123", x) == 0); // expected-warning{{TRUE}}
695 }
696
strcmp_0()697 void strcmp_0() {
698 char *x = "123";
699 char *y = "123";
700 clang_analyzer_eval(strcmp(x, y) == 0); // expected-warning{{TRUE}}
701 }
702
strcmp_1()703 void strcmp_1() {
704 char *x = "234";
705 char *y = "123";
706 clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}}
707 }
708
strcmp_2()709 void strcmp_2() {
710 char *x = "123";
711 char *y = "234";
712 clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
713 }
714
strcmp_null_0()715 void strcmp_null_0() {
716 char *x = NULL;
717 char *y = "123";
718 strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
719 }
720
strcmp_null_1()721 void strcmp_null_1() {
722 char *x = "123";
723 char *y = NULL;
724 strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
725 }
726
strcmp_diff_length_0()727 void strcmp_diff_length_0() {
728 char *x = "12345";
729 char *y = "234";
730 clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
731 }
732
strcmp_diff_length_1()733 void strcmp_diff_length_1() {
734 char *x = "123";
735 char *y = "23456";
736 clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
737 }
738
strcmp_diff_length_2()739 void strcmp_diff_length_2() {
740 char *x = "12345";
741 char *y = "123";
742 clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}}
743 }
744
strcmp_diff_length_3()745 void strcmp_diff_length_3() {
746 char *x = "123";
747 char *y = "12345";
748 clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
749 }
750
strcmp_embedded_null()751 void strcmp_embedded_null () {
752 clang_analyzer_eval(strcmp("\0z", "\0y") == 0); // expected-warning{{TRUE}}
753 }
754
strcmp_unknown_arg(char * unknown)755 void strcmp_unknown_arg (char *unknown) {
756 clang_analyzer_eval(strcmp(unknown, unknown) == 0); // expected-warning{{TRUE}}
757 }
758
759 //===----------------------------------------------------------------------===
760 // strncmp()
761 //===----------------------------------------------------------------------===
762
763 #define strncmp BUILTIN(strncmp)
764 int strncmp(const char *s1, const char *s2, size_t n);
765
strncmp_constant0()766 void strncmp_constant0() {
767 clang_analyzer_eval(strncmp("123", "123", 3) == 0); // expected-warning{{TRUE}}
768 }
769
strncmp_constant_and_var_0()770 void strncmp_constant_and_var_0() {
771 char *x = "123";
772 clang_analyzer_eval(strncmp(x, "123", 3) == 0); // expected-warning{{TRUE}}
773 }
774
strncmp_constant_and_var_1()775 void strncmp_constant_and_var_1() {
776 char *x = "123";
777 clang_analyzer_eval(strncmp("123", x, 3) == 0); // expected-warning{{TRUE}}
778 }
779
strncmp_0()780 void strncmp_0() {
781 char *x = "123";
782 char *y = "123";
783 clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
784 }
785
strncmp_1()786 void strncmp_1() {
787 char *x = "234";
788 char *y = "123";
789 clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}}
790 }
791
strncmp_2()792 void strncmp_2() {
793 char *x = "123";
794 char *y = "234";
795 clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}}
796 }
797
strncmp_null_0()798 void strncmp_null_0() {
799 char *x = NULL;
800 char *y = "123";
801 strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
802 }
803
strncmp_null_1()804 void strncmp_null_1() {
805 char *x = "123";
806 char *y = NULL;
807 strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
808 }
809
strncmp_diff_length_0()810 void strncmp_diff_length_0() {
811 char *x = "12345";
812 char *y = "234";
813 clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
814 }
815
strncmp_diff_length_1()816 void strncmp_diff_length_1() {
817 char *x = "123";
818 char *y = "23456";
819 clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
820 }
821
strncmp_diff_length_2()822 void strncmp_diff_length_2() {
823 char *x = "12345";
824 char *y = "123";
825 clang_analyzer_eval(strncmp(x, y, 5) == 1); // expected-warning{{TRUE}}
826 }
827
strncmp_diff_length_3()828 void strncmp_diff_length_3() {
829 char *x = "123";
830 char *y = "12345";
831 clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
832 }
833
strncmp_diff_length_4()834 void strncmp_diff_length_4() {
835 char *x = "123";
836 char *y = "12345";
837 clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
838 }
839
strncmp_diff_length_5()840 void strncmp_diff_length_5() {
841 char *x = "012";
842 char *y = "12345";
843 clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}}
844 }
845
strncmp_diff_length_6()846 void strncmp_diff_length_6() {
847 char *x = "234";
848 char *y = "12345";
849 clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}}
850 }
851
strncmp_embedded_null()852 void strncmp_embedded_null () {
853 clang_analyzer_eval(strncmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
854 }
855
856 //===----------------------------------------------------------------------===
857 // strcasecmp()
858 //===----------------------------------------------------------------------===
859
860 #define strcasecmp BUILTIN(strcasecmp)
861 int strcasecmp(const char *s1, const char *s2);
862
strcasecmp_constant0()863 void strcasecmp_constant0() {
864 clang_analyzer_eval(strcasecmp("abc", "Abc") == 0); // expected-warning{{TRUE}}
865 }
866
strcasecmp_constant_and_var_0()867 void strcasecmp_constant_and_var_0() {
868 char *x = "abc";
869 clang_analyzer_eval(strcasecmp(x, "Abc") == 0); // expected-warning{{TRUE}}
870 }
871
strcasecmp_constant_and_var_1()872 void strcasecmp_constant_and_var_1() {
873 char *x = "abc";
874 clang_analyzer_eval(strcasecmp("Abc", x) == 0); // expected-warning{{TRUE}}
875 }
876
strcasecmp_0()877 void strcasecmp_0() {
878 char *x = "abc";
879 char *y = "Abc";
880 clang_analyzer_eval(strcasecmp(x, y) == 0); // expected-warning{{TRUE}}
881 }
882
strcasecmp_1()883 void strcasecmp_1() {
884 char *x = "Bcd";
885 char *y = "abc";
886 clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}}
887 }
888
strcasecmp_2()889 void strcasecmp_2() {
890 char *x = "abc";
891 char *y = "Bcd";
892 clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
893 }
894
strcasecmp_null_0()895 void strcasecmp_null_0() {
896 char *x = NULL;
897 char *y = "123";
898 strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
899 }
900
strcasecmp_null_1()901 void strcasecmp_null_1() {
902 char *x = "123";
903 char *y = NULL;
904 strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
905 }
906
strcasecmp_diff_length_0()907 void strcasecmp_diff_length_0() {
908 char *x = "abcde";
909 char *y = "aBd";
910 clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
911 }
912
strcasecmp_diff_length_1()913 void strcasecmp_diff_length_1() {
914 char *x = "abc";
915 char *y = "aBdef";
916 clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
917 }
918
strcasecmp_diff_length_2()919 void strcasecmp_diff_length_2() {
920 char *x = "aBcDe";
921 char *y = "abc";
922 clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}}
923 }
924
strcasecmp_diff_length_3()925 void strcasecmp_diff_length_3() {
926 char *x = "aBc";
927 char *y = "abcde";
928 clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
929 }
930
strcasecmp_embedded_null()931 void strcasecmp_embedded_null () {
932 clang_analyzer_eval(strcasecmp("ab\0zz", "ab\0yy") == 0); // expected-warning{{TRUE}}
933 }
934
935 //===----------------------------------------------------------------------===
936 // strncasecmp()
937 //===----------------------------------------------------------------------===
938
939 #define strncasecmp BUILTIN(strncasecmp)
940 int strncasecmp(const char *s1, const char *s2, size_t n);
941
strncasecmp_constant0()942 void strncasecmp_constant0() {
943 clang_analyzer_eval(strncasecmp("abc", "Abc", 3) == 0); // expected-warning{{TRUE}}
944 }
945
strncasecmp_constant_and_var_0()946 void strncasecmp_constant_and_var_0() {
947 char *x = "abc";
948 clang_analyzer_eval(strncasecmp(x, "Abc", 3) == 0); // expected-warning{{TRUE}}
949 }
950
strncasecmp_constant_and_var_1()951 void strncasecmp_constant_and_var_1() {
952 char *x = "abc";
953 clang_analyzer_eval(strncasecmp("Abc", x, 3) == 0); // expected-warning{{TRUE}}
954 }
955
strncasecmp_0()956 void strncasecmp_0() {
957 char *x = "abc";
958 char *y = "Abc";
959 clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
960 }
961
strncasecmp_1()962 void strncasecmp_1() {
963 char *x = "Bcd";
964 char *y = "abc";
965 clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}}
966 }
967
strncasecmp_2()968 void strncasecmp_2() {
969 char *x = "abc";
970 char *y = "Bcd";
971 clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}}
972 }
973
strncasecmp_null_0()974 void strncasecmp_null_0() {
975 char *x = NULL;
976 char *y = "123";
977 strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
978 }
979
strncasecmp_null_1()980 void strncasecmp_null_1() {
981 char *x = "123";
982 char *y = NULL;
983 strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
984 }
985
strncasecmp_diff_length_0()986 void strncasecmp_diff_length_0() {
987 char *x = "abcde";
988 char *y = "aBd";
989 clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
990 }
991
strncasecmp_diff_length_1()992 void strncasecmp_diff_length_1() {
993 char *x = "abc";
994 char *y = "aBdef";
995 clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
996 }
997
strncasecmp_diff_length_2()998 void strncasecmp_diff_length_2() {
999 char *x = "aBcDe";
1000 char *y = "abc";
1001 clang_analyzer_eval(strncasecmp(x, y, 5) == 1); // expected-warning{{TRUE}}
1002 }
1003
strncasecmp_diff_length_3()1004 void strncasecmp_diff_length_3() {
1005 char *x = "aBc";
1006 char *y = "abcde";
1007 clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
1008 }
1009
strncasecmp_diff_length_4()1010 void strncasecmp_diff_length_4() {
1011 char *x = "abcde";
1012 char *y = "aBc";
1013 clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
1014 }
1015
strncasecmp_diff_length_5()1016 void strncasecmp_diff_length_5() {
1017 char *x = "abcde";
1018 char *y = "aBd";
1019 clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}}
1020 }
1021
strncasecmp_diff_length_6()1022 void strncasecmp_diff_length_6() {
1023 char *x = "aBDe";
1024 char *y = "abc";
1025 clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}}
1026 }
1027
strncasecmp_embedded_null()1028 void strncasecmp_embedded_null () {
1029 clang_analyzer_eval(strncasecmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
1030 }
1031
1032 //===----------------------------------------------------------------------===
1033 // strsep()
1034 //===----------------------------------------------------------------------===
1035
1036 char *strsep(char **stringp, const char *delim);
1037
strsep_null_delim(char * s)1038 void strsep_null_delim(char *s) {
1039 strsep(&s, NULL); // expected-warning{{Null pointer argument in call to strsep()}}
1040 }
1041
strsep_null_search()1042 void strsep_null_search() {
1043 strsep(NULL, ""); // expected-warning{{Null pointer argument in call to strsep()}}
1044 }
1045
strsep_return_original_pointer(char * s)1046 void strsep_return_original_pointer(char *s) {
1047 char *original = s;
1048 char *result = strsep(&s, ""); // no-warning
1049 clang_analyzer_eval(original == result); // expected-warning{{TRUE}}
1050 }
1051
strsep_null_string()1052 void strsep_null_string() {
1053 char *s = NULL;
1054 char *result = strsep(&s, ""); // no-warning
1055 clang_analyzer_eval(result == NULL); // expected-warning{{TRUE}}
1056 }
1057
strsep_changes_input_pointer(char * s)1058 void strsep_changes_input_pointer(char *s) {
1059 char *original = s;
1060 strsep(&s, ""); // no-warning
1061 clang_analyzer_eval(s == original); // expected-warning{{UNKNOWN}}
1062 clang_analyzer_eval(s == NULL); // expected-warning{{UNKNOWN}}
1063
1064 // Check that the value is symbolic.
1065 if (s == NULL) {
1066 clang_analyzer_eval(s == NULL); // expected-warning{{TRUE}}
1067 }
1068 }
1069
strsep_changes_input_string()1070 void strsep_changes_input_string() {
1071 char str[] = "abc";
1072
1073 clang_analyzer_eval(str[1] == 'b'); // expected-warning{{TRUE}}
1074
1075 char *s = str;
1076 strsep(&s, "b"); // no-warning
1077
1078 // The real strsep will change the first delimiter it finds into a NUL
1079 // character. For now, we just model the invalidation.
1080 clang_analyzer_eval(str[1] == 'b'); // expected-warning{{UNKNOWN}}
1081 }
1082
1083 //===----------------------------------------------------------------------===
1084 // FIXMEs
1085 //===----------------------------------------------------------------------===
1086
1087 // The analyzer_eval call below should evaluate to true. We are being too
1088 // aggressive in marking the (length of) src symbol dead. The length of dst
1089 // depends on src. This could be explicitely specified in the checker or the
1090 // logic for handling MetadataSymbol in SymbolManager needs to change.
strcat_symbolic_src_length(char * src)1091 void strcat_symbolic_src_length(char *src) {
1092 char dst[8] = "1234";
1093 strcat(dst, src);
1094 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{UNKNOWN}}
1095 }
1096
1097 // The analyzer_eval call below should evaluate to true. Most likely the same
1098 // issue as the test above.
strncpy_exactly_matching_buffer2(char * y)1099 void strncpy_exactly_matching_buffer2(char *y) {
1100 if (strlen(y) >= 4)
1101 return;
1102
1103 char x[4];
1104 strncpy(x, y, 4); // no-warning
1105
1106 // This time, we know that y fits in x anyway.
1107 clang_analyzer_eval(strlen(x) <= 3); // expected-warning{{UNKNOWN}}
1108 }
1109