taint-generic.c revision 9b0c749a20d0f7d0e63441d76baa15def3f37fdb
1// RUN: %clang_cc1  -analyze -analyzer-checker=experimental.security.taint,experimental.security.ArrayBoundV2 -Wno-format-security -verify %s
2
3int scanf(const char *restrict format, ...);
4int getchar(void);
5
6typedef struct _FILE FILE;
7extern FILE *stdin;
8int fscanf(FILE *restrict stream, const char *restrict format, ...);
9int sprintf(char *str, const char *format, ...);
10void setproctitle(const char *fmt, ...);
11typedef __typeof(sizeof(int)) size_t;
12
13// Define string functions. Use builtin for some of them. They all default to
14// the processing in the taint checker.
15#define strcpy(dest, src) \
16  ((__builtin_object_size(dest, 0) != -1ULL) \
17   ? __builtin___strcpy_chk (dest, src, __builtin_object_size(dest, 1)) \
18   : __inline_strcpy_chk(dest, src))
19
20static char *__inline_strcpy_chk (char *dest, const char *src) {
21  return __builtin___strcpy_chk(dest, src, __builtin_object_size(dest, 1));
22}
23char *stpcpy(char *restrict s1, const char *restrict s2);
24char *strncpy( char * destination, const char * source, size_t num );
25char *strndup(const char *s, size_t n);
26
27#define BUFSIZE 10
28
29int Buffer[BUFSIZE];
30void bufferScanfDirect(void)
31{
32  int n;
33  scanf("%d", &n);
34  Buffer[n] = 1; // expected-warning {{Out of bound memory access }}
35}
36
37void bufferScanfArithmetic1(int x) {
38  int n;
39  scanf("%d", &n);
40  int m = (n - 3);
41  Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
42}
43
44void bufferScanfArithmetic2(int x) {
45  int n;
46  scanf("%d", &n);
47  int m = 100 / (n + 3) * x;
48  Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
49}
50
51void bufferScanfAssignment(int x) {
52  int n;
53  scanf("%d", &n);
54  int m;
55  if (x > 0) {
56    m = n;
57    Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
58  }
59}
60
61void scanfArg() {
62  int t;
63  scanf("%d", t); // expected-warning {{conversion specifies type 'int *' but the argument has type 'int'}}
64}
65
66void bufferGetchar(int x) {
67  int m = getchar();
68  Buffer[m] = 1;  //expected-warning {{Out of bound memory access }}
69}
70
71void testUncontrolledFormatString(char **p) {
72  char s[80];
73  fscanf(stdin, "%s", s);
74  char buf[128];
75  sprintf(buf,s); // expected-warning {{Uncontrolled Format String}}
76  setproctitle(s, 3); // expected-warning {{Uncontrolled Format String}}
77
78  // Test taint propagation through strcpy and family.
79  char scpy[80];
80  strcpy(scpy, s);
81  sprintf(buf,scpy); // expected-warning {{Uncontrolled Format String}}
82
83  stpcpy(*(++p), s); // this generates __inline.
84  setproctitle(*(p), 3); // expected-warning {{Uncontrolled Format String}}
85
86  char spcpy[80];
87  stpcpy(spcpy, s);
88  setproctitle(spcpy, 3); // expected-warning {{Uncontrolled Format String}}
89
90  char *spcpyret;
91  spcpyret = stpcpy(spcpy, s);
92  setproctitle(spcpyret, 3); // expected-warning {{Uncontrolled Format String}}
93
94  char sncpy[80];
95  strncpy(sncpy, s, 20);
96  setproctitle(sncpy, 3); // expected-warning {{Uncontrolled Format String}}
97
98  char *dup;
99  dup = strndup(s, 20);
100  setproctitle(dup, 3); // expected-warning {{Uncontrolled Format String}}
101
102}
103
104int system(const char *command);
105void testTaintSystemCall() {
106  char buffer[156];
107  char addr[128];
108  scanf("%s", addr);
109  system(addr); // expected-warning {{Tainted data passed to a system call}}
110
111  // Test that spintf transfers taint.
112  sprintf(buffer, "/bin/mail %s < /tmp/email", addr);
113  system(buffer); // expected-warning {{Tainted data passed to a system call}}
114}
115void testTaintSystemCall2() {
116  // Test that snpintf transfers taint.
117  char buffern[156];
118  char addr[128];
119  scanf("%s", addr);
120  __builtin_snprintf(buffern, 10, "/bin/mail %s < /tmp/email", addr);
121  system(buffern); // expected-warning {{Tainted data passed to a system call}}
122}
123void testTaintSystemCall3() {
124  char buffern2[156];
125  int numt;
126  char addr[128];
127  scanf("%s %d", addr, &numt);
128  __builtin_snprintf(buffern2, numt, "/bin/mail %s < /tmp/email", "abcd");
129  system(buffern2); // expected-warning {{Tainted data passed to a system call}}
130}
131