xref: /llvm-project/clang/test/Analysis/taint-generic.c (revision 09b8dbfa80d62e64efb09bd166324270c96badf9)
1 // RUN: %clang_analyze_cc1 -Wno-format-security -Wno-pointer-to-int-cast \
2 // RUN:   -Wno-incompatible-library-redeclaration -verify %s \
3 // RUN:   -analyzer-checker=optin.taint.GenericTaint \
4 // RUN:   -analyzer-checker=optin.taint.TaintedDiv \
5 // RUN:   -analyzer-checker=core \
6 // RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
7 // RUN:   -analyzer-checker=debug.ExprInspection \
8 // RUN:   -analyzer-config \
9 // RUN:     optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
10 
11 // RUN: %clang_analyze_cc1 -Wno-format-security -Wno-pointer-to-int-cast \
12 // RUN:   -Wno-incompatible-library-redeclaration -verify %s \
13 // RUN:   -DFILE_IS_STRUCT \
14 // RUN:   -analyzer-checker=optin.taint.GenericTaint \
15 // RUN:   -analyzer-checker=optin.taint.TaintedDiv \
16 // RUN:   -analyzer-checker=core \
17 // RUN:   -analyzer-checker=alpha.security.ArrayBoundV2 \
18 // RUN:   -analyzer-checker=debug.ExprInspection \
19 // RUN:   -analyzer-config \
20 // RUN:     optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml
21 
22 // RUN: not %clang_analyze_cc1 -verify %s \
23 // RUN:   -analyzer-checker=optin.taint.GenericTaint  \
24 // RUN:   -analyzer-config \
25 // RUN:     optin.taint.TaintPropagation:Config=justguessit \
26 // RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-FILE
27 
28 // CHECK-INVALID-FILE: (frontend): invalid input for checker option
29 // CHECK-INVALID-FILE-SAME:        'optin.taint.TaintPropagation:Config',
30 // CHECK-INVALID-FILE-SAME:        that expects a valid filename instead of
31 // CHECK-INVALID-FILE-SAME:        'justguessit'
32 
33 // RUN: not %clang_analyze_cc1 -verify %s \
34 // RUN:   -analyzer-checker=optin.taint.GenericTaint  \
35 // RUN:   -analyzer-config \
36 // RUN:     optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config-ill-formed.yaml \
37 // RUN:   2>&1 | FileCheck -DMSG=%errc_EINVAL %s -check-prefix=CHECK-ILL-FORMED
38 
39 // CHECK-ILL-FORMED: (frontend): invalid input for checker option
40 // CHECK-ILL-FORMED-SAME:        'optin.taint.TaintPropagation:Config',
41 // CHECK-ILL-FORMED-SAME:        that expects a valid yaml file: [[MSG]]
42 
43 // RUN: not %clang_analyze_cc1 -verify %s \
44 // RUN:   -analyzer-checker=optin.taint.GenericTaint \
45 // RUN:   -analyzer-config \
46 // RUN:     optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config-invalid-arg.yaml \
47 // RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-ARG
48 
49 // CHECK-INVALID-ARG: (frontend): invalid input for checker option
50 // CHECK-INVALID-ARG-SAME:        'optin.taint.TaintPropagation:Config',
51 // CHECK-INVALID-ARG-SAME:        that expects an argument number for propagation
52 // CHECK-INVALID-ARG-SAME:        rules greater or equal to -1
53 
54 typedef long long rsize_t;
55 typedef __typeof(sizeof(int)) size_t;
56 typedef signed long long ssize_t;
57 typedef __WCHAR_TYPE__ wchar_t;
58 void clang_analyzer_isTainted_char(char);
59 void clang_analyzer_isTainted_wchar(wchar_t);
60 void clang_analyzer_isTainted_charp(char*);
61 void clang_analyzer_isTainted_int(int);
62 void clang_analyzer_dump_int(int);
63 
64 int coin();
65 
66 int scanf(const char *restrict format, ...);
67 char *gets(char *str);
68 char *gets_s(char *str, rsize_t n);
69 int getchar(void);
70 
71 typedef struct _FILE FILE;
72 #ifdef FILE_IS_STRUCT
73 extern struct _FILE *stdin;
74 #else
75 extern FILE *stdin;
76 #endif
77 
78 #define bool _Bool
79 #define NULL (void*)0
80 
81 wchar_t *fgetws(wchar_t *ws, int n, FILE *stream);
82 wchar_t *wmemset(wchar_t *wcs, wchar_t wc, unsigned long n);
83 wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t n);
84 wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t n);
85 size_t wcslen(const wchar_t *s);
86 wchar_t *wcscpy(wchar_t * dest, const wchar_t * src);
87 wchar_t *wcsncpy(wchar_t *dest, const wchar_t *src, size_t n);
88 wchar_t *wcscat(wchar_t *dest, const wchar_t *src);
89 wchar_t *wcsncat(wchar_t *dest,const wchar_t *src, size_t n);
90 int swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...);
91 
92 char *getenv(const char *name);
93 
94 FILE *fopen(const char *name, const char *mode);
95 
96 int fscanf(FILE *restrict stream, const char *restrict format, ...);
97 int sprintf(char *str, const char *format, ...);
98 void setproctitle(const char *fmt, ...);
99 void setproctitle_init(int argc, char *argv[], char *envp[]);
100 
101 // Define string functions. Use builtin for some of them. They all default to
102 // the processing in the taint checker.
103 #define strcpy(dest, src) \
104   ((__builtin_object_size(dest, 0) != -1ULL) \
105    ? __builtin___strcpy_chk (dest, src, __builtin_object_size(dest, 1)) \
106    : __inline_strcpy_chk(dest, src))
107 
108 static char *__inline_strcpy_chk (char *dest, const char *src) {
109   return __builtin___strcpy_chk(dest, src, __builtin_object_size(dest, 1));
110 }
111 char *stpcpy(char *restrict s1, const char *restrict s2);
112 char *strncpy( char * destination, const char * source, size_t num );
113 char *strndup(const char *s, size_t n);
114 char *strncat(char *restrict s1, const char *restrict s2, size_t n);
115 
116 void *malloc(size_t);
117 void *calloc(size_t nmemb, size_t size);
118 void bcopy(void *s1, void *s2, size_t n);
119 
120 
121 //    function | pathname | filename | fd | arglist | argv[] | envp[]
122 //    ===============================================================
123 // 1  execl    |     X    |          |    |    X    |        |
124 // 2  execle   |     X    |          |    |    X    |        |   X
125 // 3  execlp   |          |     X    |    |    X    |        |
126 // 4  execv    |     X    |          |    |         |    X   |
127 // 5  execve   |     X    |          |    |         |    X   |   X
128 // 6  execvp   |          |     X    |    |         |    X   |
129 // 7  execvpe  |          |     X    |    |         |    X   |   X
130 // 8  fexecve  |          |          |  X |         |    X   |   X
131 //    ===============================================================
132 //    letter   |          |     p    |  f |    l    |    v   |   e
133 //
134 // legend:
135 //  - pathname: rel/abs path to the binary
136 //  - filename: file name searched in PATH to execute the binary
137 //  - fd:       accepts a file descriptor
138 //  - arglist:  accepts variadic arguments
139 //  - argv:     accepts a pointer to array, denoting the new argv
140 //  - envp:     accepts a pointer to array, denoting the new envp
141 
142 int execl(const char *path, const char *arg, ...);
143 int execle(const char *path, const char *arg, ...);
144 int execlp(const char *file, const char *arg, ...);
145 int execv(const char *path, char *const argv[]);
146 int execve(const char *path, char *const argv[], char *const envp[]);
147 int execvp(const char *file, char *const argv[]);
148 int execvpe(const char *file, char *const argv[], char *const envp[]);
149 int fexecve(int fd, char *const argv[], char *const envp[]);
150 FILE *popen(const char *command, const char *type);
151 int pclose(FILE *stream);
152 int system(const char *command);
153 
154 
155 typedef size_t socklen_t;
156 
157 struct sockaddr {
158   unsigned short sa_family;
159   char sa_data[14];
160 };
161 
162 #define BUFSIZE 10
163 
164 int Buffer[BUFSIZE];
165 void bufferScanfDirect(void)
166 {
167   int n;
168   scanf("%d", &n);
169   Buffer[n] = 1; // expected-warning {{Potential out of bound access }}
170 }
171 
172 void bufferScanfArithmetic1(int x) {
173   int n;
174   scanf("%d", &n);
175   int m = (n - 3);
176   Buffer[m] = 1; // expected-warning {{Potential out of bound access }}
177 }
178 
179 void bufferScanfArithmetic2(int x) {
180   int n;
181   scanf("%d", &n);
182   int m = 100 - (n + 3) * x;
183   Buffer[m] = 1; // expected-warning {{Potential out of bound access }}
184 }
185 
186 void bufferScanfAssignment(int x) {
187   int n;
188   scanf("%d", &n);
189   int m;
190   if (x > 0) {
191     m = n;
192     Buffer[m] = 1; // expected-warning {{Potential out of bound access }}
193   }
194 }
195 
196 void scanfArg(void) {
197   int t = 0;
198   scanf("%d", t); // expected-warning {{format specifies type 'int *' but the argument has type 'int'}}
199 }
200 
201 void bufferGetchar(int x) {
202   int m = getchar();
203   Buffer[m] = 1;  //expected-warning {{Potential out of bound access}}
204 }
205 
206 extern const unsigned short int **__ctype_b_loc (void);
207 enum { _ISdigit = 2048 };
208 # define isdigit(c) ((*__ctype_b_loc ())[(int) (c)] & (unsigned short int) _ISdigit)
209 
210 int isdigitImplFalsePositive(void) {
211   // If this code no longer produces a bug report, then consider removing the
212   // special case that disables buffer overflow reports coming from the isXXXXX
213   // macros in ctypes.h.
214   int c = getchar();
215   return ((*__ctype_b_loc ())[(int) (c)] & (unsigned short int) _ISdigit);
216   //expected-warning@-1 {{Potential out of bound access}}
217 }
218 
219 int isdigitSuppressed(void) {
220   // Same code as above, but reports are suppressed based on macro name:
221   int c = getchar();
222   return isdigit(c); //no-warning
223 }
224 
225 // Some later tests use isdigit as a function, so we need to undef it:
226 #undef isdigit
227 
228 void testUncontrolledFormatString(char **p) {
229   char s[80];
230   fscanf(stdin, "%s", s);
231   char buf[128];
232   sprintf(buf,s); // expected-warning {{Uncontrolled Format String}}
233   setproctitle(s, 3); // expected-warning {{Uncontrolled Format String}}
234 
235   // Test taint propagation through strcpy and family.
236   char scpy[80];
237   strcpy(scpy, s);
238   sprintf(buf,scpy); // expected-warning {{Uncontrolled Format String}}
239 
240   stpcpy(*(++p), s); // this generates __inline.
241   setproctitle(*(p), 3); // expected-warning {{Uncontrolled Format String}}
242 
243   char spcpy[80];
244   stpcpy(spcpy, s);
245   setproctitle(spcpy, 3); // expected-warning {{Uncontrolled Format String}}
246 
247   char *spcpyret;
248   spcpyret = stpcpy(spcpy, s);
249   setproctitle(spcpyret, 3); // expected-warning {{Uncontrolled Format String}}
250 
251   char sncpy[80];
252   strncpy(sncpy, s, 20);
253   setproctitle(sncpy, 3); // expected-warning {{Uncontrolled Format String}}
254 
255   char *dup;
256   dup = strndup(s, 20);
257   setproctitle(dup, 3); // expected-warning {{Uncontrolled Format String}}
258 
259 }
260 
261 void testTaintSystemCall(void) {
262   char buffer[156];
263   char addr[128];
264   scanf("%s", addr);
265   system(addr); // expected-warning {{Untrusted data is passed to a system call}}
266 
267   // Test that spintf transfers taint.
268   sprintf(buffer, "/bin/mail %s < /tmp/email", addr);
269   system(buffer); // expected-warning {{Untrusted data is passed to a system call}}
270 }
271 
272 void testTaintSystemCall2(void) {
273   // Test that snpintf transfers taint.
274   char buffern[156];
275   char addr[128];
276   scanf("%s", addr);
277   __builtin_snprintf(buffern, 10, "/bin/mail %s < /tmp/email", addr);
278   // expected-warning@-1 {{'snprintf' will always be truncated; specified size is 10, but format string expands to at least 24}}
279   system(buffern); // expected-warning {{Untrusted data is passed to a system call}}
280 }
281 
282 void testTaintSystemCall3(void) {
283   char buffern2[156];
284   int numt;
285   char addr[128];
286   scanf("%s %d", addr, &numt);
287   __builtin_snprintf(buffern2, numt, "/bin/mail %s < /tmp/email", "abcd");
288   system(buffern2); // expected-warning {{Untrusted data is passed to a system call}}
289 }
290 
291 void testGets(void) {
292   char str[50];
293   gets(str);
294   system(str); // expected-warning {{Untrusted data is passed to a system call}}
295 }
296 
297 void testGets_s(void) {
298   char str[50];
299   gets_s(str, 49);
300   system(str); // expected-warning {{Untrusted data is passed to a system call}}
301 }
302 
303 void testTaintedBufferSize(void) {
304   size_t ts;
305   // The functions malloc, calloc, bcopy and memcpy are not taint sinks in the
306   // default config of GenericTaintChecker (because that would cause too many
307   // false positives).
308   // FIXME: We should generate warnings when a value passed to these functions
309   // is tainted and _can be very large_ (because that's exploitable). This
310   // functionality probably belongs to the checkers that do more detailed
311   // modeling of these functions (MallocChecker and CStringChecker).
312   scanf("%zd", &ts);
313   int *buf1 = (int*)malloc(ts*sizeof(int)); // warn here, ts is unbounded and tainted
314   char *dst = (char*)calloc(ts, sizeof(char)); // warn here, ts is unbounded tainted
315   bcopy(buf1, dst, ts); // no warning here, since the size of buf1, dst equals ts. Cannot overflow.
316   __builtin_memcpy(dst, buf1, (ts + 4)*sizeof(char)); // warn here, dst overflows (whatever the value of ts)
317 
318   // If both buffers are trusted, do not issue a warning.
319   char *dst2 = (char*)malloc(ts*sizeof(char)); // warn here, ts in unbounded
320   strncat(dst2, dst, ts); // no-warning
321 }
322 
323 #define AF_UNIX   1   /* local to host (pipes) */
324 #define AF_INET   2   /* internetwork: UDP, TCP, etc. */
325 #define AF_LOCAL  AF_UNIX   /* backward compatibility */
326 #define SOCK_STREAM 1
327 int socket(int, int, int);
328 size_t read(int, void *, size_t);
329 
330 void testSocket(void) {
331   int sock;
332   char buffer[100];
333 
334   sock = socket(AF_INET, SOCK_STREAM, 0);
335   read(sock, buffer, 100);
336   execl(buffer, "filename", 0); // expected-warning {{Untrusted data is passed to a system call}}
337 
338   sock = socket(AF_LOCAL, SOCK_STREAM, 0);
339   read(sock, buffer, 100);
340   execl(buffer, "filename", 0); // no-warning
341 
342   sock = socket(AF_INET, SOCK_STREAM, 0);
343   // References to both buffer and &buffer as an argument should taint the argument
344   read(sock, &buffer, 100);
345   execl(buffer, "filename", 0); // expected-warning {{Untrusted data is passed to a system call}}
346 }
347 
348 void testStruct(void) {
349   struct {
350     char buf[16];
351     int length;
352   } tainted;
353 
354   char buffer[16];
355   int sock;
356 
357   sock = socket(AF_INET, SOCK_STREAM, 0);
358   read(sock, &tainted, sizeof(tainted));
359   clang_analyzer_isTainted_int(tainted.length); // expected-warning {{YES }}
360 }
361 
362 void testStructArray(void) {
363   struct {
364     int length;
365   } tainted[4];
366 
367   char dstbuf[16], srcbuf[16];
368   int sock;
369 
370   sock = socket(AF_INET, SOCK_STREAM, 0);
371   __builtin_memset(srcbuf, 0, sizeof(srcbuf));
372 
373   read(sock, &tainted[0], sizeof(tainted));
374   clang_analyzer_isTainted_int(tainted[0].length); // expected-warning {{YES}}
375 
376   __builtin_memset(&tainted, 0, sizeof(tainted));
377   read(sock, &tainted, sizeof(tainted));
378   clang_analyzer_isTainted_int(tainted[0].length); // expected-warning {{YES}}
379 
380   __builtin_memset(&tainted, 0, sizeof(tainted));
381   // If we taint element 1, we should not raise an alert on taint for element 0 or element 2
382   read(sock, &tainted[1], sizeof(tainted));
383   clang_analyzer_isTainted_int(tainted[0].length); // expected-warning {{NO}}
384   clang_analyzer_isTainted_int(tainted[2].length); // expected-warning {{NO}}
385 }
386 
387 void testUnion(void) {
388   union {
389     int x;
390     char y[4];
391   } tainted;
392 
393   char buffer[4];
394 
395   int sock = socket(AF_INET, SOCK_STREAM, 0);
396   read(sock, &tainted.y, sizeof(tainted.y));
397   // FIXME: overlapping regions aren't detected by isTainted yet
398   __builtin_memcpy(buffer, tainted.y, tainted.x);
399 }
400 
401 int testDivByZero(void) {
402   int x;
403   scanf("%d", &x);
404   return 5/x; // expected-warning {{Division by a tainted value, possibly zero}}
405 }
406 
407 int testTaintedDivFP(void) {
408   int x;
409   scanf("%d", &x);
410   if (!x)
411     return 0;
412   return 5/x; // x cannot be 0, so no tainted warning either
413 }
414 
415 // Zero-sized VLAs.
416 void testTaintedVLASize(void) {
417   int x;
418   scanf("%d", &x);
419   int vla[x]; // expected-warning{{Declared variable-length array (VLA) has tainted (attacker controlled) size that can be 0 or negative}}
420 }
421 
422 // Tainted-sanitized VLAs.
423 void testTaintedSanitizedVLASize(void) {
424   int x;
425   scanf("%d", &x);
426   if (x<1)
427     return;
428   int vla[x]; // no-warning
429 }
430 
431 int testTaintedAllocaMem() {
432   char x;
433   void * p;
434   scanf("%c", &x);
435   p = __builtin_alloca(1);
436   __builtin_memcpy(p, &x, 1);
437   return 5 / *(char*)p; // expected-warning {{Division by a tainted value, possibly zero}}
438 }
439 
440 int testTaintedMallocMem() {
441   char x;
442   void * p;
443   scanf("%c", &x);
444   p = malloc(1);
445   __builtin_memcpy(p, &x, 1);
446   return 5 / *(char*)p; // expected-warning {{Division by a tainted value, possibly zero}}
447 }
448 
449 
450 // This computation used to take a very long time.
451 #define longcmp(a,b,c) { \
452   a -= c;  a ^= c;  c += b; b -= a;  b ^= (a<<6) | (a >> (32-b));  a += c; c -= b;  c ^= b;  b += a; \
453   a -= c;  a ^= c;  c += b; b -= a;  b ^= a;  a += c; c -= b;  c ^= b;  b += a; }
454 
455 unsigned radar11369570_hanging(const unsigned char *arr, int l) {
456   unsigned a, b, c;
457   a = b = c = 0x9899e3 + l;
458   while (l >= 6) {
459     unsigned t;
460     scanf("%d", &t);
461     a += b;
462     a ^= a;
463     a += (arr[3] + ((unsigned) arr[2] << 8) + ((unsigned) arr[1] << 16) + ((unsigned) arr[0] << 24));
464     longcmp(a, t, c);
465     l -= 12;
466   }
467   return 5/a; // FIXME: Should be a "div by tainted" warning here.
468 }
469 
470 // This computation used to take a very long time.
471 void complex_taint_queries(const int *p) {
472   int tainted = 0;
473   scanf("%d", &tainted);
474 
475   // Make "tmp" tainted.
476   int tmp = tainted + tainted;
477   clang_analyzer_isTainted_int(tmp); // expected-warning{{YES}}
478 
479   // Make "tmp" SymExpr a lot more complicated by applying computation.
480   // This should balloon the symbol complexity.
481   tmp += p[0] + p[0];
482   tmp += p[1] + p[1];
483   tmp += p[2] + p[2];
484   clang_analyzer_dump_int(tmp); // expected-warning{{((((conj_}} symbol complexity: 8
485   clang_analyzer_isTainted_int(tmp); // expected-warning{{YES}}
486 
487   tmp += p[3] + p[3];
488   clang_analyzer_dump_int(tmp); // expected-warning{{(((((conj_}} symbol complexity: 10
489   clang_analyzer_isTainted_int(tmp); // expected-warning{{NO}} 10 is already too complex to be traversed
490 
491   tmp += p[4] + p[4];
492   tmp += p[5] + p[5];
493   tmp += p[6] + p[6];
494   tmp += p[7] + p[7];
495   tmp += p[8] + p[8];
496   tmp += p[9] + p[9];
497   tmp += p[10] + p[10];
498   tmp += p[11] + p[11];
499   tmp += p[12] + p[12];
500   tmp += p[13] + p[13];
501   tmp += p[14] + p[14];
502   tmp += p[15] + p[15];
503 
504   // The SymExpr still holds the full history of the computation, yet, "isTainted" doesn't traverse the tree as the complexity is over the threshold.
505   clang_analyzer_dump_int(tmp);
506   // expected-warning@-1{{(((((((((((((((((conj_}} symbol complexity: 34
507   clang_analyzer_isTainted_int(tmp); // expected-warning{{NO}} FIXME: Ideally, this should still result in "tainted".
508 
509   // By making it even one step more complex, then it would hit the "max-symbol-complexity"
510   // threshold and the engine would cut the SymExpr and replace it by a new conjured symbol.
511   tmp += p[16];
512   clang_analyzer_dump_int(tmp); // expected-warning{{conj_}} symbol complexity: 1
513   clang_analyzer_isTainted_int(tmp); // expected-warning{{NO}}
514 }
515 
516 // Check that we do not assert of the following code.
517 int SymSymExprWithDiffTypes(void* p) {
518   int i;
519   scanf("%d", &i);
520   int j = (i % (int)(long)p);
521   return 5/j; // expected-warning {{Division by a tainted value, possibly zero}}
522 }
523 
524 
525 void constraintManagerShouldTreatAsOpaque(int rhs) {
526   int i;
527   scanf("%d", &i);
528   // This comparison used to hit an assertion in the constraint manager,
529   // which didn't handle NonLoc sym-sym comparisons.
530   if (i < rhs)
531     return;
532   if (i < rhs)
533     *(volatile int *) 0; // no-warning
534 }
535 
536 int testSprintf_is_not_a_source(char *buf, char *msg) {
537   int x = sprintf(buf, "%s", msg); // no-warning
538   return 1 / x;                    // no-warning: 'sprintf' is not a taint source
539 }
540 
541 int testSprintf_propagates_taint(char *buf, char *msg) {
542   scanf("%s", msg);
543   int x = sprintf(buf, "%s", msg); // propagate taint!
544   return 1 / x;                    // expected-warning {{Division by a tainted value, possibly zero}}
545 }
546 
547 void test_wchar_apis_dont_propagate(const char *path) {
548   // strlen, wcslen, strnlen and alike intentionally don't propagate taint.
549   // See the details here: https://github.com/llvm/llvm-project/pull/66086
550   // This isn't ideal, but this is only what we have now.
551 
552   FILE *f = fopen(path, "r");
553   clang_analyzer_isTainted_charp((char*)f);  // expected-warning {{YES}}
554   wchar_t wbuf[10];
555   fgetws(wbuf, sizeof(wbuf)/sizeof(*wbuf), f);
556   clang_analyzer_isTainted_wchar(*wbuf); // expected-warning {{YES}}
557   int n = wcslen(wbuf);
558   clang_analyzer_isTainted_int(n); // expected-warning {{NO}}
559 
560   wchar_t dst[100] = L"ABC";
561   clang_analyzer_isTainted_wchar(*dst); // expected-warning {{NO}}
562   wcsncat(dst, wbuf, sizeof(wbuf)/sizeof(*wbuf));
563   clang_analyzer_isTainted_wchar(*dst); // expected-warning {{YES}}
564 
565   int m = wcslen(dst);
566   clang_analyzer_isTainted_int(m); // expected-warning {{NO}}
567 }
568 
569 int scanf_s(const char *format, ...);
570 int testScanf_s_(int *out) {
571   scanf_s("%d", out);
572   return 1 / *out; // expected-warning {{Division by a tainted value, possibly zero}}
573 }
574 
575 #define _IO_FILE FILE
576 int _IO_getc(_IO_FILE *__fp);
577 int testUnderscoreIO_getc(_IO_FILE *fp) {
578   char c = _IO_getc(fp);
579   return 1 / c; // expected-warning {{Division by a tainted value, possibly zero}}
580 }
581 
582 char *getcwd(char *buf, size_t size);
583 int testGetcwd(char *buf, size_t size) {
584   char *c = getcwd(buf, size);
585   return system(c); // expected-warning {{Untrusted data is passed to a system call}}
586 }
587 
588 char *getwd(char *buf);
589 int testGetwd(char *buf) {
590   char *c = getwd(buf);
591   return system(c); // expected-warning {{Untrusted data is passed to a system call}}
592 }
593 
594 ssize_t readlink(const char *path, char *buf, size_t bufsiz);
595 int testReadlink(char *path, char *buf, size_t bufsiz) {
596   ssize_t s = readlink(path, buf, bufsiz);
597   system(buf); // expected-warning {{Untrusted data is passed to a system call}}
598   // readlink never returns 0
599   return 1 / (s + 1); // expected-warning {{Division by a tainted value, possibly zero}}
600 }
601 
602 ssize_t readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
603 int testReadlinkat(int dirfd, char *path, char *buf, size_t bufsiz) {
604   ssize_t s = readlinkat(dirfd, path, buf, bufsiz);
605   system(buf);        // expected-warning {{Untrusted data is passed to a system call}}
606   (void)(1 / dirfd);  // arg 0 is not tainted
607   system(path);       // arg 1 is not tainted
608   (void)(1 / bufsiz); // arg 3 is not tainted
609   // readlinkat never returns 0
610   return 1 / (s + 1); // expected-warning {{Division by a tainted value, possibly zero}}
611 }
612 
613 char *get_current_dir_name(void);
614 int testGet_current_dir_name() {
615   char *d = get_current_dir_name();
616   return system(d); // expected-warning {{Untrusted data is passed to a system call}}
617 }
618 
619 int gethostname(char *name, size_t len);
620 int testGethostname(char *name, size_t len) {
621   gethostname(name, len);
622   return system(name); // expected-warning {{Untrusted data is passed to a system call}}
623 }
624 
625 int getnameinfo(const struct sockaddr *restrict addr, socklen_t addrlen,
626                 char *restrict host, socklen_t hostlen,
627                 char *restrict serv, socklen_t servlen, int flags);
628 int testGetnameinfo(const struct sockaddr *restrict addr, socklen_t addrlen,
629                     char *restrict host, socklen_t hostlen,
630                     char *restrict serv, socklen_t servlen, int flags) {
631   getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);
632 
633   system(host);        // expected-warning {{Untrusted data is passed to a system call}}
634   return system(serv); // expected-warning {{Untrusted data is passed to a system call}}
635 }
636 
637 int getseuserbyname(const char *linuxuser, char **selinuxuser, char **level);
638 int testGetseuserbyname(const char *linuxuser, char **selinuxuser, char **level) {
639   getseuserbyname(linuxuser, selinuxuser, level);
640   system(selinuxuser[0]);  // expected-warning {{Untrusted data is passed to a system call}}
641   return system(level[0]); // expected-warning {{Untrusted data is passed to a system call}}
642 }
643 
644 typedef int gid_t;
645 int getgroups(int size, gid_t list[]);
646 int testGetgroups(int size, gid_t list[], bool flag) {
647   int result = getgroups(size, list);
648   if (flag)
649     return 1 / list[0]; // expected-warning {{Division by a tainted value, possibly zero}}
650 
651   return 1 / (result + 1); // expected-warning {{Division by a tainted value, possibly zero}}
652 }
653 
654 char *getlogin(void);
655 int testGetlogin() {
656   char *n = getlogin();
657   return system(n); // expected-warning {{Untrusted data is passed to a system call}}
658 }
659 
660 int getlogin_r(char *buf, size_t bufsize);
661 int testGetlogin_r(char *buf, size_t bufsize) {
662   getlogin_r(buf, bufsize);
663   return system(buf); // expected-warning {{Untrusted data is passed to a system call}}
664 }
665 
666 int fscanf_s(FILE *stream, const char *format, ...);
667 void testFscanf_s(const char *fname, int *d) {
668   FILE *f = fopen(fname, "r");
669   fscanf_s(f, "%d", d);
670   clang_analyzer_isTainted_int(*d); // expected-warning {{YES}}
671 }
672 
673 int fread(void *buffer, size_t size, size_t count, FILE *stream);
674 void testFread(const char *fname, int *buffer, size_t size, size_t count) {
675   FILE *f = fopen(fname, "r");
676   size_t read = fread(buffer, size, count, f);
677 
678   clang_analyzer_isTainted_int(*buffer); // expected-warning {{YES}}
679   clang_analyzer_isTainted_int(read); // expected-warning {{YES}}
680 }
681 
682 ssize_t recv(int sockfd, void *buf, size_t len, int flags);
683 int accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
684 int bind(int fd, const struct sockaddr *addr, socklen_t addrlen);
685 int listen(int fd, int backlog);
686 
687 void testRecv(int *buf, size_t len, int flags) {
688   int fd;
689   scanf("%d", &fd); // fake a tainted a file descriptor
690 
691   size_t read = recv(fd, buf, len, flags);
692   clang_analyzer_isTainted_int(*buf); // expected-warning {{YES}}
693   clang_analyzer_isTainted_int(read); // expected-warning {{YES}}
694 }
695 
696 ssize_t recvfrom(int sockfd, void *restrict buf, size_t len, int flags,
697                  struct sockaddr *restrict src_addr,
698                  socklen_t *restrict addrlen);
699 void testRecvfrom(int *restrict buf, size_t len, int flags,
700                  struct sockaddr *restrict src_addr,
701                  socklen_t *restrict addrlen) {
702   int fd;
703   scanf("%d", &fd); // fake a tainted a file descriptor
704 
705   size_t read = recvfrom(fd, buf, len, flags, src_addr, addrlen);
706   clang_analyzer_isTainted_int(*buf); // expected-warning {{YES}}
707   clang_analyzer_isTainted_int(read); // expected-warning {{YES}}
708 }
709 
710 char *ttyname(int fd);
711 void testTtyname() {
712   int fd;
713   scanf("%d", &fd); // fake a tainted a file descriptor
714 
715   char *name = ttyname(fd);
716   clang_analyzer_isTainted_charp(name); // expected-warning {{YES}}
717 }
718 
719 int ttyname_r(int fd, char *buf, size_t buflen);
720 void testTtyname_r(char *buf, size_t buflen) {
721   int fd;
722   scanf("%d", &fd); // fake a tainted a file descriptor
723 
724   int result = ttyname_r(fd, buf, buflen);
725   clang_analyzer_isTainted_char(*buf); // expected-warning {{YES}}
726   clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
727 }
728 
729 char *dirname(char *path);
730 void testDirname() {
731   char buf[10];
732   scanf("%9s", buf);
733 
734   char *name = dirname(buf);
735   clang_analyzer_isTainted_charp(name); // expected-warning {{YES}}
736 }
737 
738 char *basename(char *path);
739 void testBasename() {
740   char buf[10];
741   scanf("%9s", buf);
742 
743   char *name = basename(buf);
744   clang_analyzer_isTainted_charp(name); // expected-warning {{YES}}
745 }
746 
747 int fnmatch(const char *pattern, const char *string, int flags);
748 void testFnmatch(const char *pattern, int flags) {
749   char string[10];
750   scanf("%9s", string);
751 
752   int result = fnmatch(pattern, string, flags);
753   clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
754 }
755 
756 void *memchr(const void *s, int c, size_t n);
757 void testMemchr(int c, size_t n) {
758   char buf[10];
759   scanf("%9s", buf);
760 
761   char *result = memchr(buf, c, n);
762   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
763 }
764 
765 void *memrchr(const void *s, int c, size_t n);
766 void testMemrchr(int c, size_t n) {
767   char buf[10];
768   scanf("%9s", buf);
769 
770   char *result = memrchr(buf, c, n);
771   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
772 }
773 
774 void *rawmemchr(const void *s, int c);
775 void testRawmemchr(int c) {
776   char buf[10];
777   scanf("%9s", buf);
778 
779   char *result = rawmemchr(buf, c);
780   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
781 }
782 
783 int mbtowc(wchar_t *pwc, const char *s, size_t n);
784 void testMbtowc(wchar_t *pwc, size_t n) {
785   char buf[10];
786   scanf("%9s", buf);
787 
788   int result = mbtowc(pwc, buf, n);
789   clang_analyzer_isTainted_char(*pwc); // expected-warning {{YES}}
790   clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
791 }
792 
793 int wctomb(char *s, wchar_t wc);
794 void testWctomb(char *buf) {
795   wchar_t wc = getchar();
796 
797   int result = wctomb(buf, wc);
798   clang_analyzer_isTainted_char(*buf); // expected-warning {{YES}}
799   clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
800 }
801 
802 int wcwidth(wchar_t c);
803 void testWcwidth() {
804   wchar_t wc = getchar();
805 
806   int width = wcwidth(wc);
807   clang_analyzer_isTainted_int(width); // expected-warning {{YES}}
808 }
809 
810 int memcmp(const void *s1, const void *s2, size_t n);
811 void testMemcmpWithLHSTainted(size_t n, char *rhs) {
812   char lhs[10];
813   scanf("%9s", lhs);
814 
815   int cmp_result = memcmp(lhs, rhs, n);
816   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
817 }
818 
819 void testMemcmpWithRHSTainted(size_t n, char *lhs) {
820   char rhs[10];
821   scanf("%9s", rhs);
822 
823   int cmp_result = memcmp(lhs, rhs, n);
824   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
825 }
826 
827 void *memcpy(void *restrict dest, const void *restrict src, size_t n);
828 void testMemcpy(char *dst, size_t n) {
829   char src[10];
830   scanf("%9s", src);
831 
832   char *result = memcpy(dst, src, n);
833 
834   clang_analyzer_isTainted_char(*dst); // expected-warning {{YES}}
835   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
836 }
837 
838 void *memmove(void *dest, const void *src, size_t n);
839 void testMemmove(char *dst, size_t n) {
840   char src[10];
841   scanf("%9s", src);
842 
843   char *result = memmove(dst, src, n);
844 
845   clang_analyzer_isTainted_char(*dst); // expected-warning {{YES}}
846   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
847 }
848 
849 void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
850 void testMemmem(const void *needle, size_t needlelen) {
851   char haystack[10];
852   scanf("%9s", haystack);
853 
854   char *result = memmem(haystack, 9, needle, needlelen);
855   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
856 }
857 
858 char *strstr(const char *haystack, const char *needle);
859 void testStrstr(const char *needle) {
860   char haystack[10];
861   scanf("%9s", haystack);
862 
863   char *result = strstr(haystack, needle);
864   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
865 }
866 
867 char *strcasestr(const char *haystack, const char *needle);
868 void testStrcasestr(const char *needle) {
869   char haystack[10];
870   scanf("%9s", haystack);
871 
872   char *result = strcasestr(haystack, needle);
873   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
874 }
875 
876 char *strchrnul(const char *s, int c);
877 void testStrchrnul() {
878   char s[10];
879   scanf("%9s", s);
880 
881   char *result = strchrnul(s, 9);
882   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
883 }
884 
885 char *index(const char *s, int c);
886 void testIndex() {
887   char s[10];
888   scanf("%9s", s);
889 
890   char *result = index(s, 9);
891   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
892 }
893 
894 char *rindex(const char *s, int c);
895 void testRindex() {
896   char s[10];
897   scanf("%9s", s);
898 
899   char *result = rindex(s, 9);
900   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
901 }
902 
903 int strcmp(const char *s1, const char *s2);
904 void testStrcmpWithLHSTainted(char *rhs) {
905   char lhs[10];
906   scanf("%9s", lhs);
907 
908   int cmp_result = strcmp(lhs, rhs);
909   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
910 }
911 
912 void testStrcmpWithRHSTainted(char *lhs) {
913   char rhs[10];
914   scanf("%9s", rhs);
915 
916   int cmp_result = strcmp(lhs, rhs);
917   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
918 }
919 int strcasecmp(const char *s1, const char *s2);
920 void testStrcasecmpWithLHSTainted(char *rhs) {
921   char lhs[10];
922   scanf("%9s", lhs);
923 
924   int cmp_result = strcasecmp(lhs, rhs);
925   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
926 }
927 
928 void testStrcasecmpWithRHSTainted(char *lhs) {
929   char rhs[10];
930   scanf("%9s", rhs);
931 
932   int cmp_result = strcasecmp(lhs, rhs);
933   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
934 }
935 int strncmp(const char *s1, const char *s2, size_t n);
936 void testStrncmpWithLHSTainted(char *rhs, size_t n) {
937   char lhs[10];
938   scanf("%9s", lhs);
939 
940   int cmp_result = strncmp(lhs, rhs, n);
941   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
942 }
943 
944 void testStrncmpWithRHSTainted(char *lhs, size_t n) {
945   char rhs[10];
946   scanf("%9s", rhs);
947 
948   int cmp_result = strncmp(lhs, rhs, n);
949   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
950 }
951 
952 void testStrncmpWithNTainted(char *lhs, char *rhs) {
953   int n;
954   scanf("%d", &n);
955 
956   int cmp_result = strncmp(lhs, rhs, n);
957   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
958 }
959 
960 int strncasecmp(const char *s1, const char *s2, size_t n);
961 void testStrncasecmpWithLHSTainted(char *rhs, size_t n) {
962   char lhs[10];
963   scanf("%9s", lhs);
964 
965   int cmp_result = strncmp(lhs, rhs, n);
966   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
967 }
968 
969 void testStrncasecmpWithRHSTainted(char *lhs, size_t n) {
970   char rhs[10];
971   scanf("%9s", rhs);
972 
973   int cmp_result = strncmp(lhs, rhs, n);
974   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
975 }
976 
977 void testStrncasecmpWithNTainted(char *lhs, char *rhs) {
978   int n;
979   scanf("%d", &n);
980 
981   int cmp_result = strncmp(lhs, rhs, n);
982   clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
983 }
984 
985 size_t strspn(const char *s, const char *accept);
986 void testStrspnFirstArgTainted(const char *accept) {
987   char s[10];
988   scanf("%9s", s);
989 
990   size_t result = strspn(s, accept);
991   clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
992 }
993 
994 void testStrspnSecondArgTainted(const char *s) {
995   char accept[10];
996   scanf("%9s", accept);
997 
998   size_t result = strspn(s, accept);
999   clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
1000 }
1001 
1002 size_t strcspn(const char *s, const char *reject);
1003 void testStrcspnFirstArgTainted(const char *reject) {
1004   char s[10];
1005   scanf("%9s", s);
1006 
1007   size_t result = strcspn(s, reject);
1008   clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
1009 }
1010 
1011 void testStrcspnSecondArgTainted(const char *s) {
1012   char reject[10];
1013   scanf("%9s", reject);
1014 
1015   size_t result = strcspn(s, reject);
1016   clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
1017 }
1018 
1019 char *strpbrk(const char *s, const char *accept);
1020 void testStrpbrk(const char *accept) {
1021   char s[10];
1022   scanf("%9s", s);
1023 
1024   char *result = strpbrk(s, accept);
1025   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
1026 }
1027 
1028 char *strndup(const char *s, size_t n);
1029 void testStrndup(size_t n) {
1030   char s[10];
1031   scanf("%9s", s);
1032 
1033   char *result = strndup(s, n);
1034   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
1035 }
1036 
1037 char *strdupa(const char *s);
1038 void testStrdupa() {
1039   char s[10];
1040   scanf("%9s", s);
1041 
1042   char *result = strdupa(s);
1043   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
1044 }
1045 
1046 char *strndupa(const char *s, size_t n);
1047 void testStrndupa(size_t n) {
1048   char s[10];
1049   scanf("%9s", s);
1050 
1051   char *result = strndupa(s, n);
1052   clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
1053 }
1054 
1055 size_t strlen(const char *s);
1056 void testStrlen_dont_propagate() {
1057   // strlen, wcslen, strnlen and alike intentionally don't propagate taint.
1058   // See the details here: https://github.com/llvm/llvm-project/pull/66086
1059   // This isn't ideal, but this is only what we have now.
1060   char s[10];
1061   scanf("%9s", s);
1062 
1063   size_t result = strlen(s);
1064   // strlen propagating taint would bring in many false positives
1065   clang_analyzer_isTainted_int(result); // expected-warning {{NO}}
1066 }
1067 
1068 size_t strnlen(const char *s, size_t maxlen);
1069 void testStrnlen_dont_propagate(size_t maxlen) {
1070   // strlen, wcslen, strnlen and alike intentionally don't propagate taint.
1071   // See the details here: https://github.com/llvm/llvm-project/pull/66086
1072   // This isn't ideal, but this is only what we have now.
1073   char s[10];
1074   scanf("%9s", s);
1075   size_t result = strnlen(s, maxlen);
1076   clang_analyzer_isTainted_int(result); // expected-warning {{NO}}
1077 }
1078 
1079 long strtol(const char *restrict nptr, char **restrict endptr, int base);
1080 long long strtoll(const char *restrict nptr, char **restrict endptr, int base);
1081 unsigned long int strtoul(const char *nptr, char **endptr, int base);
1082 unsigned long long int strtoull(const char *nptr, char **endptr, int base);
1083 void testStrtolVariants(char **restrict endptr, int base) {
1084   char s[10];
1085   scanf("%9s", s);
1086 
1087   long result_l = strtol(s, endptr, base);
1088   clang_analyzer_isTainted_int(result_l); // expected-warning {{YES}}
1089 
1090   long long result_ll = strtoll(s, endptr, base);
1091   clang_analyzer_isTainted_int(result_ll); // expected-warning {{YES}}
1092 
1093   unsigned long result_ul = strtoul(s, endptr, base);
1094   clang_analyzer_isTainted_int(result_ul); // expected-warning {{YES}}
1095 
1096   unsigned long long result_ull = strtoull(s, endptr, base);
1097   clang_analyzer_isTainted_int(result_ull); // expected-warning {{YES}}
1098 }
1099 
1100 int isalnum(int c);
1101 int isalpha(int c);
1102 int isascii(int c);
1103 int isblank(int c);
1104 int iscntrl(int c);
1105 int isdigit(int c);
1106 int isgraph(int c);
1107 int islower(int c);
1108 int isprint(int c);
1109 int ispunct(int c);
1110 int isspace(int c);
1111 int isupper(int c);
1112 int isxdigit(int c);
1113 
1114 void testIsFunctions() {
1115   char c;
1116   scanf("%c", &c);
1117 
1118   int alnum = isalnum(c);
1119   clang_analyzer_isTainted_int(alnum); // expected-warning {{YES}}
1120 
1121   int alpha = isalpha(c);
1122   clang_analyzer_isTainted_int(alpha); // expected-warning {{YES}}
1123 
1124   int ascii = isascii(c);
1125   clang_analyzer_isTainted_int(ascii); // expected-warning {{YES}}
1126 
1127   int blank = isblank(c);
1128   clang_analyzer_isTainted_int(blank); // expected-warning {{YES}}
1129 
1130   int cntrl = iscntrl(c);
1131   clang_analyzer_isTainted_int(cntrl); // expected-warning {{YES}}
1132 
1133   int digit = isdigit(c);
1134   clang_analyzer_isTainted_int(digit); // expected-warning {{YES}}
1135 
1136   int graph = isgraph(c);
1137   clang_analyzer_isTainted_int(graph); // expected-warning {{YES}}
1138 
1139   int lower = islower(c);
1140   clang_analyzer_isTainted_int(lower); // expected-warning {{YES}}
1141 
1142   int print = isprint(c);
1143   clang_analyzer_isTainted_int(print); // expected-warning {{YES}}
1144 
1145   int punct = ispunct(c);
1146   clang_analyzer_isTainted_int(punct); // expected-warning {{YES}}
1147 
1148   int space = isspace(c);
1149   clang_analyzer_isTainted_int(space); // expected-warning {{YES}}
1150 
1151   int upper = isupper(c);
1152   clang_analyzer_isTainted_int(upper); // expected-warning {{YES}}
1153 
1154   int xdigit = isxdigit(c);
1155   clang_analyzer_isTainted_int(xdigit); // expected-warning {{YES}}
1156 }
1157 
1158 void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
1159 void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg);
1160 void testQsort() {
1161   int data[1];
1162   scanf("%d", data);
1163 
1164   qsort(data, sizeof(data), sizeof(data[0]), NULL);
1165   clang_analyzer_isTainted_int(data[0]); // expected-warning {{YES}}
1166   qsort_r(data, sizeof(data), sizeof(data[0]), NULL, NULL);
1167   clang_analyzer_isTainted_int(data[0]); // expected-warning {{YES}}
1168 }
1169 
1170 // Test configuration
1171 int mySource1(void);
1172 void mySource2(int*);
1173 void myScanf(const char*, ...);
1174 int myPropagator(int, int*);
1175 int mySnprintf(char*, size_t, const char*, ...);
1176 bool isOutOfRange(const int*); // const filter function
1177 void sanitizeCmd(char*); // non-const filter function
1178 void mySink(int, int, int);
1179 
1180 void testConfigurationSources1(void) {
1181   int x = mySource1();
1182   Buffer[x] = 1; // expected-warning {{Potential out of bound access }}
1183 }
1184 
1185 void testConfigurationSources2(void) {
1186   int x;
1187   mySource2(&x);
1188   Buffer[x] = 1; // expected-warning {{Potential out of bound access }}
1189 }
1190 
1191 void testConfigurationSources3(void) {
1192   int x, y;
1193   myScanf("%d %d", &x, &y);
1194   Buffer[y] = 1; // expected-warning {{Potential out of bound access }}
1195 }
1196 
1197 void testConfigurationPropagation(void) {
1198   int x = mySource1();
1199   int y;
1200   myPropagator(x, &y);
1201   Buffer[y] = 1; // expected-warning {{Potential out of bound access }}
1202 }
1203 
1204 void testConfigurationFilter(void) {
1205   int x = mySource1();
1206   if (isOutOfRange(&x)) // the filter function
1207     return;
1208   Buffer[x] = 1; // no-warning
1209 }
1210 
1211 void testConfigurationFilterNonConst(void) {
1212   char buffer[1000];
1213   myScanf("%s", buffer); // makes buffer tainted
1214   system(buffer); // expected-warning {{Untrusted data is passed to a system call}}
1215 }
1216 
1217 void testConfigurationFilterNonConst2(void) {
1218   char buffer[1000];
1219   myScanf("%s", buffer); // makes buffer tainted
1220   sanitizeCmd(buffer); // removes taintedness
1221   system(buffer); // no-warning
1222 }
1223 
1224 void testConfigurationSinks(void) {
1225   int x = mySource1();
1226   mySink(x, 1, 2);
1227   // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
1228   mySink(1, x, 2); // no-warning
1229   mySink(1, 2, x);
1230   // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
1231 }
1232 
1233 int test_exec_like_functions() {
1234   char buf[100] = {0};
1235   scanf("%99s", buf);
1236   clang_analyzer_isTainted_char(buf[0]); // expected-warning {{YES}}
1237 
1238   char *cleanArray[] = {"ENV1=V1", "ENV2=V2", NULL};
1239   char *taintedArray[] = {buf, "ENV2=V2", NULL};
1240   clang_analyzer_isTainted_char(taintedArray[0][0]);      // expected-warning {{YES}}
1241   clang_analyzer_isTainted_char(*(char*)taintedArray[0]); // expected-warning {{YES}}
1242   clang_analyzer_isTainted_char(*(char*)taintedArray);    // expected-warning {{NO}}  We should have YES here.
1243   // FIXME: Above the triple pointer indirection will confuse the checker,
1244   // as we only check two levels. The results would be worse, if the tainted
1245   // subobject ("buf") would not be at the beginning of the enclosing object,
1246   // for the same reason.
1247 
1248   switch (coin()) {
1249     default: break;
1250     // Execute `path` with all arguments after `path` until a NULL pointer
1251     // and environment from `environ'.
1252     case 0: return execl("path", "arg0", "arg1", "arg2", NULL); // no-warning
1253     case 1: return execl(buf, "arg0", "arg1", "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1254     case 2: return execl("path", buf, "arg1", "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1255     case 3: return execl("path", "arg0", buf, "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1256     case 4: return execl("path", "arg0", "arg1", buf, NULL); // expected-warning {{Untrusted data is passed to a system call}}
1257   }
1258 
1259   switch (coin()) {
1260     default: break;
1261     // Execute `path` with all arguments after `PATH` until a NULL pointer,
1262     // and the argument after that for environment.
1263     case 0: return execle("path", "arg0", "arg1", NULL,   cleanArray); // no-warning
1264     case 1: return execle(   buf, "arg0", "arg1", NULL,   cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1265     case 2: return execle("path",    buf, "arg1", NULL,   cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1266     case 3: return execle("path", "arg0",    buf, NULL,   cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1267     case 4: return execle("path", "arg0", "arg1", NULL,          buf); // expected-warning {{Untrusted data is passed to a system call}}
1268     case 5: return execle("path", "arg0", "arg1", NULL, taintedArray); // FIXME: We might wanna have a report here.
1269   }
1270 
1271   switch (coin()) {
1272     default: break;
1273     // Execute `file`, searching in the `PATH' environment variable if it
1274     // contains no slashes, with all arguments after `file` until a NULL
1275     // pointer and environment from `environ'.
1276     case 0: return execlp("file", "arg0", "arg1", "arg2", NULL); // no-warning
1277     case 1: return execlp(   buf, "arg0", "arg1", "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1278     case 2: return execlp("file",    buf, "arg1", "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1279     case 3: return execlp("file", "arg0",    buf, "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1280     case 4: return execlp("file", "arg0", "arg1",    buf, NULL); // expected-warning {{Untrusted data is passed to a system call}}
1281   }
1282 
1283   switch (coin()) {
1284     default: break;
1285     // Execute `path` with arguments `ARGV` and environment from `environ'.
1286     case 0: return execv("path", /*argv=*/  cleanArray); // no-warning
1287     case 1: return execv(   buf, /*argv=*/  cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1288     case 2: return execv("path", /*argv=*/taintedArray); // FIXME: We might wanna have a report here.
1289   }
1290 
1291   switch (coin()) {
1292     default: break;
1293     // Replace the current process, executing `path` with arguments `ARGV`
1294     // and environment `ENVP`. `ARGV` and `ENVP` are terminated by NULL pointers.
1295     case 0: return execve("path", /*argv=*/  cleanArray, /*envp=*/cleanArray); // no-warning
1296     case 1: return execve(   buf, /*argv=*/  cleanArray, /*envp=*/cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1297     case 2: return execve("path", /*argv=*/taintedArray, /*envp=*/cleanArray); // FIXME: We might wanna have a report here.
1298     case 3: return execve("path", /*argv=*/cleanArray, /*envp=*/taintedArray); // FIXME: We might wanna have a report here.
1299   }
1300 
1301   switch (coin()) {
1302     default: break;
1303     // Execute `file`, searching in the `PATH' environment variable if it
1304     // contains no slashes, with arguments `ARGV` and environment from `environ'.
1305     case 0: return execvp("file", /*argv=*/  cleanArray); // no-warning
1306     case 1: return execvp(   buf, /*argv=*/  cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1307     case 2: return execvp("file", /*argv=*/taintedArray); // FIXME: We might wanna have a report here.
1308   }
1309 
1310   // execvpe
1311   switch (coin()) {
1312     default: break;
1313     // Execute `file`, searching in the `PATH' environment variable if it
1314     // contains no slashes, with arguments `ARGV` and environment `ENVP`.
1315     // `ARGV` and `ENVP` are terminated by NULL pointers.
1316     case 0: return execvpe("file", /*argv=*/  cleanArray, /*envp=*/  cleanArray); // no-warning
1317     case 1: return execvpe(   buf, /*argv=*/  cleanArray, /*envp=*/  cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1318     case 2: return execvpe("file", /*argv=*/taintedArray, /*envp=*/  cleanArray); // FIXME: We might wanna have a report here.
1319     case 3: return execvpe("file", /*argv=*/  cleanArray, /*envp=*/taintedArray); // FIXME: We might wanna have a report here.
1320   }
1321 
1322   int cleanFD = coin();
1323   int taintedFD;
1324   scanf("%d", &taintedFD);
1325   clang_analyzer_isTainted_int(taintedFD); // expected-warning {{YES}}
1326 
1327   switch (coin()) {
1328     default: break;
1329     // Execute the file `FD` refers to, overlaying the running program image.
1330     // `ARGV` and `ENVP` are passed to the new program, as for `execve'.
1331     case 0: return fexecve(  cleanFD, /*argv=*/  cleanArray, /*envp=*/  cleanArray); // no-warning
1332     case 1: return fexecve(taintedFD, /*argv=*/  cleanArray, /*envp=*/  cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1333     case 2: return fexecve(  cleanFD, /*argv=*/taintedArray, /*envp=*/  cleanArray); // FIXME: We might wanna have a report here.
1334     case 3: return fexecve(  cleanFD, /*argv=*/  cleanArray, /*envp=*/taintedArray); // FIXME: We might wanna have a report here.
1335   }
1336 
1337   switch (coin()) {
1338     default: break;
1339     // Create a new stream connected to a pipe running the given `command`.
1340     case 0: return pclose(popen("command", /*mode=*/"r")); // no-warning
1341     case 1: return pclose(popen(      buf, /*mode=*/"r")); // expected-warning {{Untrusted data is passed to a system call}}
1342     case 2: return pclose(popen("command", /*mode=*/buf)); // 'mode' is not a taint sink.
1343   }
1344 
1345   switch (coin()) {
1346     default: break;
1347     // Execute the given line as a shell command.
1348     case 0: return system("command"); // no-warning
1349     case 1: return system(      buf); // expected-warning {{Untrusted data is passed to a system call}}
1350   }
1351 
1352   return 0;
1353 }
1354 
1355 void testUnknownFunction(void (*foo)(void)) {
1356   foo(); // no-crash
1357 }
1358 
1359 void testProctitleFalseNegative(void) {
1360   char flag[80];
1361   fscanf(stdin, "%79s", flag);
1362   char *argv[] = {"myapp", flag};
1363   // FIXME: We should have a warning below: Untrusted data passed to sink.
1364   setproctitle_init(1, argv, 0);
1365 }
1366 
1367 void testProctitle2(char *real_argv[]) {
1368   char *app = getenv("APP_NAME");
1369   if (!app)
1370     return;
1371   char *argv[] = {app, "--foobar"};
1372   setproctitle_init(1, argv, 0);         // expected-warning {{Untrusted data is passed to a user-defined sink}}
1373   setproctitle_init(1, real_argv, argv); // expected-warning {{Untrusted data is passed to a user-defined sink}}
1374 }
1375 
1376 void testAcceptPropagates() {
1377   int listenSocket = socket(2, 1, 6);
1378   clang_analyzer_isTainted_int(listenSocket); // expected-warning {{YES}}
1379   int acceptSocket = accept(listenSocket, 0, 0);
1380   clang_analyzer_isTainted_int(acceptSocket); // expected-warning {{YES}}
1381 }
1382