• 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 
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_check_modelling()683 void strcmp_check_modelling() {
684   char *x = "aa";
685   char *y = "a";
686   clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}}
687   clang_analyzer_eval(strcmp(x, y) <= 0); // expected-warning{{FALSE}}
688   clang_analyzer_eval(strcmp(x, y) > 1); // expected-warning{{UNKNOWN}}
689 
690   clang_analyzer_eval(strcmp(y, x) < 0); // expected-warning{{TRUE}}
691   clang_analyzer_eval(strcmp(y, x) >= 0); // expected-warning{{FALSE}}
692   clang_analyzer_eval(strcmp(y, x) < -1); // expected-warning{{UNKNOWN}}
693 }
694 
strcmp_constant0()695 void strcmp_constant0() {
696   clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}}
697 }
698 
strcmp_constant_and_var_0()699 void strcmp_constant_and_var_0() {
700   char *x = "123";
701   clang_analyzer_eval(strcmp(x, "123") == 0); // expected-warning{{TRUE}}
702 }
703 
strcmp_constant_and_var_1()704 void strcmp_constant_and_var_1() {
705   char *x = "123";
706   clang_analyzer_eval(strcmp("123", x) == 0); // expected-warning{{TRUE}}
707 }
708 
strcmp_0()709 void strcmp_0() {
710   char *x = "123";
711   char *y = "123";
712   clang_analyzer_eval(strcmp(x, y) == 0); // expected-warning{{TRUE}}
713 }
714 
strcmp_1()715 void strcmp_1() {
716   char *x = "234";
717   char *y = "123";
718   clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}}
719 }
720 
strcmp_2()721 void strcmp_2() {
722   char *x = "123";
723   char *y = "234";
724   clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
725 }
726 
strcmp_null_0()727 void strcmp_null_0() {
728   char *x = NULL;
729   char *y = "123";
730   strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
731 }
732 
strcmp_null_1()733 void strcmp_null_1() {
734   char *x = "123";
735   char *y = NULL;
736   strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
737 }
738 
strcmp_diff_length_0()739 void strcmp_diff_length_0() {
740   char *x = "12345";
741   char *y = "234";
742   clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
743 }
744 
strcmp_diff_length_1()745 void strcmp_diff_length_1() {
746   char *x = "123";
747   char *y = "23456";
748   clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
749 }
750 
strcmp_diff_length_2()751 void strcmp_diff_length_2() {
752   char *x = "12345";
753   char *y = "123";
754   clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}}
755 }
756 
strcmp_diff_length_3()757 void strcmp_diff_length_3() {
758   char *x = "123";
759   char *y = "12345";
760   clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
761 }
762 
strcmp_embedded_null()763 void strcmp_embedded_null () {
764 	clang_analyzer_eval(strcmp("\0z", "\0y") == 0); // expected-warning{{TRUE}}
765 }
766 
strcmp_unknown_arg(char * unknown)767 void strcmp_unknown_arg (char *unknown) {
768 	clang_analyzer_eval(strcmp(unknown, unknown) == 0); // expected-warning{{TRUE}}
769 }
770 
771 union argument {
772    char *f;
773 };
774 
function_pointer_cast_helper(char ** a)775 void function_pointer_cast_helper(char **a) {
776   strcmp("Hi", *a); // PR24951 crash
777 }
778 
strcmp_union_function_pointer_cast(union argument a)779 void strcmp_union_function_pointer_cast(union argument a) {
780   void (*fPtr)(union argument *) = (void (*)(union argument *))function_pointer_cast_helper;
781 
782   fPtr(&a);
783 }
784 
785 //===----------------------------------------------------------------------===
786 // strncmp()
787 //===----------------------------------------------------------------------===
788 
789 #define strncmp BUILTIN(strncmp)
790 int strncmp(const char *s1, const char *s2, size_t n);
791 
strncmp_check_modelling()792 void strncmp_check_modelling() {
793   char *x = "aa";
794   char *y = "a";
795   clang_analyzer_eval(strncmp(x, y, 2) > 0); // expected-warning{{TRUE}}
796   clang_analyzer_eval(strncmp(x, y, 2) <= 0); // expected-warning{{FALSE}}
797   clang_analyzer_eval(strncmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}}
798 
799   clang_analyzer_eval(strncmp(y, x, 2) < 0); // expected-warning{{TRUE}}
800   clang_analyzer_eval(strncmp(y, x, 2) >= 0); // expected-warning{{FALSE}}
801   clang_analyzer_eval(strncmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}}
802 }
803 
strncmp_constant0()804 void strncmp_constant0() {
805   clang_analyzer_eval(strncmp("123", "123", 3) == 0); // expected-warning{{TRUE}}
806 }
807 
strncmp_constant_and_var_0()808 void strncmp_constant_and_var_0() {
809   char *x = "123";
810   clang_analyzer_eval(strncmp(x, "123", 3) == 0); // expected-warning{{TRUE}}
811 }
812 
strncmp_constant_and_var_1()813 void strncmp_constant_and_var_1() {
814   char *x = "123";
815   clang_analyzer_eval(strncmp("123", x, 3) == 0); // expected-warning{{TRUE}}
816 }
817 
strncmp_0()818 void strncmp_0() {
819   char *x = "123";
820   char *y = "123";
821   clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
822 }
823 
strncmp_1()824 void strncmp_1() {
825   char *x = "234";
826   char *y = "123";
827   clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}}
828 }
829 
strncmp_2()830 void strncmp_2() {
831   char *x = "123";
832   char *y = "234";
833   clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}}
834 }
835 
strncmp_null_0()836 void strncmp_null_0() {
837   char *x = NULL;
838   char *y = "123";
839   strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
840 }
841 
strncmp_null_1()842 void strncmp_null_1() {
843   char *x = "123";
844   char *y = NULL;
845   strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
846 }
847 
strncmp_diff_length_0()848 void strncmp_diff_length_0() {
849   char *x = "12345";
850   char *y = "234";
851   clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}}
852 }
853 
strncmp_diff_length_1()854 void strncmp_diff_length_1() {
855   char *x = "123";
856   char *y = "23456";
857   clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}}
858 }
859 
strncmp_diff_length_2()860 void strncmp_diff_length_2() {
861   char *x = "12345";
862   char *y = "123";
863   clang_analyzer_eval(strncmp(x, y, 5) > 0); // expected-warning{{TRUE}}
864 }
865 
strncmp_diff_length_3()866 void strncmp_diff_length_3() {
867   char *x = "123";
868   char *y = "12345";
869   clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}}
870 }
871 
strncmp_diff_length_4()872 void strncmp_diff_length_4() {
873   char *x = "123";
874   char *y = "12345";
875   clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
876 }
877 
strncmp_diff_length_5()878 void strncmp_diff_length_5() {
879   char *x = "012";
880   char *y = "12345";
881   clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}}
882 }
883 
strncmp_diff_length_6()884 void strncmp_diff_length_6() {
885   char *x = "234";
886   char *y = "12345";
887   clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}}
888 }
889 
strncmp_embedded_null()890 void strncmp_embedded_null () {
891 	clang_analyzer_eval(strncmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
892 }
893 
894 //===----------------------------------------------------------------------===
895 // strcasecmp()
896 //===----------------------------------------------------------------------===
897 
898 #define strcasecmp BUILTIN(strcasecmp)
899 int strcasecmp(const char *s1, const char *s2);
900 
strcasecmp_check_modelling()901 void strcasecmp_check_modelling() {
902   char *x = "aa";
903   char *y = "a";
904   clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}}
905   clang_analyzer_eval(strcasecmp(x, y) <= 0); // expected-warning{{FALSE}}
906   clang_analyzer_eval(strcasecmp(x, y) > 1); // expected-warning{{UNKNOWN}}
907 
908   clang_analyzer_eval(strcasecmp(y, x) < 0); // expected-warning{{TRUE}}
909   clang_analyzer_eval(strcasecmp(y, x) >= 0); // expected-warning{{FALSE}}
910   clang_analyzer_eval(strcasecmp(y, x) < -1); // expected-warning{{UNKNOWN}}
911 }
912 
strcasecmp_constant0()913 void strcasecmp_constant0() {
914   clang_analyzer_eval(strcasecmp("abc", "Abc") == 0); // expected-warning{{TRUE}}
915 }
916 
strcasecmp_constant_and_var_0()917 void strcasecmp_constant_and_var_0() {
918   char *x = "abc";
919   clang_analyzer_eval(strcasecmp(x, "Abc") == 0); // expected-warning{{TRUE}}
920 }
921 
strcasecmp_constant_and_var_1()922 void strcasecmp_constant_and_var_1() {
923   char *x = "abc";
924   clang_analyzer_eval(strcasecmp("Abc", x) == 0); // expected-warning{{TRUE}}
925 }
926 
strcasecmp_0()927 void strcasecmp_0() {
928   char *x = "abc";
929   char *y = "Abc";
930   clang_analyzer_eval(strcasecmp(x, y) == 0); // expected-warning{{TRUE}}
931 }
932 
strcasecmp_1()933 void strcasecmp_1() {
934   char *x = "Bcd";
935   char *y = "abc";
936   clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}}
937 }
938 
strcasecmp_2()939 void strcasecmp_2() {
940   char *x = "abc";
941   char *y = "Bcd";
942   clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
943 }
944 
strcasecmp_null_0()945 void strcasecmp_null_0() {
946   char *x = NULL;
947   char *y = "123";
948   strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
949 }
950 
strcasecmp_null_1()951 void strcasecmp_null_1() {
952   char *x = "123";
953   char *y = NULL;
954   strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
955 }
956 
strcasecmp_diff_length_0()957 void strcasecmp_diff_length_0() {
958   char *x = "abcde";
959   char *y = "aBd";
960   clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
961 }
962 
strcasecmp_diff_length_1()963 void strcasecmp_diff_length_1() {
964   char *x = "abc";
965   char *y = "aBdef";
966   clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
967 }
968 
strcasecmp_diff_length_2()969 void strcasecmp_diff_length_2() {
970   char *x = "aBcDe";
971   char *y = "abc";
972   clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}}
973 }
974 
strcasecmp_diff_length_3()975 void strcasecmp_diff_length_3() {
976   char *x = "aBc";
977   char *y = "abcde";
978   clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
979 }
980 
strcasecmp_embedded_null()981 void strcasecmp_embedded_null () {
982 	clang_analyzer_eval(strcasecmp("ab\0zz", "ab\0yy") == 0); // expected-warning{{TRUE}}
983 }
984 
985 //===----------------------------------------------------------------------===
986 // strncasecmp()
987 //===----------------------------------------------------------------------===
988 
989 #define strncasecmp BUILTIN(strncasecmp)
990 int strncasecmp(const char *s1, const char *s2, size_t n);
991 
strncasecmp_check_modelling()992 void strncasecmp_check_modelling() {
993   char *x = "aa";
994   char *y = "a";
995   clang_analyzer_eval(strncasecmp(x, y, 2) > 0); // expected-warning{{TRUE}}
996   clang_analyzer_eval(strncasecmp(x, y, 2) <= 0); // expected-warning{{FALSE}}
997   clang_analyzer_eval(strncasecmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}}
998 
999   clang_analyzer_eval(strncasecmp(y, x, 2) < 0); // expected-warning{{TRUE}}
1000   clang_analyzer_eval(strncasecmp(y, x, 2) >= 0); // expected-warning{{FALSE}}
1001   clang_analyzer_eval(strncasecmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}}
1002 }
1003 
strncasecmp_constant0()1004 void strncasecmp_constant0() {
1005   clang_analyzer_eval(strncasecmp("abc", "Abc", 3) == 0); // expected-warning{{TRUE}}
1006 }
1007 
strncasecmp_constant_and_var_0()1008 void strncasecmp_constant_and_var_0() {
1009   char *x = "abc";
1010   clang_analyzer_eval(strncasecmp(x, "Abc", 3) == 0); // expected-warning{{TRUE}}
1011 }
1012 
strncasecmp_constant_and_var_1()1013 void strncasecmp_constant_and_var_1() {
1014   char *x = "abc";
1015   clang_analyzer_eval(strncasecmp("Abc", x, 3) == 0); // expected-warning{{TRUE}}
1016 }
1017 
strncasecmp_0()1018 void strncasecmp_0() {
1019   char *x = "abc";
1020   char *y = "Abc";
1021   clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
1022 }
1023 
strncasecmp_1()1024 void strncasecmp_1() {
1025   char *x = "Bcd";
1026   char *y = "abc";
1027   clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}}
1028 }
1029 
strncasecmp_2()1030 void strncasecmp_2() {
1031   char *x = "abc";
1032   char *y = "Bcd";
1033   clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}}
1034 }
1035 
strncasecmp_null_0()1036 void strncasecmp_null_0() {
1037   char *x = NULL;
1038   char *y = "123";
1039   strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
1040 }
1041 
strncasecmp_null_1()1042 void strncasecmp_null_1() {
1043   char *x = "123";
1044   char *y = NULL;
1045   strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
1046 }
1047 
strncasecmp_diff_length_0()1048 void strncasecmp_diff_length_0() {
1049   char *x = "abcde";
1050   char *y = "aBd";
1051   clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}}
1052 }
1053 
strncasecmp_diff_length_1()1054 void strncasecmp_diff_length_1() {
1055   char *x = "abc";
1056   char *y = "aBdef";
1057   clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}}
1058 }
1059 
strncasecmp_diff_length_2()1060 void strncasecmp_diff_length_2() {
1061   char *x = "aBcDe";
1062   char *y = "abc";
1063   clang_analyzer_eval(strncasecmp(x, y, 5) > 0); // expected-warning{{TRUE}}
1064 }
1065 
strncasecmp_diff_length_3()1066 void strncasecmp_diff_length_3() {
1067   char *x = "aBc";
1068   char *y = "abcde";
1069   clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}}
1070 }
1071 
strncasecmp_diff_length_4()1072 void strncasecmp_diff_length_4() {
1073   char *x = "abcde";
1074   char *y = "aBc";
1075   clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
1076 }
1077 
strncasecmp_diff_length_5()1078 void strncasecmp_diff_length_5() {
1079   char *x = "abcde";
1080   char *y = "aBd";
1081   clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}}
1082 }
1083 
strncasecmp_diff_length_6()1084 void strncasecmp_diff_length_6() {
1085   char *x = "aBDe";
1086   char *y = "abc";
1087   clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}}
1088 }
1089 
strncasecmp_embedded_null()1090 void strncasecmp_embedded_null () {
1091 	clang_analyzer_eval(strncasecmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
1092 }
1093 
1094 //===----------------------------------------------------------------------===
1095 // strsep()
1096 //===----------------------------------------------------------------------===
1097 
1098 char *strsep(char **stringp, const char *delim);
1099 
strsep_null_delim(char * s)1100 void strsep_null_delim(char *s) {
1101   strsep(&s, NULL); // expected-warning{{Null pointer argument in call to strsep()}}
1102 }
1103 
strsep_null_search()1104 void strsep_null_search() {
1105   strsep(NULL, ""); // expected-warning{{Null pointer argument in call to strsep()}}
1106 }
1107 
strsep_return_original_pointer(char * s)1108 void strsep_return_original_pointer(char *s) {
1109   char *original = s;
1110   char *result = strsep(&s, ""); // no-warning
1111   clang_analyzer_eval(original == result); // expected-warning{{TRUE}}
1112 }
1113 
strsep_null_string()1114 void strsep_null_string() {
1115   char *s = NULL;
1116   char *result = strsep(&s, ""); // no-warning
1117   clang_analyzer_eval(result == NULL); // expected-warning{{TRUE}}
1118 }
1119 
strsep_changes_input_pointer(char * s)1120 void strsep_changes_input_pointer(char *s) {
1121   char *original = s;
1122   strsep(&s, ""); // no-warning
1123   clang_analyzer_eval(s == original); // expected-warning{{UNKNOWN}}
1124   clang_analyzer_eval(s == NULL); // expected-warning{{UNKNOWN}}
1125 
1126   // Check that the value is symbolic.
1127   if (s == NULL) {
1128     clang_analyzer_eval(s == NULL); // expected-warning{{TRUE}}
1129   }
1130 }
1131 
strsep_changes_input_string()1132 void strsep_changes_input_string() {
1133   char str[] = "abc";
1134 
1135   clang_analyzer_eval(str[1] == 'b'); // expected-warning{{TRUE}}
1136 
1137   char *s = str;
1138   strsep(&s, "b"); // no-warning
1139 
1140   // The real strsep will change the first delimiter it finds into a NUL
1141   // character. For now, we just model the invalidation.
1142   clang_analyzer_eval(str[1] == 'b'); // expected-warning{{UNKNOWN}}
1143 }
1144 
1145 //===----------------------------------------------------------------------===
1146 // FIXMEs
1147 //===----------------------------------------------------------------------===
1148 
1149 // The analyzer_eval call below should evaluate to true. We are being too
1150 // aggressive in marking the (length of) src symbol dead. The length of dst
1151 // depends on src. This could be explicitely specified in the checker or the
1152 // logic for handling MetadataSymbol in SymbolManager needs to change.
strcat_symbolic_src_length(char * src)1153 void strcat_symbolic_src_length(char *src) {
1154 	char dst[8] = "1234";
1155 	strcat(dst, src);
1156   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{UNKNOWN}}
1157 }
1158 
1159 // The analyzer_eval call below should evaluate to true. Most likely the same
1160 // issue as the test above.
strncpy_exactly_matching_buffer2(char * y)1161 void strncpy_exactly_matching_buffer2(char *y) {
1162 	if (strlen(y) >= 4)
1163 		return;
1164 
1165 	char x[4];
1166 	strncpy(x, y, 4); // no-warning
1167 
1168 	// This time, we know that y fits in x anyway.
1169   clang_analyzer_eval(strlen(x) <= 3); // expected-warning{{UNKNOWN}}
1170 }
1171