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