xref: /llvm-project/clang/test/Analysis/wstring.c (revision 501faaa0d65e9814566ef65e58d834c155553b8a)
1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN:   -analyzer-checker=core \
3 // RUN:   -analyzer-checker=unix.cstring \
4 // RUN:   -analyzer-checker=alpha.unix.cstring \
5 // RUN:   -analyzer-disable-checker=alpha.unix.cstring.UninitializedRead \
6 // RUN:   -analyzer-checker=debug.ExprInspection \
7 // RUN:   -analyzer-config eagerly-assume=false
8 //
9 // RUN: %clang_analyze_cc1 -verify %s -DUSE_BUILTINS \
10 // RUN:   -analyzer-checker=core \
11 // RUN:   -analyzer-checker=unix.cstring \
12 // RUN:   -analyzer-checker=alpha.unix.cstring \
13 // RUN:   -analyzer-disable-checker=alpha.unix.cstring.UninitializedRead \
14 // RUN:   -analyzer-checker=debug.ExprInspection \
15 // RUN:   -analyzer-config eagerly-assume=false
16 
17 //===----------------------------------------------------------------------===
18 // Declarations
19 //===----------------------------------------------------------------------===
20 
21 // Some functions are implemented as builtins. These should be #defined as
22 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
23 
24 #ifdef USE_BUILTINS
25 # define BUILTIN(f) __builtin_ ## f
26 #else /* USE_BUILTINS */
27 # define BUILTIN(f) f
28 #endif /* USE_BUILTINS */
29 
30 typedef __SIZE_TYPE__ size_t;
31 typedef __WCHAR_TYPE__ wchar_t;
32 
33 void clang_analyzer_eval(int);
34 
35 //===----------------------------------------------------------------------===
36 // wmemcpy()
37 //===----------------------------------------------------------------------===
38 
39 #define wmemcpy BUILTIN(wmemcpy)
40 wchar_t *wmemcpy(wchar_t *restrict s1, const wchar_t *restrict s2, size_t n);
41 
wmemcpy0(void)42 void wmemcpy0 (void) {
43   wchar_t src[] = {1, 2, 3, 4};
44   wchar_t dst[4] = {0};
45 
46   wmemcpy(dst, src, 4); // no-warning
47 
48   clang_analyzer_eval(wmemcpy(dst, src, 4) == dst); // expected-warning{{TRUE}}
49 
50   // If we actually model the copy, we can make this known.
51   // The important thing for now is that the old value has been invalidated.
52   clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
53 }
54 
wmemcpy1(void)55 void wmemcpy1 (void) {
56   wchar_t src[] = {1, 2, 3, 4};
57   wchar_t dst[10];
58 
59   wmemcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}}
60 }
61 
wmemcpy2(void)62 void wmemcpy2 (void) {
63   wchar_t src[] = {1, 2, 3, 4};
64   wchar_t dst[1];
65 
66   wmemcpy(dst, src, 4); // expected-warning {{Memory copy function overflows the destination buffer}}
67 }
68 
wmemcpy3(void)69 void wmemcpy3 (void) {
70   wchar_t src[] = {1, 2, 3, 4};
71   wchar_t dst[3];
72 
73   wmemcpy(dst+1, src+2, 2); // no-warning
74 }
75 
wmemcpy4(void)76 void wmemcpy4 (void) {
77   wchar_t src[] = {1, 2, 3, 4};
78   wchar_t dst[10];
79 
80   wmemcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
81 }
82 
wmemcpy5(void)83 void wmemcpy5(void) {
84   wchar_t src[] = {1, 2, 3, 4};
85   wchar_t dst[3];
86 
87   wmemcpy(dst + 2, src + 2, 2); // expected-warning{{Memory copy function overflows the destination buffer}}
88 }
89 
wmemcpy6(void)90 void wmemcpy6(void) {
91   wchar_t a[4] = {0};
92   wmemcpy(a, a, 2); // expected-warning{{overlapping}}
93 }
94 
wmemcpy7(void)95 void wmemcpy7(void) {
96   wchar_t a[4] = {0};
97   wmemcpy(a+2, a+1, 2); // expected-warning{{overlapping}}
98 }
99 
wmemcpy8(void)100 void wmemcpy8(void) {
101   wchar_t a[4] = {0};
102   wmemcpy(a+1, a+2, 2); // expected-warning{{overlapping}}
103 }
104 
wmemcpy9(void)105 void wmemcpy9(void) {
106   wchar_t a[4] = {0};
107   wmemcpy(a+2, a+1, 1); // no-warning
108   wmemcpy(a+1, a+2, 1); // no-warning
109 }
110 
wmemcpy10(void)111 void wmemcpy10(void) {
112   wchar_t a[4] = {0};
113   wmemcpy(0, a, 1); // expected-warning{{Null pointer passed as 1st argument to memory copy function}}
114 }
115 
wmemcpy11(void)116 void wmemcpy11(void) {
117   wchar_t a[4] = {0};
118   wmemcpy(a, 0, 1); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
119 }
120 
wmemcpy12(void)121 void wmemcpy12(void) {
122   wchar_t a[4] = {0};
123   wmemcpy(0, a, 0); // no-warning
124 }
125 
wmemcpy13(void)126 void wmemcpy13(void) {
127   wchar_t a[4] = {0};
128   wmemcpy(a, 0, 0); // no-warning
129 }
130 
wmemcpy_unknown_size(size_t n)131 void wmemcpy_unknown_size (size_t n) {
132   wchar_t a[4], b[4] = {1};
133   clang_analyzer_eval(wmemcpy(a, b, n) == a); // expected-warning{{TRUE}}
134 }
135 
wmemcpy_unknown_size_warn(size_t n)136 void wmemcpy_unknown_size_warn (size_t n) {
137   wchar_t a[4];
138   void *result = wmemcpy(a, 0, n); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
139   clang_analyzer_eval(result == a); // no-warning (above is fatal)
140 }
141 
142 //===----------------------------------------------------------------------===
143 // wmempcpy()
144 //===----------------------------------------------------------------------===
145 
146 wchar_t *wmempcpy(wchar_t *restrict s1, const wchar_t *restrict s2, size_t n);
147 
wmempcpy0(void)148 void wmempcpy0 (void) {
149   wchar_t src[] = {1, 2, 3, 4};
150   wchar_t dst[5] = {0};
151 
152   wmempcpy(dst, src, 4); // no-warning
153 
154   clang_analyzer_eval(wmempcpy(dst, src, 4) == &dst[4]); // expected-warning{{TRUE}}
155 
156   // If we actually model the copy, we can make this known.
157   // The important thing for now is that the old value has been invalidated.
158   clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
159 }
160 
wmempcpy1(void)161 void wmempcpy1 (void) {
162   wchar_t src[] = {1, 2, 3, 4};
163   wchar_t dst[10];
164 
165   wmempcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}}
166 }
167 
wmempcpy2(void)168 void wmempcpy2 (void) {
169   wchar_t src[] = {1, 2, 3, 4};
170   wchar_t dst[1];
171 
172   wmempcpy(dst, src, 4); // expected-warning{{Memory copy function overflows the destination buffer}}
173 }
174 
wmempcpy3(void)175 void wmempcpy3 (void) {
176   wchar_t src[] = {1, 2, 3, 4};
177   wchar_t dst[3];
178 
179   wmempcpy(dst+1, src+2, 2); // no-warning
180 }
181 
wmempcpy4(void)182 void wmempcpy4 (void) {
183   wchar_t src[] = {1, 2, 3, 4};
184   wchar_t dst[10];
185 
186   wmempcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
187 }
188 
wmempcpy5(void)189 void wmempcpy5(void) {
190   wchar_t src[] = {1, 2, 3, 4};
191   wchar_t dst[3];
192 
193   wmempcpy(dst + 2, src + 2, 2); // expected-warning{{Memory copy function overflows the destination buffer}}
194 }
195 
wmempcpy6(void)196 void wmempcpy6(void) {
197   wchar_t a[4] = {0};
198   wmempcpy(a, a, 2); // expected-warning{{overlapping}}
199 }
200 
wmempcpy7(void)201 void wmempcpy7(void) {
202   wchar_t a[4] = {0};
203   wmempcpy(a+2, a+1, 2); // expected-warning{{overlapping}}
204 }
205 
wmempcpy8(void)206 void wmempcpy8(void) {
207   wchar_t a[4] = {0};
208   wmempcpy(a+1, a+2, 2); // expected-warning{{overlapping}}
209 }
210 
wmempcpy9(void)211 void wmempcpy9(void) {
212   wchar_t a[4] = {0};
213   wmempcpy(a+2, a+1, 1); // no-warning
214   wmempcpy(a+1, a+2, 1); // no-warning
215 }
216 
wmempcpy10(void)217 void wmempcpy10(void) {
218   wchar_t a[4] = {0};
219   wmempcpy(0, a, 1); // expected-warning{{Null pointer passed as 1st argument to memory copy function}}
220 }
221 
wmempcpy11(void)222 void wmempcpy11(void) {
223   wchar_t a[4] = {0};
224   wmempcpy(a, 0, 1); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
225 }
226 
wmempcpy12(void)227 void wmempcpy12(void) {
228   wchar_t a[4] = {0};
229   wmempcpy(0, a, 0); // no-warning
230 }
231 
wmempcpy13(void)232 void wmempcpy13(void) {
233   wchar_t a[4] = {0};
234   wmempcpy(a, 0, 0); // no-warning
235 }
236 
wmempcpy14(void)237 void wmempcpy14(void) {
238   wchar_t src[] = {1, 2, 3, 4};
239   wchar_t dst[5] = {0};
240   wchar_t *p;
241 
242   p = wmempcpy(dst, src, 4);
243 
244   clang_analyzer_eval(p == &dst[4]); // expected-warning{{TRUE}}
245 }
246 
247 struct st {
248   wchar_t i;
249   wchar_t j;
250 };
251 
wmempcpy15(void)252 void wmempcpy15(void) {
253   struct st s1 = {0};
254   struct st s2;
255   struct st *p1;
256   struct st *p2;
257 
258   p1 = (&s2) + 1;
259   p2 = (struct st *)wmempcpy((wchar_t *)&s2, (wchar_t *)&s1, 2);
260 
261   clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}}
262 }
263 
wmempcpy16(void)264 void wmempcpy16(void) {
265   struct st s1[10] = {{0}};
266   struct st s2[10];
267   struct st *p1;
268   struct st *p2;
269 
270   p1 = (&s2[0]) + 5;
271   p2 = (struct st *)wmempcpy((wchar_t *)&s2[0], (wchar_t *)&s1[0], 5 * 2);
272 
273   clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}}
274 }
275 
wmempcpy_unknown_size_warn(size_t n)276 void wmempcpy_unknown_size_warn (size_t n) {
277   wchar_t a[4];
278   void *result = wmempcpy(a, 0, n); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
279   clang_analyzer_eval(result == a); // no-warning (above is fatal)
280 }
281 
wmempcpy_unknownable_size(wchar_t * src,float n)282 void wmempcpy_unknownable_size (wchar_t *src, float n) {
283   wchar_t a[4];
284   // This used to crash because we don't model floats.
285   wmempcpy(a, src, (size_t)n);
286 }
287 
288 //===----------------------------------------------------------------------===
289 // wmemmove()
290 //===----------------------------------------------------------------------===
291 
292 #define wmemmove BUILTIN(wmemmove)
293 wchar_t *wmemmove(wchar_t *s1, const wchar_t *s2, size_t n);
294 
wmemmove0(void)295 void wmemmove0 (void) {
296   wchar_t src[] = {1, 2, 3, 4};
297   wchar_t dst[4] = {0};
298 
299   wmemmove(dst, src, 4); // no-warning
300 
301   clang_analyzer_eval(wmemmove(dst, src, 4) == dst); // expected-warning{{TRUE}}
302 
303   clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
304 }
305 
wmemmove1(void)306 void wmemmove1 (void) {
307   wchar_t src[] = {1, 2, 3, 4};
308   wchar_t dst[10];
309 
310   wmemmove(dst, src, 5); // expected-warning{{out-of-bound}}
311 }
312 
wmemmove2(void)313 void wmemmove2 (void) {
314   wchar_t src[] = {1, 2, 3, 4};
315   wchar_t dst[1];
316 
317   wmemmove(dst, src, 4); // expected-warning{{Memory copy function overflows the destination buffer}}
318 }
319 
320 //===----------------------------------------------------------------------===
321 // wmemcmp()
322 //===----------------------------------------------------------------------===
323 
324 #define wmemcmp BUILTIN(wmemcmp)
325 int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n);
326 
wmemcmp0(void)327 void wmemcmp0 (void) {
328   wchar_t a[] = {1, 2, 3, 4};
329   wchar_t b[4] = { 0 };
330 
331   wmemcmp(a, b, 4); // no-warning
332 }
333 
wmemcmp1(void)334 void wmemcmp1 (void) {
335   wchar_t a[] = {1, 2, 3, 4};
336   wchar_t b[10] = { 0 };
337 
338   wmemcmp(a, b, 5); // expected-warning{{out-of-bound}}
339 }
340 
wmemcmp2(void)341 void wmemcmp2 (void) {
342   wchar_t a[] = {1, 2, 3, 4};
343   wchar_t b[1] = { 0 };
344 
345   wmemcmp(a, b, 4); // expected-warning{{out-of-bound}}
346 }
347 
wmemcmp3(void)348 void wmemcmp3 (void) {
349   wchar_t a[] = {1, 2, 3, 4};
350 
351   clang_analyzer_eval(wmemcmp(a, a, 4) == 0); // expected-warning{{TRUE}}
352 }
353 
wmemcmp4(wchar_t * input)354 void wmemcmp4 (wchar_t *input) {
355   wchar_t a[] = {1, 2, 3, 4};
356 
357   clang_analyzer_eval(wmemcmp(a, input, 4) == 0); // expected-warning{{UNKNOWN}}
358 }
359 
wmemcmp5(wchar_t * input)360 void wmemcmp5 (wchar_t *input) {
361   wchar_t a[] = {1, 2, 3, 4};
362 
363   clang_analyzer_eval(wmemcmp(a, 0, 0) == 0); // expected-warning{{TRUE}}
364   clang_analyzer_eval(wmemcmp(0, a, 0) == 0); // expected-warning{{TRUE}}
365   clang_analyzer_eval(wmemcmp(a, input, 0) == 0); // expected-warning{{TRUE}}
366 }
367 
wmemcmp6(wchar_t * a,wchar_t * b,size_t n)368 void wmemcmp6 (wchar_t *a, wchar_t *b, size_t n) {
369   int result = wmemcmp(a, b, n);
370   if (result != 0)
371     clang_analyzer_eval(n != 0); // expected-warning{{TRUE}}
372   // else
373   //   analyzer_assert_unknown(n == 0);
374 
375   // We can't do the above comparison because n has already been constrained.
376   // On one path n == 0, on the other n != 0.
377 }
378 
wmemcmp7(wchar_t * a,size_t x,size_t y,size_t n)379 int wmemcmp7 (wchar_t *a, size_t x, size_t y, size_t n) {
380   // We used to crash when either of the arguments was unknown.
381   return wmemcmp(a, &a[x*y], n) +
382          wmemcmp(&a[x*y], a, n);
383 }
384 
wmemcmp8(wchar_t * a,size_t n)385 int wmemcmp8(wchar_t *a, size_t n) {
386   wchar_t *b = 0;
387   // Do not warn about the first argument!
388   return wmemcmp(a, b, n); // expected-warning{{Null pointer passed as 2nd argument to memory comparison function}}
389 }
390 
391 //===----------------------------------------------------------------------===
392 // wcslen()
393 //===----------------------------------------------------------------------===
394 
395 #define wcslen BUILTIN(wcslen)
396 size_t wcslen(const wchar_t *s);
397 
wcslen_constant0(void)398 void wcslen_constant0(void) {
399   clang_analyzer_eval(wcslen(L"123") == 3); // expected-warning{{TRUE}}
400 }
401 
wcslen_constant1(void)402 void wcslen_constant1(void) {
403   const wchar_t *a = L"123";
404   clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{TRUE}}
405 }
406 
wcslen_constant2(wchar_t x)407 void wcslen_constant2(wchar_t x) {
408   wchar_t a[] = L"123";
409   clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{TRUE}}
410 
411   a[0] = x;
412   clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{UNKNOWN}}
413 }
414 
wcslen_null(void)415 size_t wcslen_null(void) {
416   return wcslen(0); // expected-warning{{Null pointer passed as 1st argument to string length function}}
417 }
418 
wcslen_fn(void)419 size_t wcslen_fn(void) {
420   return wcslen((wchar_t*)&wcslen_fn); // expected-warning{{Argument to string length function is the address of the function 'wcslen_fn', which is not a null-terminated string}}
421 }
422 
wcslen_nonloc(void)423 size_t wcslen_nonloc(void) {
424 label:
425   return wcslen((wchar_t*)&&label); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
426 }
427 
wcslen_subregion(void)428 void wcslen_subregion(void) {
429   struct two_strings { wchar_t a[2], b[2]; };
430   extern void use_two_strings(struct two_strings *);
431 
432   struct two_strings z;
433   use_two_strings(&z);
434 
435   size_t a = wcslen(z.a);
436   z.b[0] = 5;
437   size_t b = wcslen(z.a);
438   if (a == 0)
439     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
440 
441   use_two_strings(&z);
442 
443   size_t c = wcslen(z.a);
444   if (a == 0)
445     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
446 }
447 
448 extern void use_string(wchar_t *);
wcslen_argument(wchar_t * x)449 void wcslen_argument(wchar_t *x) {
450   size_t a = wcslen(x);
451   size_t b = wcslen(x);
452   if (a == 0)
453     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
454 
455   use_string(x);
456 
457   size_t c = wcslen(x);
458   if (a == 0)
459     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
460 }
461 
462 extern wchar_t global_str[];
wcslen_global(void)463 void wcslen_global(void) {
464   size_t a = wcslen(global_str);
465   size_t b = wcslen(global_str);
466   if (a == 0) {
467     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
468     // Make sure clang_analyzer_eval does not invalidate globals.
469     clang_analyzer_eval(wcslen(global_str) == 0); // expected-warning{{TRUE}}
470   }
471 
472   // Call a function with unknown effects, which should invalidate globals.
473   use_string(0);
474 
475   size_t c = wcslen(global_str);
476   if (a == 0)
477     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
478 }
479 
wcslen_indirect(wchar_t * x)480 void wcslen_indirect(wchar_t *x) {
481   size_t a = wcslen(x);
482   wchar_t *p = x;
483   wchar_t **p2 = &p;
484   size_t b = wcslen(x);
485   if (a == 0)
486     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
487 
488   extern void use_string_ptr(wchar_t*const*);
489   use_string_ptr(p2);
490 
491   size_t c = wcslen(x);
492   if (a == 0)
493     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
494 }
495 
wcslen_indirect2(wchar_t * x)496 void wcslen_indirect2(wchar_t *x) {
497   size_t a = wcslen(x);
498   wchar_t *p = x;
499   wchar_t **p2 = &p;
500   extern void use_string_ptr2(wchar_t**);
501   use_string_ptr2(p2);
502 
503   size_t c = wcslen(x);
504   if (a == 0)
505     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
506 }
507 
wcslen_liveness(const wchar_t * x)508 void wcslen_liveness(const wchar_t *x) {
509   if (wcslen(x) < 5)
510     return;
511   clang_analyzer_eval(wcslen(x) < 5); // expected-warning{{FALSE}}
512 }
513 
514 
wcslenWrapper(const wchar_t * str)515 size_t wcslenWrapper(const wchar_t *str) {
516   return wcslen(str);
517 }
518 
519 extern void invalidate(wchar_t *s);
520 
testwcslenCallee(void)521 void testwcslenCallee(void) {
522   wchar_t str[42];
523   invalidate(str);
524   size_t lenBefore = wcslenWrapper(str);
525   invalidate(str);
526   size_t lenAfter = wcslenWrapper(str);
527   clang_analyzer_eval(lenBefore == lenAfter); // expected-warning{{UNKNOWN}}
528 }
529 
530 //===----------------------------------------------------------------------===
531 // wcsnlen()
532 //===----------------------------------------------------------------------===
533 
534 size_t wcsnlen(const wchar_t *s, size_t maxlen);
535 
wcsnlen_constant0(void)536 void wcsnlen_constant0(void) {
537   clang_analyzer_eval(wcsnlen(L"123", 10) == 3); // expected-warning{{TRUE}}
538 }
539 
wcsnlen_constant1(void)540 void wcsnlen_constant1(void) {
541   const wchar_t *a = L"123";
542   clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{TRUE}}
543 }
544 
wcsnlen_constant2(char x)545 void wcsnlen_constant2(char x) {
546   wchar_t a[] = L"123";
547   clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{TRUE}}
548   a[0] = x;
549   clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{UNKNOWN}}
550 }
551 
wcsnlen_constant4(void)552 void wcsnlen_constant4(void) {
553   clang_analyzer_eval(wcsnlen(L"123456", 3) == 3); // expected-warning{{TRUE}}
554 }
555 
wcsnlen_constant5(void)556 void wcsnlen_constant5(void) {
557   const wchar_t *a = L"123456";
558   clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{TRUE}}
559 }
560 
wcsnlen_constant6(char x)561 void wcsnlen_constant6(char x) {
562   wchar_t a[] = L"123456";
563   clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{TRUE}}
564   a[0] = x;
565   clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{UNKNOWN}}
566 }
567 
wcsnlen_null(void)568 size_t wcsnlen_null(void) {
569   return wcsnlen(0, 3); // expected-warning{{Null pointer passed as 1st argument to string length function}}
570 }
571 
wcsnlen_fn(void)572 size_t wcsnlen_fn(void) {
573   return wcsnlen((wchar_t*)&wcsnlen_fn, 3); // expected-warning{{Argument to string length function is the address of the function 'wcsnlen_fn', which is not a null-terminated string}}
574 }
575 
wcsnlen_nonloc(void)576 size_t wcsnlen_nonloc(void) {
577 label:
578   return wcsnlen((wchar_t*)&&label, 3); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
579 }
580 
wcsnlen_zero(void)581 void wcsnlen_zero(void) {
582   clang_analyzer_eval(wcsnlen(L"abc", 0) == 0); // expected-warning{{TRUE}}
583   clang_analyzer_eval(wcsnlen(0, 0) == 0); // expected-warning{{TRUE}}
584 }
585 
wcsnlen_compound_literal(void)586 size_t wcsnlen_compound_literal(void) {
587   // This used to crash because we don't model the string lengths of
588   // compound literals.
589   return wcsnlen((wchar_t[]) { 'a', 'b', 0 }, 1);
590 }
591 
wcsnlen_unknown_limit(float f)592 size_t wcsnlen_unknown_limit(float f) {
593   // This used to crash because we don't model the integer values of floats.
594   return wcsnlen(L"abc", (int)f);
595 }
596 
wcsnlen_is_not_wcslen(wchar_t * x)597 void wcsnlen_is_not_wcslen(wchar_t *x) {
598   clang_analyzer_eval(wcsnlen(x, 10) == wcslen(x)); // expected-warning{{UNKNOWN}}
599 }
600 
wcsnlen_at_limit(wchar_t * x)601 void wcsnlen_at_limit(wchar_t *x) {
602   size_t len = wcsnlen(x, 10);
603   clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}}
604   clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}}
605   clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}}
606 }
607 
wcsnlen_at_actual(size_t limit)608 void wcsnlen_at_actual(size_t limit) {
609   size_t len = wcsnlen(L"abc", limit);
610   clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}}
611   // This is due to eager assertion in wcsnlen.
612   if (limit == 0) {
613     clang_analyzer_eval(len == 0); // expected-warning{{TRUE}}
614   } else {
615     clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}}
616     clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}}
617   }
618 }
619 
620 //===----------------------------------------------------------------------===
621 // other tests
622 //===----------------------------------------------------------------------===
623 
624 static const wchar_t w_str[] = L"Hello world";
625 
wmemcpy_sizeof(void)626 void wmemcpy_sizeof(void) {
627   wchar_t a[32];
628   wmemcpy(a, w_str, sizeof(w_str) / sizeof(w_str[0]));
629   wmemcpy(a, w_str, (sizeof(w_str) / sizeof(w_str[0])) + 1); // expected-warning {{Memory copy function accesses out-of-bound array element}}
630 }
631 
wmemcpy_wcslen(void)632 void wmemcpy_wcslen(void) {
633   wchar_t a[32];
634   // FIXME: This should work with 'w_str' instead of 'w_str1'
635   const wchar_t w_str1[] = L"Hello world";
636   wmemcpy(a, w_str1, wcslen(w_str1) + 1);
637   wmemcpy(a, w_str1, wcslen(w_str1) + 2); // expected-warning {{Memory copy function accesses out-of-bound array element}}
638 }
639