taint-tester.c revision d3d8548e75f3fb6db53ed0927c1df30d78f4ce1d
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);
7
8#define BUFSIZE 10
9int Buffer[BUFSIZE];
10
11struct XYStruct {
12  int x;
13  int y;
14  char z;
15};
16
17void taintTracking(int x) {
18  int n;
19  int *addr = &Buffer[0];
20  scanf("%d", &n);
21  addr += n;// expected-warning + {{tainted}}
22  *addr = n; // expected-warning + {{tainted}}
23
24  double tdiv = n / 30; // expected-warning+ {{tainted}}
25  char *loc_cast = (char *) n; // expected-warning +{{tainted}}
26  char tinc = tdiv++; // expected-warning + {{tainted}}
27  int tincdec = (char)tinc--; // expected-warning+{{tainted}}
28
29  // Tainted ptr arithmetic/array element address.
30  int tprtarithmetic1 = *(addr+1); // expected-warning + {{tainted}}
31
32  // Dereference.
33  int *ptr;
34  scanf("%p", &ptr);
35  int ptrDeref = *ptr; // expected-warning + {{tainted}}
36  int _ptrDeref = ptrDeref + 13; // expected-warning + {{tainted}}
37
38  // Pointer arithmetic + dereferencing.
39  // FIXME: We fail to propagate the taint here because RegionStore does not
40  // handle ElementRegions with symbolic indexes.
41  int addrDeref = *addr; // expected-warning + {{tainted}}
42  int _addrDeref = addrDeref;
43
44  // Tainted struct address, casts.
45  struct XYStruct *xyPtr = 0;
46  scanf("%p", &xyPtr);
47  void *tXYStructPtr = xyPtr; // expected-warning + {{tainted}}
48  struct XYStruct *xyPtrCopy = tXYStructPtr; // expected-warning + {{tainted}}
49  int ptrtx = xyPtr->x;// expected-warning + {{tainted}}
50  int ptrty = xyPtr->y;// expected-warning + {{tainted}}
51
52  // Taint on fields of a struct.
53  struct XYStruct xy = {2, 3, 11};
54  scanf("%d", &xy.y);
55  scanf("%d", &xy.x);
56  int tx = xy.x; // expected-warning + {{tainted}}
57  int ty = xy.y; // FIXME: This should be tainted as well.
58  char ntz = xy.z;// no warning
59  // Now, scanf scans both.
60  scanf("%d %d", &xy.y, &xy.x);
61  int ttx = xy.x; // expected-warning + {{tainted}}
62  int tty = xy.y; // expected-warning + {{tainted}}
63}
64
65void BitwiseOp(int in, char inn) {
66  // Taint on bitwise operations, integer to integer cast.
67  int m;
68  int x = 0;
69  scanf("%d", &x);
70  int y = (in << (x << in)) * 5;// expected-warning + {{tainted}}
71  // The next line tests integer to integer cast.
72  int z = y & inn; // expected-warning + {{tainted}}
73  if (y == 5) // expected-warning + {{tainted}}
74    m = z | z;// expected-warning + {{tainted}}
75  else
76    m = inn;
77  int mm = m; // expected-warning + {{tainted}}
78}
79
80// Test getenv.
81char *getenv(const char *name);
82void getenvTest(char *home) {
83  home = getenv("HOME"); // expected-warning + {{tainted}}
84  if (home != 0) { // expected-warning + {{tainted}}
85      char d = home[0]; // expected-warning + {{tainted}}
86    }
87}
88
89typedef struct _FILE FILE;
90extern FILE *stdin;
91extern FILE *stdout;
92extern FILE *stderr;
93int fscanf(FILE *restrict stream, const char *restrict format, ...);
94int fprintf(FILE *stream, const char *format, ...);
95int fclose(FILE *stream);
96FILE *fopen(const char *path, const char *mode);
97
98int fscanfTest(void) {
99  FILE *fp;
100  char s[80];
101  int t;
102
103  // Check if stdin is treated as tainted.
104  fscanf(stdin, "%s %d", s, &t);
105  // Note, here, s is not tainted, but the data s points to is tainted.
106  char *ts = s;
107  char tss = s[0]; // expected-warning + {{tainted}}
108  int tt = t; // expected-warning + {{tainted}}
109  if((fp=fopen("test", "w")) == 0) // expected-warning + {{tainted}}
110    return 1;
111  fprintf(fp, "%s %d", s, t); // expected-warning + {{tainted}}
112  fclose(fp); // expected-warning + {{tainted}}
113
114  // Test fscanf and fopen.
115  if((fp=fopen("test","r")) == 0) // expected-warning + {{tainted}}
116    return 1;
117  fscanf(fp, "%s%d", s, &t); // expected-warning + {{tainted}}
118  fprintf(stdout, "%s %d", s, t); // expected-warning + {{tainted}}
119  return 0;
120}
121
122// Check if we propagate taint from stdin when it's used in an assignment.
123void stdinTest1() {
124  int i;
125  fscanf(stdin, "%d", &i);
126  int j = i; // expected-warning + {{tainted}}
127}
128void stdinTest2(FILE *pIn) {
129  FILE *p = stdin;
130  FILE *pp = p;
131  int ii;
132
133  fscanf(pp, "%d", &ii);
134  int jj = ii;// expected-warning + {{tainted}}
135
136  fscanf(p, "%d", &ii);
137  int jj2 = ii;// expected-warning + {{tainted}}
138
139  ii = 3;
140  int jj3 = ii;// no warning
141
142  p = pIn;
143  fscanf(p, "%d", &ii);
144  int jj4 = ii;// no warning
145}
146
147void stdinTest3() {
148  FILE **ppp = &stdin;
149  int iii;
150  fscanf(*ppp, "%d", &iii);
151  int jjj = iii;// expected-warning + {{tainted}}
152}
153