1// RUN: %clang_cc1 -Wno-int-to-pointer-cast -analyze -analyzer-checker=alpha.security.taint,debug.TaintTest %s -verify
2
3#include "Inputs/system-header-simulator.h"
4
5#define BUFSIZE 10
6int Buffer[BUFSIZE];
7
8struct XYStruct {
9  int x;
10  int y;
11  char z;
12};
13
14void 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
62void 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.
78char *getenv(const char *name);
79void 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
86int 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.
111void stdinTest1() {
112  int i;
113  fscanf(stdin, "%d", &i);
114  int j = i; // expected-warning + {{tainted}}
115}
116void 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
135void 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.
143void foo();
144void stdinTest4() {
145  int i;
146  fscanf(stdin, "%d", &i);
147  foo();
148  int j = i; // expected-warning + {{tainted}}
149}
150
151int getw(FILE *);
152void getwTest() {
153  int i = getw(stdin); // expected-warning + {{tainted}}
154}
155
156typedef long ssize_t;
157ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict);
158int  printf(const char * __restrict, ...);
159void free(void *ptr);
160void 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
174int atoi(const char *nptr);
175long atol(const char *nptr);
176long long atoll(const char *nptr);
177
178void 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