1// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
2// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DUSE_BUILTINS -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
3// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
4// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DUSE_BUILTINS -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
5// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
6// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi -DUSE_BUILTINS -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
7// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify
8// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi -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
149void test_strcpy_2() {
150  char x[4];
151  strcpy(x, "abcd"); //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}}
152}
153
154void test_strcpy_safe() {
155  char x[5];
156  strcpy(x, "abcd");
157}
158
159//===----------------------------------------------------------------------===
160// strcat()
161//===----------------------------------------------------------------------===
162#ifdef VARIANT
163
164#define __strcat_chk BUILTIN(__strcat_chk)
165char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen);
166
167#define strcat(a,b) __strcat_chk(a,b,(size_t)-1)
168
169#else /* VARIANT */
170
171#define strcat BUILTIN(strcat)
172char *strcat(char *restrict s1, const char *restrict s2);
173
174#endif /* VARIANT */
175
176void test_strcat() {
177  char x[4];
178  char *y;
179
180  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}}
181}
182
183//===----------------------------------------------------------------------===
184// vfork()
185//===----------------------------------------------------------------------===
186typedef int __int32_t;
187typedef __int32_t pid_t;
188pid_t vfork(void);
189
190void test_vfork() {
191  vfork(); //expected-warning{{Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process}}
192}
193
194//===----------------------------------------------------------------------===
195// mkstemp()
196//===----------------------------------------------------------------------===
197
198char *mkdtemp(char *template);
199int mkstemps(char *template, int suffixlen);
200int mkstemp(char *template);
201char *mktemp(char *template);
202
203void test_mkstemp() {
204  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)}}
205  mkstemp("XXXXXX");
206  mkstemp("XXXXXXX");
207  mkstemps("XXXXXX", 0);
208  mkstemps("XXXXXX", 1); // expected-warning {{5 'X's seen}}
209  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)}}
210  mkdtemp("XX"); // expected-warning {{2 'X's seen}}
211  mkstemp("X"); // expected-warning {{Call to 'mkstemp' should have at least 6 'X's in the format string to be secure (1 'X' seen)}}
212  mkdtemp("XXXXXX");
213}
214
215