security-syntax-checks.m revision 3ea9e33ea25e0c2b12db56418ba3f994eb662c04
1// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
2// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -DUSE_BUILTINS -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
3// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
4// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
5// RUN: %clang_cc1 -triple x86_64-unknown-cloudabi -analyze -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
6// RUN: %clang_cc1 -triple x86_64-unknown-cloudabi -analyze -DUSE_BUILTINS -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
7// RUN: %clang_cc1 -triple x86_64-unknown-cloudabi -analyze -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
8// RUN: %clang_cc1 -triple x86_64-unknown-cloudabi -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
9
10#ifdef USE_BUILTINS
11# define BUILTIN(f) __builtin_ ## f
12#else /* USE_BUILTINS */
13# define BUILTIN(f) f
14#endif /* USE_BUILTINS */
15
16typedef typeof(sizeof(int)) size_t;
17
18
19// <rdar://problem/6336718> rule request: floating point used as loop 
20//  condition (FLP30-C, FLP-30-CPP)
21//
22// For reference: https://www.securecoding.cert.org/confluence/display/seccode/FLP30-C.+Do+not+use+floating+point+variables+as+loop+counters
23//
24void test_float_condition() {
25  for (float x = 0.1f; x <= 1.0f; x += 0.1f) {} // expected-warning{{Variable 'x' with floating point type 'float'}}
26  for (float x = 100000001.0f; x <= 100000010.0f; x += 1.0f) {} // expected-warning{{Variable 'x' with floating point type 'float'}}
27  for (float x = 100000001.0f; x <= 100000010.0f; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'float'}}
28  for (double x = 100000001.0; x <= 100000010.0; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'double'}}
29  for (double x = 100000001.0; ((x)) <= 100000010.0; ((x))++ ) {} // expected-warning{{Variable 'x' with floating point type 'double'}}
30  
31  for (double x = 100000001.0; 100000010.0 >= x; x = x + 1.0 ) {} // expected-warning{{Variable 'x' with floating point type 'double'}}
32  
33  int i = 0;
34  for (double x = 100000001.0; ((x)) <= 100000010.0; ((x))++, ++i ) {} // expected-warning{{Variable 'x' with floating point type 'double'}}
35  
36  typedef float FooType;
37  for (FooType x = 100000001.0f; x <= 100000010.0f; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'FooType'}}
38}
39
40// <rdar://problem/6335715> rule request: gets() buffer overflow
41// Part of recommendation: 300-BSI (buildsecurityin.us-cert.gov)
42char* gets(char *buf);
43
44void test_gets() {
45  char buff[1024];
46  gets(buff); // expected-warning{{Call to function 'gets' is extremely insecure as it can always result in a buffer overflow}}
47}
48
49int getpw(unsigned int uid, char *buf);
50
51void test_getpw() {
52  char buff[1024];
53  getpw(2, buff); // expected-warning{{The getpw() function is dangerous as it may overflow the provided buffer. It is obsoleted by getpwuid()}}
54}
55
56// <rdar://problem/6337132> CWE-273: Failure to Check Whether Privileges Were
57//  Dropped Successfully
58typedef unsigned int __uint32_t;
59typedef __uint32_t __darwin_uid_t;
60typedef __uint32_t __darwin_gid_t;
61typedef __darwin_uid_t uid_t;
62typedef __darwin_gid_t gid_t;
63int setuid(uid_t);
64int setregid(gid_t, gid_t);
65int setreuid(uid_t, uid_t);
66extern void check(int);
67void abort(void);
68
69void test_setuid() 
70{
71  setuid(2); // expected-warning{{The return value from the call to 'setuid' is not checked.  If an error occurs in 'setuid', the following code may execute with unexpected privileges}}
72  setuid(0); // expected-warning{{The return value from the call to 'setuid' is not checked.  If an error occurs in 'setuid', the following code may execute with unexpected privileges}}
73  if (setuid (2) != 0)
74    abort();
75
76  // Currently the 'setuid' check is not flow-sensitive, and only looks
77  // at whether the function was called in a compound statement.  This
78  // will lead to false negatives, but there should be no false positives.
79  int t = setuid(2);  // no-warning
80  (void)setuid (2); // no-warning
81
82  check(setuid (2)); // no-warning
83
84  setreuid(2,2); // expected-warning{{The return value from the call to 'setreuid' is not checked.  If an error occurs in 'setreuid', the following code may execute with unexpected privileges}}
85  setregid(2,2); // expected-warning{{The return value from the call to 'setregid' is not checked.  If an error occurs in 'setregid', the following code may execute with unexpected privileges}}
86}
87
88// <rdar://problem/6337100> CWE-338: Use of cryptographically weak prng
89typedef  unsigned short *ushort_ptr_t;  // Test that sugar doesn't confuse the warning.
90int      rand(void);
91double   drand48(void);
92double   erand48(unsigned short[3]);
93long     jrand48(ushort_ptr_t);
94void     lcong48(unsigned short[7]);
95long     lrand48(void);
96long     mrand48(void);
97long     nrand48(unsigned short[3]);
98long     random(void);
99int      rand_r(unsigned *);
100
101void test_rand()
102{
103  unsigned short a[7];
104  unsigned b;
105  
106  rand();	// expected-warning{{Function 'rand' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
107  drand48();	// expected-warning{{Function 'drand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
108  erand48(a);	// expected-warning{{Function 'erand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
109  jrand48(a);	// expected-warning{{Function 'jrand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
110  lcong48(a);	// expected-warning{{Function 'lcong48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
111  lrand48();	// expected-warning{{Function 'lrand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
112  mrand48();	// expected-warning{{Function 'mrand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
113  nrand48(a);	// expected-warning{{Function 'nrand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
114  rand_r(&b);	// expected-warning{{Function 'rand_r' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
115  random();	// expected-warning{{The 'random' function produces a sequence of values that an adversary may be able to predict.  Use 'arc4random' instead}}
116}
117
118char *mktemp(char *buf);
119
120void test_mktemp() {
121  char *x = mktemp("/tmp/zxcv"); // expected-warning{{Call to function 'mktemp' is insecure as it always creates or uses insecure temporary file}}
122}
123
124
125//===----------------------------------------------------------------------===
126// strcpy()
127//===----------------------------------------------------------------------===
128#ifdef VARIANT
129
130#define __strcpy_chk BUILTIN(__strcpy_chk)
131char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
132
133#define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1)
134
135#else /* VARIANT */
136
137#define strcpy BUILTIN(strcpy)
138char *strcpy(char *restrict s1, const char *restrict s2);
139
140#endif /* VARIANT */
141
142void test_strcpy() {
143  char x[4];
144  char *y;
145
146  strcpy(x, y); //expected-warning{{Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119}}
147}
148
149//===----------------------------------------------------------------------===
150// strcat()
151//===----------------------------------------------------------------------===
152#ifdef VARIANT
153
154#define __strcat_chk BUILTIN(__strcat_chk)
155char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen);
156
157#define strcat(a,b) __strcat_chk(a,b,(size_t)-1)
158
159#else /* VARIANT */
160
161#define strcat BUILTIN(strcat)
162char *strcat(char *restrict s1, const char *restrict s2);
163
164#endif /* VARIANT */
165
166void test_strcat() {
167  char x[4];
168  char *y;
169
170  strcat(x, y); //expected-warning{{Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119}}
171}
172
173//===----------------------------------------------------------------------===
174// vfork()
175//===----------------------------------------------------------------------===
176typedef int __int32_t;
177typedef __int32_t pid_t;
178pid_t vfork(void);
179
180void test_vfork() {
181  vfork(); //expected-warning{{Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process}}
182}
183
184//===----------------------------------------------------------------------===
185// mkstemp()
186//===----------------------------------------------------------------------===
187
188char *mkdtemp(char *template);
189int mkstemps(char *template, int suffixlen);
190int mkstemp(char *template);
191char *mktemp(char *template);
192
193void test_mkstemp() {
194  mkstemp("XX"); // expected-warning {{Call to 'mkstemp' should have at least 6 'X's in the format string to be secure (2 'X's seen)}}
195  mkstemp("XXXXXX");
196  mkstemp("XXXXXXX");
197  mkstemps("XXXXXX", 0);
198  mkstemps("XXXXXX", 1); // expected-warning {{5 'X's seen}}
199  mkstemps("XXXXXX", 2); // expected-warning {{Call to 'mkstemps' should have at least 6 'X's in the format string to be secure (4 'X's seen, 2 characters used as a suffix)}}
200  mkdtemp("XX"); // expected-warning {{2 'X's seen}}
201  mkstemp("X"); // expected-warning {{Call to 'mkstemp' should have at least 6 'X's in the format string to be secure (1 'X' seen)}}
202  mkdtemp("XXXXXX");
203}
204
205