taint-tester.c revision b9ac30cf9ec001fd0d63ffc44289a333a21e691d
1// RUN: %clang_cc1  -analyze -analyzer-checker=experimental.security.taint,debug.TaintTest %s -verify
2
3#include <stdarg.h>
4
5int scanf(const char *restrict format, ...);
6int getchar(void);
7typedef __typeof(sizeof(int)) size_t;
8
9#define BUFSIZE 10
10int Buffer[BUFSIZE];
11
12struct XYStruct {
13  int x;
14  int y;
15  char z;
16};
17
18void 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
66void 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.
82char *getenv(const char *name);
83void 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
90typedef struct _FILE FILE;
91extern FILE *stdin;
92extern FILE *stdout;
93extern FILE *stderr;
94int fscanf(FILE *restrict stream, const char *restrict format, ...);
95int fprintf(FILE *stream, const char *format, ...);
96int fclose(FILE *stream);
97FILE *fopen(const char *path, const char *mode);
98
99int 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.
124void stdinTest1() {
125  int i;
126  fscanf(stdin, "%d", &i);
127  int j = i; // expected-warning + {{tainted}}
128}
129void 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
148void 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.
156void foo();
157void stdinTest4() {
158  int i;
159  fscanf(stdin, "%d", &i);
160  foo();
161  int j = i; // expected-warning + {{tainted}}
162}
163
164int getw(FILE *);
165void getwTest() {
166  int i = getw(stdin); // expected-warning + {{tainted}}
167}
168
169typedef long ssize_t;
170ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict);
171int  printf(const char * __restrict, ...);
172void free(void *ptr);
173void 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
187int atoi(const char *nptr);
188long atol(const char *nptr);
189long long atoll(const char *nptr);
190
191void 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