[ELF] Reorder SectionBase/InputSectionBase members
[llvm-project.git] / clang / test / Analysis / taint-generic.c
blobad5a99fe8b3a35b0e707715cdbb536c48ef4d4b6
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
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
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
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'
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
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]]
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
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
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);
64 int coin();
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);
71 typedef struct _FILE FILE;
72 #ifdef FILE_IS_STRUCT
73 extern struct _FILE *stdin;
74 #else
75 extern FILE *stdin;
76 #endif
78 #define bool _Bool
79 #define NULL (void*)0
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, ...);
92 char *getenv(const char *name);
94 FILE *fopen(const char *name, const char *mode);
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[]);
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))
108 static char *__inline_strcpy_chk (char *dest, const char *src) {
109 return __builtin___strcpy_chk(dest, src, __builtin_object_size(dest, 1));
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);
116 void *malloc(size_t);
117 void *calloc(size_t nmemb, size_t size);
118 void bcopy(void *s1, void *s2, size_t n);
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
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
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);
155 typedef size_t socklen_t;
157 struct sockaddr {
158 unsigned short sa_family;
159 char sa_data[14];
162 #define BUFSIZE 10
164 int Buffer[BUFSIZE];
165 void bufferScanfDirect(void)
167 int n;
168 scanf("%d", &n);
169 Buffer[n] = 1; // expected-warning {{Potential out of bound access }}
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 }}
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 }}
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 }}
196 void scanfArg(void) {
197 int t = 0;
198 scanf("%d", t); // expected-warning {{format specifies type 'int *' but the argument has type 'int'}}
201 void bufferGetchar(int x) {
202 int m = getchar();
203 Buffer[m] = 1; //expected-warning {{Potential out of bound access}}
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)
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}}
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
225 // Some later tests use isdigit as a function, so we need to undef it:
226 #undef isdigit
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}}
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}}
240 stpcpy(*(++p), s); // this generates __inline.
241 setproctitle(*(p), 3); // expected-warning {{Uncontrolled Format String}}
243 char spcpy[80];
244 stpcpy(spcpy, s);
245 setproctitle(spcpy, 3); // expected-warning {{Uncontrolled Format String}}
247 char *spcpyret;
248 spcpyret = stpcpy(spcpy, s);
249 setproctitle(spcpyret, 3); // expected-warning {{Uncontrolled Format String}}
251 char sncpy[80];
252 strncpy(sncpy, s, 20);
253 setproctitle(sncpy, 3); // expected-warning {{Uncontrolled Format String}}
255 char *dup;
256 dup = strndup(s, 20);
257 setproctitle(dup, 3); // expected-warning {{Uncontrolled Format String}}
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}}
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}}
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}}
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}}
291 void testGets(void) {
292 char str[50];
293 gets(str);
294 system(str); // expected-warning {{Untrusted data is passed to a system call}}
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}}
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)
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
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);
330 void testSocket(void) {
331 int sock;
332 char buffer[100];
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}}
338 sock = socket(AF_LOCAL, SOCK_STREAM, 0);
339 read(sock, buffer, 100);
340 execl(buffer, "filename", 0); // no-warning
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}}
348 void testStruct(void) {
349 struct {
350 char buf[16];
351 int length;
352 } tainted;
354 char buffer[16];
355 int sock;
357 sock = socket(AF_INET, SOCK_STREAM, 0);
358 read(sock, &tainted, sizeof(tainted));
359 clang_analyzer_isTainted_int(tainted.length); // expected-warning {{YES }}
362 void testStructArray(void) {
363 struct {
364 int length;
365 } tainted[4];
367 char dstbuf[16], srcbuf[16];
368 int sock;
370 sock = socket(AF_INET, SOCK_STREAM, 0);
371 __builtin_memset(srcbuf, 0, sizeof(srcbuf));
373 read(sock, &tainted[0], sizeof(tainted));
374 clang_analyzer_isTainted_int(tainted[0].length); // expected-warning {{YES}}
376 __builtin_memset(&tainted, 0, sizeof(tainted));
377 read(sock, &tainted, sizeof(tainted));
378 clang_analyzer_isTainted_int(tainted[0].length); // expected-warning {{YES}}
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}}
387 void testUnion(void) {
388 union {
389 int x;
390 char y[4];
391 } tainted;
393 char buffer[4];
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);
401 int testDivByZero(void) {
402 int x;
403 scanf("%d", &x);
404 return 5/x; // expected-warning {{Division by a tainted value, possibly zero}}
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
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}}
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
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}}
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}}
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; }
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;
467 return 5/a; // FIXME: Should be a "div by tainted" warning here.
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);
475 // Make "tmp" tainted.
476 int tmp = tainted + tainted;
477 clang_analyzer_isTainted_int(tmp); // expected-warning{{YES}}
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}}
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
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];
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".
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}}
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}}
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
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
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}}
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.
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}}
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}}
565 int m = wcslen(dst);
566 clang_analyzer_isTainted_int(m); // expected-warning {{NO}}
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}}
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}}
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}}
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}}
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}}
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}}
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}}
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}}
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);
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}}
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}}
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}}
651 return 1 / (result + 1); // expected-warning {{Division by a tainted value, possibly zero}}
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}}
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}}
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}}
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);
678 clang_analyzer_isTainted_int(*buffer); // expected-warning {{YES}}
679 clang_analyzer_isTainted_int(read); // expected-warning {{YES}}
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);
687 void testRecv(int *buf, size_t len, int flags) {
688 int fd;
689 scanf("%d", &fd); // fake a tainted a file descriptor
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}}
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
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}}
710 char *ttyname(int fd);
711 void testTtyname() {
712 int fd;
713 scanf("%d", &fd); // fake a tainted a file descriptor
715 char *name = ttyname(fd);
716 clang_analyzer_isTainted_charp(name); // expected-warning {{YES}}
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
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}}
729 char *dirname(char *path);
730 void testDirname() {
731 char buf[10];
732 scanf("%9s", buf);
734 char *name = dirname(buf);
735 clang_analyzer_isTainted_charp(name); // expected-warning {{YES}}
738 char *basename(char *path);
739 void testBasename() {
740 char buf[10];
741 scanf("%9s", buf);
743 char *name = basename(buf);
744 clang_analyzer_isTainted_charp(name); // expected-warning {{YES}}
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);
752 int result = fnmatch(pattern, string, flags);
753 clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
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);
761 char *result = memchr(buf, c, n);
762 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
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);
770 char *result = memrchr(buf, c, n);
771 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
774 void *rawmemchr(const void *s, int c);
775 void testRawmemchr(int c) {
776 char buf[10];
777 scanf("%9s", buf);
779 char *result = rawmemchr(buf, c);
780 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
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);
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}}
793 int wctomb(char *s, wchar_t wc);
794 void testWctomb(char *buf) {
795 wchar_t wc = getchar();
797 int result = wctomb(buf, wc);
798 clang_analyzer_isTainted_char(*buf); // expected-warning {{YES}}
799 clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
802 int wcwidth(wchar_t c);
803 void testWcwidth() {
804 wchar_t wc = getchar();
806 int width = wcwidth(wc);
807 clang_analyzer_isTainted_int(width); // expected-warning {{YES}}
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);
815 int cmp_result = memcmp(lhs, rhs, n);
816 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
819 void testMemcmpWithRHSTainted(size_t n, char *lhs) {
820 char rhs[10];
821 scanf("%9s", rhs);
823 int cmp_result = memcmp(lhs, rhs, n);
824 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
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);
832 char *result = memcpy(dst, src, n);
834 clang_analyzer_isTainted_char(*dst); // expected-warning {{YES}}
835 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
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);
843 char *result = memmove(dst, src, n);
845 clang_analyzer_isTainted_char(*dst); // expected-warning {{YES}}
846 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
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);
854 char *result = memmem(haystack, 9, needle, needlelen);
855 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
858 char *strstr(const char *haystack, const char *needle);
859 void testStrstr(const char *needle) {
860 char haystack[10];
861 scanf("%9s", haystack);
863 char *result = strstr(haystack, needle);
864 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
867 char *strcasestr(const char *haystack, const char *needle);
868 void testStrcasestr(const char *needle) {
869 char haystack[10];
870 scanf("%9s", haystack);
872 char *result = strcasestr(haystack, needle);
873 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
876 char *strchrnul(const char *s, int c);
877 void testStrchrnul() {
878 char s[10];
879 scanf("%9s", s);
881 char *result = strchrnul(s, 9);
882 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
885 char *index(const char *s, int c);
886 void testIndex() {
887 char s[10];
888 scanf("%9s", s);
890 char *result = index(s, 9);
891 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
894 char *rindex(const char *s, int c);
895 void testRindex() {
896 char s[10];
897 scanf("%9s", s);
899 char *result = rindex(s, 9);
900 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
903 int strcmp(const char *s1, const char *s2);
904 void testStrcmpWithLHSTainted(char *rhs) {
905 char lhs[10];
906 scanf("%9s", lhs);
908 int cmp_result = strcmp(lhs, rhs);
909 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
912 void testStrcmpWithRHSTainted(char *lhs) {
913 char rhs[10];
914 scanf("%9s", rhs);
916 int cmp_result = strcmp(lhs, rhs);
917 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
919 int strcasecmp(const char *s1, const char *s2);
920 void testStrcasecmpWithLHSTainted(char *rhs) {
921 char lhs[10];
922 scanf("%9s", lhs);
924 int cmp_result = strcasecmp(lhs, rhs);
925 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
928 void testStrcasecmpWithRHSTainted(char *lhs) {
929 char rhs[10];
930 scanf("%9s", rhs);
932 int cmp_result = strcasecmp(lhs, rhs);
933 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
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);
940 int cmp_result = strncmp(lhs, rhs, n);
941 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
944 void testStrncmpWithRHSTainted(char *lhs, size_t n) {
945 char rhs[10];
946 scanf("%9s", rhs);
948 int cmp_result = strncmp(lhs, rhs, n);
949 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
952 void testStrncmpWithNTainted(char *lhs, char *rhs) {
953 int n;
954 scanf("%d", &n);
956 int cmp_result = strncmp(lhs, rhs, n);
957 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
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);
965 int cmp_result = strncmp(lhs, rhs, n);
966 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
969 void testStrncasecmpWithRHSTainted(char *lhs, size_t n) {
970 char rhs[10];
971 scanf("%9s", rhs);
973 int cmp_result = strncmp(lhs, rhs, n);
974 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
977 void testStrncasecmpWithNTainted(char *lhs, char *rhs) {
978 int n;
979 scanf("%d", &n);
981 int cmp_result = strncmp(lhs, rhs, n);
982 clang_analyzer_isTainted_int(cmp_result); // expected-warning {{YES}}
985 size_t strspn(const char *s, const char *accept);
986 void testStrspnFirstArgTainted(const char *accept) {
987 char s[10];
988 scanf("%9s", s);
990 size_t result = strspn(s, accept);
991 clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
994 void testStrspnSecondArgTainted(const char *s) {
995 char accept[10];
996 scanf("%9s", accept);
998 size_t result = strspn(s, accept);
999 clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
1002 size_t strcspn(const char *s, const char *reject);
1003 void testStrcspnFirstArgTainted(const char *reject) {
1004 char s[10];
1005 scanf("%9s", s);
1007 size_t result = strcspn(s, reject);
1008 clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
1011 void testStrcspnSecondArgTainted(const char *s) {
1012 char reject[10];
1013 scanf("%9s", reject);
1015 size_t result = strcspn(s, reject);
1016 clang_analyzer_isTainted_int(result); // expected-warning {{YES}}
1019 char *strpbrk(const char *s, const char *accept);
1020 void testStrpbrk(const char *accept) {
1021 char s[10];
1022 scanf("%9s", s);
1024 char *result = strpbrk(s, accept);
1025 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
1028 char *strndup(const char *s, size_t n);
1029 void testStrndup(size_t n) {
1030 char s[10];
1031 scanf("%9s", s);
1033 char *result = strndup(s, n);
1034 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
1037 char *strdupa(const char *s);
1038 void testStrdupa() {
1039 char s[10];
1040 scanf("%9s", s);
1042 char *result = strdupa(s);
1043 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
1046 char *strndupa(const char *s, size_t n);
1047 void testStrndupa(size_t n) {
1048 char s[10];
1049 scanf("%9s", s);
1051 char *result = strndupa(s, n);
1052 clang_analyzer_isTainted_charp(result); // expected-warning {{YES}}
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);
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}}
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}}
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);
1087 long result_l = strtol(s, endptr, base);
1088 clang_analyzer_isTainted_int(result_l); // expected-warning {{YES}}
1090 long long result_ll = strtoll(s, endptr, base);
1091 clang_analyzer_isTainted_int(result_ll); // expected-warning {{YES}}
1093 unsigned long result_ul = strtoul(s, endptr, base);
1094 clang_analyzer_isTainted_int(result_ul); // expected-warning {{YES}}
1096 unsigned long long result_ull = strtoull(s, endptr, base);
1097 clang_analyzer_isTainted_int(result_ull); // expected-warning {{YES}}
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);
1114 void testIsFunctions() {
1115 char c;
1116 scanf("%c", &c);
1118 int alnum = isalnum(c);
1119 clang_analyzer_isTainted_int(alnum); // expected-warning {{YES}}
1121 int alpha = isalpha(c);
1122 clang_analyzer_isTainted_int(alpha); // expected-warning {{YES}}
1124 int ascii = isascii(c);
1125 clang_analyzer_isTainted_int(ascii); // expected-warning {{YES}}
1127 int blank = isblank(c);
1128 clang_analyzer_isTainted_int(blank); // expected-warning {{YES}}
1130 int cntrl = iscntrl(c);
1131 clang_analyzer_isTainted_int(cntrl); // expected-warning {{YES}}
1133 int digit = isdigit(c);
1134 clang_analyzer_isTainted_int(digit); // expected-warning {{YES}}
1136 int graph = isgraph(c);
1137 clang_analyzer_isTainted_int(graph); // expected-warning {{YES}}
1139 int lower = islower(c);
1140 clang_analyzer_isTainted_int(lower); // expected-warning {{YES}}
1142 int print = isprint(c);
1143 clang_analyzer_isTainted_int(print); // expected-warning {{YES}}
1145 int punct = ispunct(c);
1146 clang_analyzer_isTainted_int(punct); // expected-warning {{YES}}
1148 int space = isspace(c);
1149 clang_analyzer_isTainted_int(space); // expected-warning {{YES}}
1151 int upper = isupper(c);
1152 clang_analyzer_isTainted_int(upper); // expected-warning {{YES}}
1154 int xdigit = isxdigit(c);
1155 clang_analyzer_isTainted_int(xdigit); // expected-warning {{YES}}
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);
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}}
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);
1180 void testConfigurationSources1(void) {
1181 int x = mySource1();
1182 Buffer[x] = 1; // expected-warning {{Potential out of bound access }}
1185 void testConfigurationSources2(void) {
1186 int x;
1187 mySource2(&x);
1188 Buffer[x] = 1; // expected-warning {{Potential out of bound access }}
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 }}
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 }}
1204 void testConfigurationFilter(void) {
1205 int x = mySource1();
1206 if (isOutOfRange(&x)) // the filter function
1207 return;
1208 Buffer[x] = 1; // no-warning
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}}
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
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}}
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}}
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.
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}}
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.
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}}
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.
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.
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.
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.
1322 int cleanFD = coin();
1323 int taintedFD;
1324 scanf("%d", &taintedFD);
1325 clang_analyzer_isTainted_int(taintedFD); // expected-warning {{YES}}
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.
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.
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}}
1352 return 0;
1355 void testUnknownFunction(void (*foo)(void)) {
1356 foo(); // no-crash
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);
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}}
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}}