taint-tester.c revision 1009ac715501a4fa1951d94722dcbe6ab30068f8
1// RUN: %clang_cc1  -analyze -analyzer-checker=experimental.security.taint,debug.TaintTest -verify %s
2
3int scanf(const char *restrict format, ...);
4int getchar(void);
5
6#define BUFSIZE 10
7int Buffer[BUFSIZE];
8
9struct XYStruct {
10  int x;
11  int y;
12  char z;
13};
14
15void taintTracking(int x) {
16  int n;
17  int *addr = &Buffer[0];
18  scanf("%d", &n);
19  addr += n;// expected-warning 2 {{tainted}}
20  *addr = n; // expected-warning 3 {{tainted}}
21
22  double tdiv = n / 30; // expected-warning 3 {{tainted}}
23  char *loc_cast = (char *) n; // expected-warning {{tainted}}
24  char tinc = tdiv++; // expected-warning {{tainted}}
25  int tincdec = (char)tinc--; // expected-warning 2 {{tainted}}
26
27  // Tainted ptr arithmetic/array element address.
28  int tprtarithmetic1 = *(addr+1); // expected-warning 2 {{tainted}}
29
30  // Dereference.
31  int *ptr;
32  scanf("%p", &ptr);
33  int ptrDeref = *ptr; // expected-warning 2 {{tainted}}
34  int _ptrDeref = ptrDeref + 13; // expected-warning 2 {{tainted}}
35
36  // Pointer arithmetic + dereferencing.
37  // FIXME: We fail to propagate the taint here because RegionStore does not
38  // handle ElementRegions with symbolic indexes.
39  int addrDeref = *addr; // expected-warning {{tainted}}
40  int _addrDeref = addrDeref;
41
42  // Tainted struct address, casts.
43  struct XYStruct *xyPtr = 0;
44  scanf("%p", &xyPtr);
45  void *tXYStructPtr = xyPtr; // expected-warning 2 {{tainted}}
46  struct XYStruct *xyPtrCopy = tXYStructPtr; // expected-warning 2 {{tainted}}
47  int ptrtx = xyPtr->x;// expected-warning 2 {{tainted}}
48  int ptrty = xyPtr->y;// expected-warning 2 {{tainted}}
49
50  // Taint on fields of a struct.
51  struct XYStruct xy = {2, 3, 11};
52  scanf("%d", &xy.y);
53  scanf("%d", &xy.x);
54  int tx = xy.x; // expected-warning {{tainted}}
55  int ty = xy.y; // FIXME: This should be tainted as well.
56  char ntz = xy.z;// no warning
57  // Now, scanf scans both.
58  scanf("%d %d", &xy.y, &xy.x);
59  int ttx = xy.x; // expected-warning {{tainted}}
60  int tty = xy.y; // expected-warning {{tainted}}
61}
62
63void BitwiseOp(int in, char inn) {
64  // Taint on bitwise operations, integer to integer cast.
65  int m;
66  int x = 0;
67  scanf("%d", &x);
68  int y = (in << (x << in)) * 5;// expected-warning 4 {{tainted}}
69  // The next line tests integer to integer cast.
70  int z = y & inn; // expected-warning 2 {{tainted}}
71  if (y == 5) // expected-warning 2 {{tainted}}
72    m = z | z;// expected-warning 4 {{tainted}}
73  else
74    m = inn;
75  int mm = m; // expected-warning   {{tainted}}
76}
77
78// Test getenv.
79char *getenv(const char *name);
80void getenvTest(char *home) {
81  home = getenv("HOME"); // expected-warning 2 {{tainted}}
82  if (home != 0) { // expected-warning 2 {{tainted}}
83      char d = home[0]; // expected-warning 2 {{tainted}}
84    }
85}
86
87struct _IO_FILE {
88  unsigned fakeField1;
89  char fakeField2;
90};
91typedef struct _IO_FILE FILE;
92extern struct _IO_FILE *stdin;
93extern struct _IO_FILE *stdout;
94extern struct _IO_FILE *stderr;
95int fscanf(FILE *restrict stream, const char *restrict format, ...);
96int fprintf(FILE *stream, const char *format, ...);
97int fclose(FILE *stream);
98FILE *fopen(const char *path, const char *mode);
99
100int fscanfTest(void) {
101  FILE *fp;
102  char s[80];
103  int t;
104
105  if((fp=fopen("test", "w")) == 0) // expected-warning 3 {{tainted}}
106    return 1;
107  // TODO: Have to mark stdin as tainted.
108  fscanf(stdin, "%s%d", s, &t);
109  fprintf(fp, "%s %d", s, t); // expected-warning 1 {{tainted}}
110  fclose(fp); // expected-warning 1 {{tainted}}
111
112  if((fp=fopen("test","r")) == 0) // expected-warning 3 {{tainted}}
113    return 1;
114  fscanf(fp, "%s%d", s, &t); // expected-warning 1 {{tainted}}
115  fprintf(stdout, "%s %d", s, t); // expected-warning 1 {{tainted}}
116  return 0;
117}
118