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