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 // wwmemcpy()
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 // wcslen()
144 //===----------------------------------------------------------------------===
145 
146 #define wcslen BUILTIN(wcslen)
147 size_t wcslen(const wchar_t *s);
148 
wcslen_constant0(void)149 void wcslen_constant0(void) {
150   clang_analyzer_eval(wcslen(L"123") == 3); // expected-warning{{TRUE}}
151 }
152 
wcslen_constant1(void)153 void wcslen_constant1(void) {
154   const wchar_t *a = L"123";
155   clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{TRUE}}
156 }
157 
wcslen_constant2(wchar_t x)158 void wcslen_constant2(wchar_t x) {
159   wchar_t a[] = L"123";
160   clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{TRUE}}
161 
162   a[0] = x;
163   clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{UNKNOWN}}
164 }
165 
wcslen_null(void)166 size_t wcslen_null(void) {
167   return wcslen(0); // expected-warning{{Null pointer passed as 1st argument to string length function}}
168 }
169 
wcslen_fn(void)170 size_t wcslen_fn(void) {
171   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}}
172 }
173 
wcslen_nonloc(void)174 size_t wcslen_nonloc(void) {
175 label:
176   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}}
177 }
178 
wcslen_subregion(void)179 void wcslen_subregion(void) {
180   struct two_strings { wchar_t a[2], b[2]; };
181   extern void use_two_strings(struct two_strings *);
182 
183   struct two_strings z;
184   use_two_strings(&z);
185 
186   size_t a = wcslen(z.a);
187   z.b[0] = 5;
188   size_t b = wcslen(z.a);
189   if (a == 0)
190     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
191 
192   use_two_strings(&z);
193 
194   size_t c = wcslen(z.a);
195   if (a == 0)
196     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
197 }
198 
199 extern void use_string(wchar_t *);
wcslen_argument(wchar_t * x)200 void wcslen_argument(wchar_t *x) {
201   size_t a = wcslen(x);
202   size_t b = wcslen(x);
203   if (a == 0)
204     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
205 
206   use_string(x);
207 
208   size_t c = wcslen(x);
209   if (a == 0)
210     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
211 }
212 
213 extern wchar_t global_str[];
wcslen_global(void)214 void wcslen_global(void) {
215   size_t a = wcslen(global_str);
216   size_t b = wcslen(global_str);
217   if (a == 0) {
218     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
219     // Make sure clang_analyzer_eval does not invalidate globals.
220     clang_analyzer_eval(wcslen(global_str) == 0); // expected-warning{{TRUE}}
221   }
222 
223   // Call a function with unknown effects, which should invalidate globals.
224   use_string(0);
225 
226   size_t c = wcslen(global_str);
227   if (a == 0)
228     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
229 }
230 
wcslen_indirect(wchar_t * x)231 void wcslen_indirect(wchar_t *x) {
232   size_t a = wcslen(x);
233   wchar_t *p = x;
234   wchar_t **p2 = &p;
235   size_t b = wcslen(x);
236   if (a == 0)
237     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
238 
239   extern void use_string_ptr(wchar_t*const*);
240   use_string_ptr(p2);
241 
242   size_t c = wcslen(x);
243   if (a == 0)
244     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
245 }
246 
wcslen_indirect2(wchar_t * x)247 void wcslen_indirect2(wchar_t *x) {
248   size_t a = wcslen(x);
249   wchar_t *p = x;
250   wchar_t **p2 = &p;
251   extern void use_string_ptr2(wchar_t**);
252   use_string_ptr2(p2);
253 
254   size_t c = wcslen(x);
255   if (a == 0)
256     clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
257 }
258 
wcslen_liveness(const wchar_t * x)259 void wcslen_liveness(const wchar_t *x) {
260   if (wcslen(x) < 5)
261     return;
262   clang_analyzer_eval(wcslen(x) < 5); // expected-warning{{FALSE}}
263 }
264 
265 
wcslenWrapper(const wchar_t * str)266 size_t wcslenWrapper(const wchar_t *str) {
267   return wcslen(str);
268 }
269 
270 extern void invalidate(wchar_t *s);
271 
testwcslenCallee(void)272 void testwcslenCallee(void) {
273   wchar_t str[42];
274   invalidate(str);
275   size_t lenBefore = wcslenWrapper(str);
276   invalidate(str);
277   size_t lenAfter = wcslenWrapper(str);
278   clang_analyzer_eval(lenBefore == lenAfter); // expected-warning{{UNKNOWN}}
279 }
280 
281 //===----------------------------------------------------------------------===
282 // wcsnlen()
283 //===----------------------------------------------------------------------===
284 
285 size_t wcsnlen(const wchar_t *s, size_t maxlen);
286 
wcsnlen_constant0(void)287 void wcsnlen_constant0(void) {
288   clang_analyzer_eval(wcsnlen(L"123", 10) == 3); // expected-warning{{TRUE}}
289 }
290 
wcsnlen_constant1(void)291 void wcsnlen_constant1(void) {
292   const wchar_t *a = L"123";
293   clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{TRUE}}
294 }
295 
wcsnlen_constant2(char x)296 void wcsnlen_constant2(char x) {
297   wchar_t a[] = L"123";
298   clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{TRUE}}
299   a[0] = x;
300   clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{UNKNOWN}}
301 }
302 
wcsnlen_constant4(void)303 void wcsnlen_constant4(void) {
304   clang_analyzer_eval(wcsnlen(L"123456", 3) == 3); // expected-warning{{TRUE}}
305 }
306 
wcsnlen_constant5(void)307 void wcsnlen_constant5(void) {
308   const wchar_t *a = L"123456";
309   clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{TRUE}}
310 }
311 
wcsnlen_constant6(char x)312 void wcsnlen_constant6(char x) {
313   wchar_t a[] = L"123456";
314   clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{TRUE}}
315   a[0] = x;
316   clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{UNKNOWN}}
317 }
318 
wcsnlen_null(void)319 size_t wcsnlen_null(void) {
320   return wcsnlen(0, 3); // expected-warning{{Null pointer passed as 1st argument to string length function}}
321 }
322 
wcsnlen_fn(void)323 size_t wcsnlen_fn(void) {
324   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}}
325 }
326 
wcsnlen_nonloc(void)327 size_t wcsnlen_nonloc(void) {
328 label:
329   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}}
330 }
331 
wcsnlen_zero(void)332 void wcsnlen_zero(void) {
333   clang_analyzer_eval(wcsnlen(L"abc", 0) == 0); // expected-warning{{TRUE}}
334   clang_analyzer_eval(wcsnlen(0, 0) == 0); // expected-warning{{TRUE}}
335 }
336 
wcsnlen_compound_literal(void)337 size_t wcsnlen_compound_literal(void) {
338   // This used to crash because we don't model the string lengths of
339   // compound literals.
340   return wcsnlen((wchar_t[]) { 'a', 'b', 0 }, 1);
341 }
342 
wcsnlen_unknown_limit(float f)343 size_t wcsnlen_unknown_limit(float f) {
344   // This used to crash because we don't model the integer values of floats.
345   return wcsnlen(L"abc", (int)f);
346 }
347 
wcsnlen_is_not_wcslen(wchar_t * x)348 void wcsnlen_is_not_wcslen(wchar_t *x) {
349   clang_analyzer_eval(wcsnlen(x, 10) == wcslen(x)); // expected-warning{{UNKNOWN}}
350 }
351 
wcsnlen_at_limit(wchar_t * x)352 void wcsnlen_at_limit(wchar_t *x) {
353   size_t len = wcsnlen(x, 10);
354   clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}}
355   clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}}
356   clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}}
357 }
358 
wcsnlen_at_actual(size_t limit)359 void wcsnlen_at_actual(size_t limit) {
360   size_t len = wcsnlen(L"abc", limit);
361   clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}}
362   // This is due to eager assertion in wcsnlen.
363   if (limit == 0) {
364     clang_analyzer_eval(len == 0); // expected-warning{{TRUE}}
365   } else {
366     clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}}
367     clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}}
368   }
369 }
370 
371 //===----------------------------------------------------------------------===
372 // other tests
373 //===----------------------------------------------------------------------===
374 
375 static const wchar_t w_str[] = L"Hello world";
376 
wmemcpy_sizeof(void)377 void wmemcpy_sizeof(void) {
378   wchar_t a[32];
379   wmemcpy(a, w_str, sizeof(w_str) / sizeof(w_str[0]));
380   wmemcpy(a, w_str, (sizeof(w_str) / sizeof(w_str[0])) + 1); // expected-warning {{Memory copy function accesses out-of-bound array element}}
381 }
382 
wmemcpy_wcslen(void)383 void wmemcpy_wcslen(void) {
384   wchar_t a[32];
385   // FIXME: This should work with 'w_str' instead of 'w_str1'
386   const wchar_t w_str1[] = L"Hello world";
387   wmemcpy(a, w_str1, wcslen(w_str1) + 1);
388   wmemcpy(a, w_str1, wcslen(w_str1) + 2); // expected-warning {{Memory copy function accesses out-of-bound array element}}
389 }
390