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