1 // RUN: %clang_analyze_cc1 -Wno-int-to-pointer-cast -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 char *pointer1;
193 void *pointer2;
noCrashTest()194 void noCrashTest() {
195   if (!*pointer1) {
196     __builtin___memcpy_chk(pointer2, pointer1, 0, 0); // no-crash
197   }
198 }
199