• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
strcpy_effects(char * x,char * y)282 void strcpy_effects(char *x, char *y) {
283   char a = x[0];
284 
285   clang_analyzer_eval(strcpy(x, y) == x); // expected-warning{{TRUE}}
286   clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}}
287   clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
288 }
289 
strcpy_overflow(char * y)290 void strcpy_overflow(char *y) {
291   char x[4];
292   if (strlen(y) == 4)
293     strcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
294 }
295 
strcpy_no_overflow(char * y)296 void strcpy_no_overflow(char *y) {
297   char x[4];
298   if (strlen(y) == 3)
299     strcpy(x, y); // no-warning
300 }
301 
302 //===----------------------------------------------------------------------===
303 // stpcpy()
304 //===----------------------------------------------------------------------===
305 
306 #ifdef VARIANT
307 
308 #define __stpcpy_chk BUILTIN(__stpcpy_chk)
309 char *__stpcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
310 
311 #define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1)
312 
313 #else /* VARIANT */
314 
315 #define stpcpy BUILTIN(stpcpy)
316 char *stpcpy(char *restrict s1, const char *restrict s2);
317 
318 #endif /* VARIANT */
319 
320 
stpcpy_effect(char * x,char * y)321 void stpcpy_effect(char *x, char *y) {
322   char a = x[0];
323 
324   clang_analyzer_eval(stpcpy(x, y) == &x[strlen(y)]); // expected-warning{{TRUE}}
325   clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}}
326   clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
327 }
328 
stpcpy_overflow(char * y)329 void stpcpy_overflow(char *y) {
330   char x[4];
331   if (strlen(y) == 4)
332     stpcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
333 }
334 
stpcpy_no_overflow(char * y)335 void stpcpy_no_overflow(char *y) {
336   char x[4];
337   if (strlen(y) == 3)
338     stpcpy(x, y); // no-warning
339 }
340 
341 //===----------------------------------------------------------------------===
342 // strcat()
343 //===----------------------------------------------------------------------===
344 
345 #ifdef VARIANT
346 
347 #define __strcat_chk BUILTIN(__strcat_chk)
348 char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen);
349 
350 #define strcat(a,b) __strcat_chk(a,b,(size_t)-1)
351 
352 #else /* VARIANT */
353 
354 #define strcat BUILTIN(strcat)
355 char *strcat(char *restrict s1, const char *restrict s2);
356 
357 #endif /* VARIANT */
358 
359 
strcat_null_dst(char * x)360 void strcat_null_dst(char *x) {
361   strcat(NULL, x); // expected-warning{{Null pointer argument in call to string copy function}}
362 }
363 
strcat_null_src(char * x)364 void strcat_null_src(char *x) {
365   strcat(x, NULL); // expected-warning{{Null pointer argument in call to string copy function}}
366 }
367 
strcat_fn(char * x)368 void strcat_fn(char *x) {
369   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}}
370 }
371 
strcat_effects(char * y)372 void strcat_effects(char *y) {
373   char x[8] = "123";
374   size_t orig_len = strlen(x);
375   char a = x[0];
376 
377   if (strlen(y) != 4)
378     return;
379 
380   clang_analyzer_eval(strcat(x, y) == x); // expected-warning{{TRUE}}
381   clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
382 }
383 
strcat_overflow_0(char * y)384 void strcat_overflow_0(char *y) {
385   char x[4] = "12";
386   if (strlen(y) == 4)
387     strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
388 }
389 
strcat_overflow_1(char * y)390 void strcat_overflow_1(char *y) {
391   char x[4] = "12";
392   if (strlen(y) == 3)
393     strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
394 }
395 
strcat_overflow_2(char * y)396 void strcat_overflow_2(char *y) {
397   char x[4] = "12";
398   if (strlen(y) == 2)
399     strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
400 }
401 
strcat_no_overflow(char * y)402 void strcat_no_overflow(char *y) {
403   char x[5] = "12";
404   if (strlen(y) == 2)
405     strcat(x, y); // no-warning
406 }
407 
strcat_symbolic_dst_length(char * dst)408 void strcat_symbolic_dst_length(char *dst) {
409 	strcat(dst, "1234");
410   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
411 }
412 
strcat_symbolic_dst_length_taint(char * dst)413 void strcat_symbolic_dst_length_taint(char *dst) {
414   scanf("%s", dst); // Taint data.
415   strcat(dst, "1234");
416   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
417 }
418 
strcat_unknown_src_length(char * src,int offset)419 void strcat_unknown_src_length(char *src, int offset) {
420 	char dst[8] = "1234";
421 	strcat(dst, &src[offset]);
422   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
423 }
424 
425 // There is no strcat_unknown_dst_length because if we can't get a symbolic
426 // length for the "before" strlen, we won't be able to set one for "after".
427 
strcat_too_big(char * dst,char * src)428 void strcat_too_big(char *dst, char *src) {
429 	if (strlen(dst) != (((size_t)0) - 2))
430 		return;
431 	if (strlen(src) != 2)
432 		return;
433 	strcat(dst, src); // expected-warning{{This expression will create a string whose length is too big to be represented as a size_t}}
434 }
435 
436 
437 //===----------------------------------------------------------------------===
438 // strncpy()
439 //===----------------------------------------------------------------------===
440 
441 #ifdef VARIANT
442 
443 #define __strncpy_chk BUILTIN(__strncpy_chk)
444 char *__strncpy_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen);
445 
446 #define strncpy(a,b,n) __strncpy_chk(a,b,n,(size_t)-1)
447 
448 #else /* VARIANT */
449 
450 #define strncpy BUILTIN(strncpy)
451 char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
452 
453 #endif /* VARIANT */
454 
455 
strncpy_null_dst(char * x)456 void strncpy_null_dst(char *x) {
457   strncpy(NULL, x, 5); // expected-warning{{Null pointer argument in call to string copy function}}
458 }
459 
strncpy_null_src(char * x)460 void strncpy_null_src(char *x) {
461   strncpy(x, NULL, 5); // expected-warning{{Null pointer argument in call to string copy function}}
462 }
463 
strncpy_fn(char * x)464 void strncpy_fn(char *x) {
465   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}}
466 }
467 
strncpy_effects(char * x,char * y)468 void strncpy_effects(char *x, char *y) {
469   char a = x[0];
470 
471   clang_analyzer_eval(strncpy(x, y, 5) == x); // expected-warning{{TRUE}}
472   clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{UNKNOWN}}
473   clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
474 }
475 
strncpy_overflow(char * y)476 void strncpy_overflow(char *y) {
477   char x[4];
478   if (strlen(y) == 4)
479     strncpy(x, y, 5); // expected-warning{{Size argument is greater than the length of the destination buffer}}
480 }
481 
strncpy_no_overflow(char * y)482 void strncpy_no_overflow(char *y) {
483   char x[4];
484   if (strlen(y) == 3)
485     strncpy(x, y, 5); // expected-warning{{Size argument is greater than the length of the destination buffer}}
486 }
487 
strncpy_no_overflow2(char * y,int n)488 void strncpy_no_overflow2(char *y, int n) {
489 	if (n <= 4)
490 		return;
491 
492   char x[4];
493   if (strlen(y) == 3)
494     strncpy(x, y, n); // expected-warning{{Size argument is greater than the length of the destination buffer}}
495 }
496 
strncpy_truncate(char * y)497 void strncpy_truncate(char *y) {
498   char x[4];
499   if (strlen(y) == 4)
500     strncpy(x, y, 3); // no-warning
501 }
502 
strncpy_no_truncate(char * y)503 void strncpy_no_truncate(char *y) {
504   char x[4];
505   if (strlen(y) == 3)
506     strncpy(x, y, 3); // no-warning
507 }
508 
strncpy_exactly_matching_buffer(char * y)509 void strncpy_exactly_matching_buffer(char *y) {
510 	char x[4];
511 	strncpy(x, y, 4); // no-warning
512 
513 	// strncpy does not null-terminate, so we have no idea what the strlen is
514 	// after this.
515   clang_analyzer_eval(strlen(x) > 4); // expected-warning{{UNKNOWN}}
516 }
517 
strncpy_zero(char * src)518 void strncpy_zero(char *src) {
519   char dst[] = "123";
520   strncpy(dst, src, 0); // no-warning
521 }
522 
strncpy_empty()523 void strncpy_empty() {
524   char dst[] = "123";
525   char src[] = "";
526   strncpy(dst, src, 4); // no-warning
527 }
528 
529 //===----------------------------------------------------------------------===
530 // strncat()
531 //===----------------------------------------------------------------------===
532 
533 #ifdef VARIANT
534 
535 #define __strncat_chk BUILTIN(__strncat_chk)
536 char *__strncat_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen);
537 
538 #define strncat(a,b,c) __strncat_chk(a,b,c, (size_t)-1)
539 
540 #else /* VARIANT */
541 
542 #define strncat BUILTIN(strncat)
543 char *strncat(char *restrict s1, const char *restrict s2, size_t n);
544 
545 #endif /* VARIANT */
546 
547 
strncat_null_dst(char * x)548 void strncat_null_dst(char *x) {
549   strncat(NULL, x, 4); // expected-warning{{Null pointer argument in call to string copy function}}
550 }
551 
strncat_null_src(char * x)552 void strncat_null_src(char *x) {
553   strncat(x, NULL, 4); // expected-warning{{Null pointer argument in call to string copy function}}
554 }
555 
strncat_fn(char * x)556 void strncat_fn(char *x) {
557   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}}
558 }
559 
strncat_effects(char * y)560 void strncat_effects(char *y) {
561   char x[8] = "123";
562   size_t orig_len = strlen(x);
563   char a = x[0];
564 
565   if (strlen(y) != 4)
566     return;
567 
568   clang_analyzer_eval(strncat(x, y, strlen(y)) == x); // expected-warning{{TRUE}}
569   clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
570 }
571 
strncat_overflow_0(char * y)572 void strncat_overflow_0(char *y) {
573   char x[4] = "12";
574   if (strlen(y) == 4)
575     strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
576 }
577 
strncat_overflow_1(char * y)578 void strncat_overflow_1(char *y) {
579   char x[4] = "12";
580   if (strlen(y) == 3)
581     strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
582 }
583 
strncat_overflow_2(char * y)584 void strncat_overflow_2(char *y) {
585   char x[4] = "12";
586   if (strlen(y) == 2)
587     strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
588 }
589 
strncat_overflow_3(char * y)590 void strncat_overflow_3(char *y) {
591   char x[4] = "12";
592   if (strlen(y) == 4)
593     strncat(x, y, 2); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
594 }
strncat_no_overflow_1(char * y)595 void strncat_no_overflow_1(char *y) {
596   char x[5] = "12";
597   if (strlen(y) == 2)
598     strncat(x, y, strlen(y)); // no-warning
599 }
600 
strncat_no_overflow_2(char * y)601 void strncat_no_overflow_2(char *y) {
602   char x[4] = "12";
603   if (strlen(y) == 4)
604     strncat(x, y, 1); // no-warning
605 }
606 
strncat_symbolic_dst_length(char * dst)607 void strncat_symbolic_dst_length(char *dst) {
608   strncat(dst, "1234", 5);
609   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
610 }
611 
strncat_symbolic_src_length(char * src)612 void strncat_symbolic_src_length(char *src) {
613   char dst[8] = "1234";
614   strncat(dst, src, 3);
615   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
616 
617   char dst2[8] = "1234";
618   strncat(dst2, src, 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
619 }
620 
strncat_unknown_src_length(char * src,int offset)621 void strncat_unknown_src_length(char *src, int offset) {
622   char dst[8] = "1234";
623   strncat(dst, &src[offset], 3);
624   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
625 
626   char dst2[8] = "1234";
627   strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
628 }
629 
630 // There is no strncat_unknown_dst_length because if we can't get a symbolic
631 // length for the "before" strlen, we won't be able to set one for "after".
632 
strncat_symbolic_limit(unsigned limit)633 void strncat_symbolic_limit(unsigned limit) {
634   char dst[6] = "1234";
635   char src[] = "567";
636   strncat(dst, src, limit); // no-warning
637 
638   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
639   clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}}
640 }
641 
strncat_unknown_limit(float limit)642 void strncat_unknown_limit(float limit) {
643   char dst[6] = "1234";
644   char src[] = "567";
645   strncat(dst, src, (size_t)limit); // no-warning
646 
647   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
648   clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}}
649 }
650 
strncat_too_big(char * dst,char * src)651 void strncat_too_big(char *dst, char *src) {
652   if (strlen(dst) != (((size_t)0) - 2))
653     return;
654   if (strlen(src) != 2)
655     return;
656   strncat(dst, src, 2); // expected-warning{{This expression will create a string whose length is too big to be represented as a size_t}}
657 }
658 
strncat_zero(char * src)659 void strncat_zero(char *src) {
660   char dst[] = "123";
661   strncat(dst, src, 0); // no-warning
662 }
663 
strncat_empty()664 void strncat_empty() {
665   char dst[8] = "123";
666   char src[] = "";
667   strncat(dst, src, 4); // no-warning
668 }
669 
670 //===----------------------------------------------------------------------===
671 // strcmp()
672 //===----------------------------------------------------------------------===
673 
674 #define strcmp BUILTIN(strcmp)
675 int strcmp(const char * s1, const char * s2);
676 
strcmp_constant0()677 void strcmp_constant0() {
678   clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}}
679 }
680 
strcmp_constant_and_var_0()681 void strcmp_constant_and_var_0() {
682   char *x = "123";
683   clang_analyzer_eval(strcmp(x, "123") == 0); // expected-warning{{TRUE}}
684 }
685 
strcmp_constant_and_var_1()686 void strcmp_constant_and_var_1() {
687   char *x = "123";
688   clang_analyzer_eval(strcmp("123", x) == 0); // expected-warning{{TRUE}}
689 }
690 
strcmp_0()691 void strcmp_0() {
692   char *x = "123";
693   char *y = "123";
694   clang_analyzer_eval(strcmp(x, y) == 0); // expected-warning{{TRUE}}
695 }
696 
strcmp_1()697 void strcmp_1() {
698   char *x = "234";
699   char *y = "123";
700   clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}}
701 }
702 
strcmp_2()703 void strcmp_2() {
704   char *x = "123";
705   char *y = "234";
706   clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
707 }
708 
strcmp_null_0()709 void strcmp_null_0() {
710   char *x = NULL;
711   char *y = "123";
712   strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
713 }
714 
strcmp_null_1()715 void strcmp_null_1() {
716   char *x = "123";
717   char *y = NULL;
718   strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
719 }
720 
strcmp_diff_length_0()721 void strcmp_diff_length_0() {
722   char *x = "12345";
723   char *y = "234";
724   clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
725 }
726 
strcmp_diff_length_1()727 void strcmp_diff_length_1() {
728   char *x = "123";
729   char *y = "23456";
730   clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
731 }
732 
strcmp_diff_length_2()733 void strcmp_diff_length_2() {
734   char *x = "12345";
735   char *y = "123";
736   clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}}
737 }
738 
strcmp_diff_length_3()739 void strcmp_diff_length_3() {
740   char *x = "123";
741   char *y = "12345";
742   clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
743 }
744 
strcmp_embedded_null()745 void strcmp_embedded_null () {
746 	clang_analyzer_eval(strcmp("\0z", "\0y") == 0); // expected-warning{{TRUE}}
747 }
748 
strcmp_unknown_arg(char * unknown)749 void strcmp_unknown_arg (char *unknown) {
750 	clang_analyzer_eval(strcmp(unknown, unknown) == 0); // expected-warning{{TRUE}}
751 }
752 
753 //===----------------------------------------------------------------------===
754 // strncmp()
755 //===----------------------------------------------------------------------===
756 
757 #define strncmp BUILTIN(strncmp)
758 int strncmp(const char *s1, const char *s2, size_t n);
759 
strncmp_constant0()760 void strncmp_constant0() {
761   clang_analyzer_eval(strncmp("123", "123", 3) == 0); // expected-warning{{TRUE}}
762 }
763 
strncmp_constant_and_var_0()764 void strncmp_constant_and_var_0() {
765   char *x = "123";
766   clang_analyzer_eval(strncmp(x, "123", 3) == 0); // expected-warning{{TRUE}}
767 }
768 
strncmp_constant_and_var_1()769 void strncmp_constant_and_var_1() {
770   char *x = "123";
771   clang_analyzer_eval(strncmp("123", x, 3) == 0); // expected-warning{{TRUE}}
772 }
773 
strncmp_0()774 void strncmp_0() {
775   char *x = "123";
776   char *y = "123";
777   clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
778 }
779 
strncmp_1()780 void strncmp_1() {
781   char *x = "234";
782   char *y = "123";
783   clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}}
784 }
785 
strncmp_2()786 void strncmp_2() {
787   char *x = "123";
788   char *y = "234";
789   clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}}
790 }
791 
strncmp_null_0()792 void strncmp_null_0() {
793   char *x = NULL;
794   char *y = "123";
795   strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
796 }
797 
strncmp_null_1()798 void strncmp_null_1() {
799   char *x = "123";
800   char *y = NULL;
801   strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
802 }
803 
strncmp_diff_length_0()804 void strncmp_diff_length_0() {
805   char *x = "12345";
806   char *y = "234";
807   clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
808 }
809 
strncmp_diff_length_1()810 void strncmp_diff_length_1() {
811   char *x = "123";
812   char *y = "23456";
813   clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
814 }
815 
strncmp_diff_length_2()816 void strncmp_diff_length_2() {
817   char *x = "12345";
818   char *y = "123";
819   clang_analyzer_eval(strncmp(x, y, 5) == 1); // expected-warning{{TRUE}}
820 }
821 
strncmp_diff_length_3()822 void strncmp_diff_length_3() {
823   char *x = "123";
824   char *y = "12345";
825   clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
826 }
827 
strncmp_diff_length_4()828 void strncmp_diff_length_4() {
829   char *x = "123";
830   char *y = "12345";
831   clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
832 }
833 
strncmp_diff_length_5()834 void strncmp_diff_length_5() {
835   char *x = "012";
836   char *y = "12345";
837   clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}}
838 }
839 
strncmp_diff_length_6()840 void strncmp_diff_length_6() {
841   char *x = "234";
842   char *y = "12345";
843   clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}}
844 }
845 
strncmp_embedded_null()846 void strncmp_embedded_null () {
847 	clang_analyzer_eval(strncmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
848 }
849 
850 //===----------------------------------------------------------------------===
851 // strcasecmp()
852 //===----------------------------------------------------------------------===
853 
854 #define strcasecmp BUILTIN(strcasecmp)
855 int strcasecmp(const char *s1, const char *s2);
856 
strcasecmp_constant0()857 void strcasecmp_constant0() {
858   clang_analyzer_eval(strcasecmp("abc", "Abc") == 0); // expected-warning{{TRUE}}
859 }
860 
strcasecmp_constant_and_var_0()861 void strcasecmp_constant_and_var_0() {
862   char *x = "abc";
863   clang_analyzer_eval(strcasecmp(x, "Abc") == 0); // expected-warning{{TRUE}}
864 }
865 
strcasecmp_constant_and_var_1()866 void strcasecmp_constant_and_var_1() {
867   char *x = "abc";
868   clang_analyzer_eval(strcasecmp("Abc", x) == 0); // expected-warning{{TRUE}}
869 }
870 
strcasecmp_0()871 void strcasecmp_0() {
872   char *x = "abc";
873   char *y = "Abc";
874   clang_analyzer_eval(strcasecmp(x, y) == 0); // expected-warning{{TRUE}}
875 }
876 
strcasecmp_1()877 void strcasecmp_1() {
878   char *x = "Bcd";
879   char *y = "abc";
880   clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}}
881 }
882 
strcasecmp_2()883 void strcasecmp_2() {
884   char *x = "abc";
885   char *y = "Bcd";
886   clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
887 }
888 
strcasecmp_null_0()889 void strcasecmp_null_0() {
890   char *x = NULL;
891   char *y = "123";
892   strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
893 }
894 
strcasecmp_null_1()895 void strcasecmp_null_1() {
896   char *x = "123";
897   char *y = NULL;
898   strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
899 }
900 
strcasecmp_diff_length_0()901 void strcasecmp_diff_length_0() {
902   char *x = "abcde";
903   char *y = "aBd";
904   clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
905 }
906 
strcasecmp_diff_length_1()907 void strcasecmp_diff_length_1() {
908   char *x = "abc";
909   char *y = "aBdef";
910   clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
911 }
912 
strcasecmp_diff_length_2()913 void strcasecmp_diff_length_2() {
914   char *x = "aBcDe";
915   char *y = "abc";
916   clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}}
917 }
918 
strcasecmp_diff_length_3()919 void strcasecmp_diff_length_3() {
920   char *x = "aBc";
921   char *y = "abcde";
922   clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
923 }
924 
strcasecmp_embedded_null()925 void strcasecmp_embedded_null () {
926 	clang_analyzer_eval(strcasecmp("ab\0zz", "ab\0yy") == 0); // expected-warning{{TRUE}}
927 }
928 
929 //===----------------------------------------------------------------------===
930 // strncasecmp()
931 //===----------------------------------------------------------------------===
932 
933 #define strncasecmp BUILTIN(strncasecmp)
934 int strncasecmp(const char *s1, const char *s2, size_t n);
935 
strncasecmp_constant0()936 void strncasecmp_constant0() {
937   clang_analyzer_eval(strncasecmp("abc", "Abc", 3) == 0); // expected-warning{{TRUE}}
938 }
939 
strncasecmp_constant_and_var_0()940 void strncasecmp_constant_and_var_0() {
941   char *x = "abc";
942   clang_analyzer_eval(strncasecmp(x, "Abc", 3) == 0); // expected-warning{{TRUE}}
943 }
944 
strncasecmp_constant_and_var_1()945 void strncasecmp_constant_and_var_1() {
946   char *x = "abc";
947   clang_analyzer_eval(strncasecmp("Abc", x, 3) == 0); // expected-warning{{TRUE}}
948 }
949 
strncasecmp_0()950 void strncasecmp_0() {
951   char *x = "abc";
952   char *y = "Abc";
953   clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
954 }
955 
strncasecmp_1()956 void strncasecmp_1() {
957   char *x = "Bcd";
958   char *y = "abc";
959   clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}}
960 }
961 
strncasecmp_2()962 void strncasecmp_2() {
963   char *x = "abc";
964   char *y = "Bcd";
965   clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}}
966 }
967 
strncasecmp_null_0()968 void strncasecmp_null_0() {
969   char *x = NULL;
970   char *y = "123";
971   strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
972 }
973 
strncasecmp_null_1()974 void strncasecmp_null_1() {
975   char *x = "123";
976   char *y = NULL;
977   strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
978 }
979 
strncasecmp_diff_length_0()980 void strncasecmp_diff_length_0() {
981   char *x = "abcde";
982   char *y = "aBd";
983   clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
984 }
985 
strncasecmp_diff_length_1()986 void strncasecmp_diff_length_1() {
987   char *x = "abc";
988   char *y = "aBdef";
989   clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
990 }
991 
strncasecmp_diff_length_2()992 void strncasecmp_diff_length_2() {
993   char *x = "aBcDe";
994   char *y = "abc";
995   clang_analyzer_eval(strncasecmp(x, y, 5) == 1); // expected-warning{{TRUE}}
996 }
997 
strncasecmp_diff_length_3()998 void strncasecmp_diff_length_3() {
999   char *x = "aBc";
1000   char *y = "abcde";
1001   clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
1002 }
1003 
strncasecmp_diff_length_4()1004 void strncasecmp_diff_length_4() {
1005   char *x = "abcde";
1006   char *y = "aBc";
1007   clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
1008 }
1009 
strncasecmp_diff_length_5()1010 void strncasecmp_diff_length_5() {
1011   char *x = "abcde";
1012   char *y = "aBd";
1013   clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}}
1014 }
1015 
strncasecmp_diff_length_6()1016 void strncasecmp_diff_length_6() {
1017   char *x = "aBDe";
1018   char *y = "abc";
1019   clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}}
1020 }
1021 
strncasecmp_embedded_null()1022 void strncasecmp_embedded_null () {
1023 	clang_analyzer_eval(strncasecmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
1024 }
1025 
1026 //===----------------------------------------------------------------------===
1027 // FIXMEs
1028 //===----------------------------------------------------------------------===
1029 
1030 // The analyzer_eval call below should evaluate to true. We are being too
1031 // aggressive in marking the (length of) src symbol dead. The length of dst
1032 // depends on src. This could be explicitely specified in the checker or the
1033 // logic for handling MetadataSymbol in SymbolManager needs to change.
strcat_symbolic_src_length(char * src)1034 void strcat_symbolic_src_length(char *src) {
1035 	char dst[8] = "1234";
1036 	strcat(dst, src);
1037   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{UNKNOWN}}
1038 }
1039 
1040 // The analyzer_eval call below should evaluate to true. Most likely the same
1041 // issue as the test above.
strncpy_exactly_matching_buffer2(char * y)1042 void strncpy_exactly_matching_buffer2(char *y) {
1043 	if (strlen(y) >= 4)
1044 		return;
1045 
1046 	char x[4];
1047 	strncpy(x, y, 4); // no-warning
1048 
1049 	// This time, we know that y fits in x anyway.
1050   clang_analyzer_eval(strlen(x) <= 3); // expected-warning{{UNKNOWN}}
1051 }
1052