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