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);
66 int scanf(const char *restrict format
, ...);
67 char *gets(char *str
);
68 char *gets_s(char *str
, rsize_t n
);
71 typedef struct _FILE
FILE;
73 extern struct _FILE
*stdin
;
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
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
;
158 unsigned short sa_family
;
165 void bufferScanfDirect(void)
169 Buffer
[n
] = 1; // expected-warning {{Potential out of bound access }}
172 void bufferScanfArithmetic1(int x
) {
176 Buffer
[m
] = 1; // expected-warning {{Potential out of bound access }}
179 void bufferScanfArithmetic2(int x
) {
182 int m
= 100 - (n
+ 3) * x
;
183 Buffer
[m
] = 1; // expected-warning {{Potential out of bound access }}
186 void bufferScanfAssignment(int x
) {
192 Buffer
[m
] = 1; // expected-warning {{Potential out of bound access }}
196 void scanfArg(void) {
198 scanf("%d", t
); // expected-warning {{format specifies type 'int *' but the argument has type 'int'}}
201 void bufferGetchar(int x
) {
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.
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:
222 return isdigit(c
); //no-warning
225 // Some later tests use isdigit as a function, so we need to undef it:
228 void testUncontrolledFormatString(char **p
) {
230 fscanf(stdin
, "%s", s
);
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.
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}}
245 setproctitle(spcpy
, 3); // expected-warning {{Uncontrolled Format String}}
248 spcpyret
= stpcpy(spcpy
, s
);
249 setproctitle(spcpyret
, 3); // expected-warning {{Uncontrolled Format String}}
252 strncpy(sncpy
, s
, 20);
253 setproctitle(sncpy
, 3); // expected-warning {{Uncontrolled Format String}}
256 dup
= strndup(s
, 20);
257 setproctitle(dup
, 3); // expected-warning {{Uncontrolled Format String}}
261 void testTaintSystemCall(void) {
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.
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) {
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) {
294 system(str
); // expected-warning {{Untrusted data is passed to a system call}}
297 void testGets_s(void) {
300 system(str
); // expected-warning {{Untrusted data is passed to a system call}}
303 void testTaintedBufferSize(void) {
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
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).
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) {
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) {
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) {
367 char dstbuf
[16], srcbuf
[16];
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) {
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) {
404 return 5/x
; // expected-warning {{Division by a tainted value, possibly zero}}
407 int testTaintedDivFP(void) {
412 return 5/x
; // x cannot be 0, so no tainted warning either
416 void testTaintedVLASize(void) {
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) {
428 int vla
[x
]; // no-warning
431 int testTaintedAllocaMem() {
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() {
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
) {
457 a
= b
= c
= 0x9899e3 + l
;
463 a
+= (arr
[3] + ((unsigned) arr
[2] << 8) + ((unsigned) arr
[1] << 16) + ((unsigned) arr
[0] << 24));
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
) {
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.
484 clang_analyzer_dump_int(tmp
); // expected-warning{{((((conj_}} symbol complexity: 8
485 clang_analyzer_isTainted_int(tmp
); // expected-warning{{YES}}
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
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.
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
) {
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
) {
528 // This comparison used to hit an assertion in the constraint manager,
529 // which didn't handle NonLoc sym-sym comparisons.
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
) {
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}}
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}}
566 clang_analyzer_isTainted_int(m
); // expected-warning {{NO}}
569 int scanf_s(const char *format
, ...);
570 int testScanf_s_(int *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}}
645 int getgroups(int size
, gid_t list
[]);
646 int testGetgroups(int size
, gid_t list
[], bool flag
) {
647 int result
= getgroups(size
, list
);
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);
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
) {
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
) {
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
);
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
) {
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
);
734 char *name
= dirname(buf
);
735 clang_analyzer_isTainted_charp(name
); // expected-warning {{YES}}
738 char *basename(char *path
);
739 void testBasename() {
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
) {
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
) {
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
) {
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
) {
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
) {
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
);
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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() {
881 char *result
= strchrnul(s
, 9);
882 clang_analyzer_isTainted_charp(result
); // expected-warning {{YES}}
885 char *index(const char *s
, int c
);
890 char *result
= index(s
, 9);
891 clang_analyzer_isTainted_charp(result
); // expected-warning {{YES}}
894 char *rindex(const char *s
, int c
);
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
) {
908 int cmp_result
= strcmp(lhs
, rhs
);
909 clang_analyzer_isTainted_int(cmp_result
); // expected-warning {{YES}}
912 void testStrcmpWithRHSTainted(char *lhs
) {
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
) {
924 int cmp_result
= strcasecmp(lhs
, rhs
);
925 clang_analyzer_isTainted_int(cmp_result
); // expected-warning {{YES}}
928 void testStrcasecmpWithRHSTainted(char *lhs
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
990 size_t result
= strspn(s
, accept
);
991 clang_analyzer_isTainted_int(result
); // expected-warning {{YES}}
994 void testStrspnSecondArgTainted(const char *s
) {
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
) {
1007 size_t result
= strcspn(s
, reject
);
1008 clang_analyzer_isTainted_int(result
); // expected-warning {{YES}}
1011 void testStrcspnSecondArgTainted(const char *s
) {
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
) {
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
) {
1033 char *result
= strndup(s
, n
);
1034 clang_analyzer_isTainted_charp(result
); // expected-warning {{YES}}
1037 char *strdupa(const char *s
);
1038 void testStrdupa() {
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
) {
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.
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.
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
) {
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}}
1112 int isxdigit(int c
);
1114 void testIsFunctions() {
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
);
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) {
1188 Buffer
[x
] = 1; // expected-warning {{Potential out of bound access }}
1191 void testConfigurationSources3(void) {
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();
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
1208 Buffer
[x
] = 1; // no-warning
1211 void testConfigurationFilterNonConst(void) {
1213 myScanf("%s", buffer
); // makes buffer tainted
1214 system(buffer
); // expected-warning {{Untrusted data is passed to a system call}}
1217 void testConfigurationFilterNonConst2(void) {
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();
1227 // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
1228 mySink(1, x
, 2); // no-warning
1230 // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
1233 int test_exec_like_functions() {
1234 char buf
[100] = {0};
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.
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}}
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.
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}}
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.
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.
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.
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();
1324 scanf("%d", &taintedFD
);
1325 clang_analyzer_isTainted_int(taintedFD
); // expected-warning {{YES}}
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.
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.
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}}
1355 void testUnknownFunction(void (*foo
)(void)) {
1359 void testProctitleFalseNegative(void) {
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");
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}}