brintos

brintos / llvm-project-archived public Read only

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