xref: /llvm-project/clang/test/Analysis/taint-tester.c (revision a017ed04cc9bcc75b3c3ef35c923dbe7dc4606f8)
1 // RUN: %clang_analyze_cc1 -Wno-int-to-pointer-cast -analyzer-checker=optin.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 
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 
62 void BitwiseOp(int in, char inn, int zz) {
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 == zz) { // expected-warning + {{tainted}}
71     m = z | z;// expected-warning + {{tainted}}
72   }
73   else
74     m = inn;
75   int mm = m; // expected-warning 1 {{tainted}}
76 }
77 
78 // Test getenv.
79 char *getenv(const char *name);
80 void getenvTest(char *home) {
81   home = getenv("HOME"); // expected-warning + {{tainted}}
82   if (home != 0) { // expected-warning + {{tainted}}
83       char d = home[0]; // expected-warning + {{tainted}}
84     }
85 }
86 
87 int fscanfTest(void) {
88   FILE *fp;
89   char s[80];
90   int t;
91 
92   // Check if stdin is treated as tainted.
93   fscanf(stdin, "%s %d", s, &t);
94   // Note, here, s is not tainted, but the data s points to is tainted.
95   char *ts = s;
96   char tss = s[0]; // expected-warning + {{tainted}}
97   int tt = t; // expected-warning + {{tainted}}
98   if((fp=fopen("test", "w")) == 0) // expected-warning + {{tainted}}
99     return 1;
100   fprintf(fp, "%s %d", s, t); // expected-warning + {{tainted}}
101   fclose(fp); // expected-warning + {{tainted}}
102 
103   // Test fscanf and fopen.
104   if((fp=fopen("test","r")) == 0) // expected-warning + {{tainted}}
105     return 1;
106   fscanf(fp, "%s%d", s, &t); // expected-warning + {{tainted}}
107   fprintf(stdout, "%s %d", s, t); // expected-warning + {{tainted}}
108   return 0;
109 }
110 
111 // Check if we propagate taint from stdin when it's used in an assignment.
112 void stdinTest1(void) {
113   int i;
114   fscanf(stdin, "%d", &i);
115   int j = i; // expected-warning + {{tainted}}
116 }
117 void stdinTest2(FILE *pIn) {
118   FILE *p = stdin;
119   FILE *pp = p;
120   int ii;
121 
122   fscanf(pp, "%d", &ii);
123   int jj = ii;// expected-warning + {{tainted}}
124 
125   fscanf(p, "%d", &ii);// expected-warning + {{tainted}}
126   int jj2 = ii;// expected-warning + {{tainted}}
127 
128   ii = 3;
129   int jj3 = ii;// no warning
130 
131   p = pIn;
132   fscanf(p, "%d", &ii);
133   int jj4 = ii;// no warning
134 }
135 
136 void stdinTest3(void) {
137   FILE **ppp = &stdin;
138   int iii;
139   fscanf(*ppp, "%d", &iii);
140   int jjj = iii;// expected-warning + {{tainted}}
141 }
142 
143 // Test that stdin does not get invalidated by calls.
144 void foo(void);
145 void stdinTest4(void) {
146   int i;
147   fscanf(stdin, "%d", &i);
148   foo();
149   int j = i; // expected-warning + {{tainted}}
150 }
151 
152 int getw(FILE *);
153 void getwTest(void) {
154   int i = getw(stdin); // expected-warning + {{tainted}}
155 }
156 
157 ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict);
158 int  printf(const char * __restrict, ...);
159 void free(void *ptr);
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 
178 void atoiTest(void) {
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;
194 void noCrashTest(void) {
195   if (!*pointer1) {
196     __builtin___memcpy_chk(pointer2, pointer1, 0, 0); // no-crash
197   }
198 }
199 
200 void builtin_overflow_test(void) {
201   int input, input2, res;
202 
203   scanf("%d", &input);
204   scanf("%d", &input2);
205 
206   if (__builtin_add_overflow(input, 10, &res)) // expected-warning + {{tainted}}
207     return;
208 
209   if (__builtin_add_overflow(10, input, &res)) // expected-warning + {{tainted}}
210     return;
211 
212   if (__builtin_add_overflow(input2, input, &res)) // expected-warning + {{tainted}}
213     return;
214 }
215