1 // RUN: %clang_cc1 -Wno-int-to-pointer-cast -analyze -analyzer-checker=alpha.security.taint,debug.TaintTest %s -verify 2 3 #include <stdarg.h> 4 5 int scanf(const char *restrict format, ...); 6 int getchar(void); 7 typedef __typeof(sizeof(int)) size_t; 8 9 #define BUFSIZE 10 10 int Buffer[BUFSIZE]; 11 12 struct XYStruct { 13 int x; 14 int y; 15 char z; 16 }; 17 18 void taintTracking(int x) { 19 int n; 20 int *addr = &Buffer[0]; 21 scanf("%d", &n); 22 addr += n;// expected-warning + {{tainted}} 23 *addr = n; // expected-warning + {{tainted}} 24 25 double tdiv = n / 30; // expected-warning+ {{tainted}} 26 char *loc_cast = (char *) n; // expected-warning +{{tainted}} 27 char tinc = tdiv++; // expected-warning + {{tainted}} 28 int tincdec = (char)tinc--; // expected-warning+{{tainted}} 29 30 // Tainted ptr arithmetic/array element address. 31 int tprtarithmetic1 = *(addr+1); // expected-warning + {{tainted}} 32 33 // Dereference. 34 int *ptr; 35 scanf("%p", &ptr); 36 int ptrDeref = *ptr; // expected-warning + {{tainted}} 37 int _ptrDeref = ptrDeref + 13; // expected-warning + {{tainted}} 38 39 // Pointer arithmetic + dereferencing. 40 // FIXME: We fail to propagate the taint here because RegionStore does not 41 // handle ElementRegions with symbolic indexes. 42 int addrDeref = *addr; // expected-warning + {{tainted}} 43 int _addrDeref = addrDeref; // expected-warning + {{tainted}} 44 45 // Tainted struct address, casts. 46 struct XYStruct *xyPtr = 0; 47 scanf("%p", &xyPtr); 48 void *tXYStructPtr = xyPtr; // expected-warning + {{tainted}} 49 struct XYStruct *xyPtrCopy = tXYStructPtr; // expected-warning + {{tainted}} 50 int ptrtx = xyPtr->x;// expected-warning + {{tainted}} 51 int ptrty = xyPtr->y;// expected-warning + {{tainted}} 52 53 // Taint on fields of a struct. 54 struct XYStruct xy = {2, 3, 11}; 55 scanf("%d", &xy.y); 56 scanf("%d", &xy.x); 57 int tx = xy.x; // expected-warning + {{tainted}} 58 int ty = xy.y; // FIXME: This should be tainted as well. 59 char ntz = xy.z;// no warning 60 // Now, scanf scans both. 61 scanf("%d %d", &xy.y, &xy.x); 62 int ttx = xy.x; // expected-warning + {{tainted}} 63 int tty = xy.y; // expected-warning + {{tainted}} 64 } 65 66 void BitwiseOp(int in, char inn) { 67 // Taint on bitwise operations, integer to integer cast. 68 int m; 69 int x = 0; 70 scanf("%d", &x); 71 int y = (in << (x << in)) * 5;// expected-warning + {{tainted}} 72 // The next line tests integer to integer cast. 73 int z = y & inn; // expected-warning + {{tainted}} 74 if (y == 5) // expected-warning + {{tainted}} 75 m = z | z;// expected-warning + {{tainted}} 76 else 77 m = inn; 78 int mm = m; // expected-warning + {{tainted}} 79 } 80 81 // Test getenv. 82 char *getenv(const char *name); 83 void getenvTest(char *home) { 84 home = getenv("HOME"); // expected-warning + {{tainted}} 85 if (home != 0) { // expected-warning + {{tainted}} 86 char d = home[0]; // expected-warning + {{tainted}} 87 } 88 } 89 90 typedef struct _FILE FILE; 91 extern FILE *stdin; 92 extern FILE *stdout; 93 extern FILE *stderr; 94 int fscanf(FILE *restrict stream, const char *restrict format, ...); 95 int fprintf(FILE *stream, const char *format, ...); 96 int fclose(FILE *stream); 97 FILE *fopen(const char *path, const char *mode); 98 99 int fscanfTest(void) { 100 FILE *fp; 101 char s[80]; 102 int t; 103 104 // Check if stdin is treated as tainted. 105 fscanf(stdin, "%s %d", s, &t); 106 // Note, here, s is not tainted, but the data s points to is tainted. 107 char *ts = s; 108 char tss = s[0]; // expected-warning + {{tainted}} 109 int tt = t; // expected-warning + {{tainted}} 110 if((fp=fopen("test", "w")) == 0) // expected-warning + {{tainted}} 111 return 1; 112 fprintf(fp, "%s %d", s, t); // expected-warning + {{tainted}} 113 fclose(fp); // expected-warning + {{tainted}} 114 115 // Test fscanf and fopen. 116 if((fp=fopen("test","r")) == 0) // expected-warning + {{tainted}} 117 return 1; 118 fscanf(fp, "%s%d", s, &t); // expected-warning + {{tainted}} 119 fprintf(stdout, "%s %d", s, t); // expected-warning + {{tainted}} 120 return 0; 121 } 122 123 // Check if we propagate taint from stdin when it's used in an assignment. 124 void stdinTest1() { 125 int i; 126 fscanf(stdin, "%d", &i); 127 int j = i; // expected-warning + {{tainted}} 128 } 129 void stdinTest2(FILE *pIn) { 130 FILE *p = stdin; 131 FILE *pp = p; 132 int ii; 133 134 fscanf(pp, "%d", &ii); 135 int jj = ii;// expected-warning + {{tainted}} 136 137 fscanf(p, "%d", &ii); 138 int jj2 = ii;// expected-warning + {{tainted}} 139 140 ii = 3; 141 int jj3 = ii;// no warning 142 143 p = pIn; 144 fscanf(p, "%d", &ii); 145 int jj4 = ii;// no warning 146 } 147 148 void stdinTest3() { 149 FILE **ppp = &stdin; 150 int iii; 151 fscanf(*ppp, "%d", &iii); 152 int jjj = iii;// expected-warning + {{tainted}} 153 } 154 155 // Test that stdin does not get invalidated by calls. 156 void foo(); 157 void stdinTest4() { 158 int i; 159 fscanf(stdin, "%d", &i); 160 foo(); 161 int j = i; // expected-warning + {{tainted}} 162 } 163 164 int getw(FILE *); 165 void getwTest() { 166 int i = getw(stdin); // expected-warning + {{tainted}} 167 } 168 169 typedef long ssize_t; 170 ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict); 171 int printf(const char * __restrict, ...); 172 void free(void *ptr); 173 void getlineTest(void) { 174 FILE *fp; 175 char *line = 0; 176 size_t len = 0; 177 ssize_t read; 178 while ((read = getline(&line, &len, stdin)) != -1) { 179 printf("%s", line); // expected-warning + {{tainted}} 180 } 181 free(line); // expected-warning + {{tainted}} 182 } 183 184 // Test propagation functions - the ones that propagate taint from arguments to 185 // return value, ptr arguments. 186 187 int atoi(const char *nptr); 188 long atol(const char *nptr); 189 long long atoll(const char *nptr); 190 191 void atoiTest() { 192 char s[80]; 193 scanf("%s", s); 194 int d = atoi(s); // expected-warning + {{tainted}} 195 int td = d; // expected-warning + {{tainted}} 196 197 long l = atol(s); // expected-warning + {{tainted}} 198 int tl = l; // expected-warning + {{tainted}} 199 200 long long ll = atoll(s); // expected-warning + {{tainted}} 201 int tll = ll; // expected-warning + {{tainted}} 202 203 } 204 205