1 // RUN: %clang_cc1 -analyze -analyzer-checker=experimental.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
taintTracking(int x)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;
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
BitwiseOp(int in,char inn)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);
getenvTest(char * home)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
fscanfTest(void)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.
stdinTest1()124 void stdinTest1() {
125 int i;
126 fscanf(stdin, "%d", &i);
127 int j = i; // expected-warning + {{tainted}}
128 }
stdinTest2(FILE * pIn)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
stdinTest3()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();
stdinTest4()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 *);
getwTest()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);
getlineTest(void)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
atoiTest()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