1// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 %s -verify \
2// RUN:   -analyzer-checker=security.insecureAPI \
3// RUN:   -analyzer-checker=security.FloatLoopCounter
4
5// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 %s -verify \
6// RUN:   -DUSE_BUILTINS \
7// RUN:   -analyzer-checker=security.insecureAPI \
8// RUN:   -analyzer-checker=security.FloatLoopCounter
9
10// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 %s -verify \
11// RUN:   -DVARIANT \
12// RUN:   -analyzer-checker=security.insecureAPI \
13// RUN:   -analyzer-checker=security.FloatLoopCounter
14
15// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 %s -verify \
16// RUN:   -DUSE_BUILTINS -DVARIANT \
17// RUN:   -analyzer-checker=security.insecureAPI \
18// RUN:   -analyzer-checker=security.FloatLoopCounter
19
20// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi %s -verify \
21// RUN:   -analyzer-checker=security.insecureAPI \
22// RUN:   -analyzer-checker=security.FloatLoopCounter
23
24// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi %s -verify \
25// RUN:   -DUSE_BUILTINS \
26// RUN:   -analyzer-checker=security.insecureAPI \
27// RUN:   -analyzer-checker=security.FloatLoopCounter
28
29// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi %s -verify \
30// RUN:   -DVARIANT \
31// RUN:   -analyzer-checker=security.insecureAPI \
32// RUN:   -analyzer-checker=security.FloatLoopCounter
33
34// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi %s -verify \
35// RUN:   -DUSE_BUILTINS -DVARIANT \
36// RUN:   -analyzer-checker=security.insecureAPI \
37// RUN:   -analyzer-checker=security.FloatLoopCounter
38
39#ifdef USE_BUILTINS
40# define BUILTIN(f) __builtin_ ## f
41#else /* USE_BUILTINS */
42# define BUILTIN(f) f
43#endif /* USE_BUILTINS */
44
45#include "Inputs/system-header-simulator-for-valist.h"
46#include "Inputs/system-header-simulator-for-simple-stream.h"
47
48typedef typeof(sizeof(int)) size_t;
49
50
51// <rdar://problem/6336718> rule request: floating point used as loop
52//  condition (FLP30-C, FLP-30-CPP)
53//
54// For reference: https://www.securecoding.cert.org/confluence/display/seccode/FLP30-C.+Do+not+use+floating+point+variables+as+loop+counters
55//
56void test_float_condition() {
57  for (float x = 0.1f; x <= 1.0f; x += 0.1f) {} // expected-warning{{Variable 'x' with floating point type 'float'}}
58  for (float x = 100000001.0f; x <= 100000010.0f; x += 1.0f) {} // expected-warning{{Variable 'x' with floating point type 'float'}}
59  for (float x = 100000001.0f; x <= 100000010.0f; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'float'}}
60  for (double x = 100000001.0; x <= 100000010.0; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'double'}}
61  for (double x = 100000001.0; ((x)) <= 100000010.0; ((x))++ ) {} // expected-warning{{Variable 'x' with floating point type 'double'}}
62
63  for (double x = 100000001.0; 100000010.0 >= x; x = x + 1.0 ) {} // expected-warning{{Variable 'x' with floating point type 'double'}}
64
65  int i = 0;
66  for (double x = 100000001.0; ((x)) <= 100000010.0; ((x))++, ++i ) {} // expected-warning{{Variable 'x' with floating point type 'double'}}
67
68  typedef float FooType;
69  for (FooType x = 100000001.0f; x <= 100000010.0f; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'FooType'}}
70}
71
72// Obsolete function bcmp
73int bcmp(const void *, const void *, size_t);
74
75int test_bcmp(void *a, void *b, size_t n) {
76  return bcmp(a, b, n); // expected-warning{{The bcmp() function is obsoleted by memcmp()}}
77}
78
79// Obsolete function bcopy
80void bcopy(void *, void *, size_t);
81
82void test_bcopy(void *a, void *b, size_t n) {
83  bcopy(a, b, n); // expected-warning{{The bcopy() function is obsoleted by memcpy() or memmove(}}
84}
85
86// Obsolete function bzero
87void bzero(void *, size_t);
88
89void test_bzero(void *a, size_t n) {
90  bzero(a, n); // expected-warning{{The bzero() function is obsoleted by memset()}}
91}
92
93// <rdar://problem/6335715> rule request: gets() buffer overflow
94// Part of recommendation: 300-BSI (buildsecurityin.us-cert.gov)
95char* gets(char *buf);
96
97void test_gets() {
98  char buff[1024];
99  gets(buff); // expected-warning{{Call to function 'gets' is extremely insecure as it can always result in a buffer overflow}}
100}
101
102int getpw(unsigned int uid, char *buf);
103
104void test_getpw() {
105  char buff[1024];
106  getpw(2, buff); // expected-warning{{The getpw() function is dangerous as it may overflow the provided buffer. It is obsoleted by getpwuid()}}
107}
108
109// <rdar://problem/6337132> CWE-273: Failure to Check Whether Privileges Were
110//  Dropped Successfully
111typedef unsigned int __uint32_t;
112typedef __uint32_t __darwin_uid_t;
113typedef __uint32_t __darwin_gid_t;
114typedef __darwin_uid_t uid_t;
115typedef __darwin_gid_t gid_t;
116int setuid(uid_t);
117int setregid(gid_t, gid_t);
118int setreuid(uid_t, uid_t);
119extern void check(int);
120void abort(void);
121
122void test_setuid()
123{
124  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}}
125  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}}
126  if (setuid (2) != 0)
127    abort();
128
129  // Currently the 'setuid' check is not flow-sensitive, and only looks
130  // at whether the function was called in a compound statement.  This
131  // will lead to false negatives, but there should be no false positives.
132  int t = setuid(2);  // no-warning
133  (void)setuid (2); // no-warning
134
135  check(setuid (2)); // no-warning
136
137  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}}
138  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}}
139}
140
141// <rdar://problem/6337100> CWE-338: Use of cryptographically weak prng
142typedef  unsigned short *ushort_ptr_t;  // Test that sugar doesn't confuse the warning.
143int      rand(void);
144double   drand48(void);
145double   erand48(unsigned short[3]);
146long     jrand48(ushort_ptr_t);
147void     lcong48(unsigned short[7]);
148long     lrand48(void);
149long     mrand48(void);
150long     nrand48(unsigned short[3]);
151long     random(void);
152int      rand_r(unsigned *);
153
154void test_rand()
155{
156  unsigned short a[7];
157  unsigned b;
158
159  rand();	// expected-warning{{Function 'rand' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
160  drand48();	// expected-warning{{Function 'drand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
161  erand48(a);	// expected-warning{{Function 'erand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
162  jrand48(a);	// expected-warning{{Function 'jrand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
163  lcong48(a);	// expected-warning{{Function 'lcong48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
164  lrand48();	// expected-warning{{Function 'lrand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
165  mrand48();	// expected-warning{{Function 'mrand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
166  nrand48(a);	// expected-warning{{Function 'nrand48' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
167  rand_r(&b);	// expected-warning{{Function 'rand_r' is obsolete because it implements a poor random number generator.  Use 'arc4random' instead}}
168  random();	// expected-warning{{The 'random' function produces a sequence of values that an adversary may be able to predict.  Use 'arc4random' instead}}
169}
170
171char *mktemp(char *buf);
172
173void test_mktemp() {
174  char *x = mktemp("/tmp/zxcv"); // expected-warning{{Call to function 'mktemp' is insecure as it always creates or uses insecure temporary file}}
175}
176
177
178//===----------------------------------------------------------------------===
179// strcpy()
180//===----------------------------------------------------------------------===
181#ifdef VARIANT
182
183#define __strcpy_chk BUILTIN(__strcpy_chk)
184char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
185
186#define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1)
187
188#else /* VARIANT */
189
190#define strcpy BUILTIN(strcpy)
191char *strcpy(char *restrict s1, const char *restrict s2);
192
193#endif /* VARIANT */
194
195void test_strcpy() {
196  char x[4];
197  char *y;
198
199  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}}
200}
201
202void test_strcpy_2() {
203  char x[4];
204  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}}
205}
206
207void test_strcpy_safe() {
208  char x[5];
209  strcpy(x, "abcd");
210}
211
212void test_strcpy_safe_2() {
213  struct {char s1[100];} s;
214  strcpy(s.s1, "hello");
215}
216
217//===----------------------------------------------------------------------===
218// strcat()
219//===----------------------------------------------------------------------===
220#ifdef VARIANT
221
222#define __strcat_chk BUILTIN(__strcat_chk)
223char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen);
224
225#define strcat(a,b) __strcat_chk(a,b,(size_t)-1)
226
227#else /* VARIANT */
228
229#define strcat BUILTIN(strcat)
230char *strcat(char *restrict s1, const char *restrict s2);
231
232#endif /* VARIANT */
233
234void test_strcat() {
235  char x[4];
236  char *y;
237
238  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}}
239}
240
241//===----------------------------------------------------------------------===
242// vfork()
243//===----------------------------------------------------------------------===
244typedef int __int32_t;
245typedef __int32_t pid_t;
246pid_t vfork(void);
247
248void test_vfork() {
249  vfork(); //expected-warning{{Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process}}
250}
251
252//===----------------------------------------------------------------------===
253// mkstemp()
254//===----------------------------------------------------------------------===
255
256char *mkdtemp(char *template);
257int mkstemps(char *template, int suffixlen);
258int mkstemp(char *template);
259char *mktemp(char *template);
260
261void test_mkstemp() {
262  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)}}
263  mkstemp("XXXXXX");
264  mkstemp("XXXXXXX");
265  mkstemps("XXXXXX", 0);
266  mkstemps("XXXXXX", 1); // expected-warning {{5 'X's seen}}
267  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)}}
268  mkdtemp("XX"); // expected-warning {{2 'X's seen}}
269  mkstemp("X"); // expected-warning {{Call to 'mkstemp' should have at least 6 'X's in the format string to be secure (1 'X' seen)}}
270  mkdtemp("XXXXXX");
271}
272
273
274//===----------------------------------------------------------------------===
275// deprecated or unsafe buffer handling
276//===----------------------------------------------------------------------===
277typedef int wchar_t;
278
279int sprintf(char *str, const char *format, ...);
280//int vsprintf (char *s, const char *format, va_list arg);
281int scanf(const char *format, ...);
282int wscanf(const wchar_t *format, ...);
283int fscanf(FILE *stream, const char *format, ...);
284int fwscanf(FILE *stream, const wchar_t *format, ...);
285int vscanf(const char *format, va_list arg);
286int vwscanf(const wchar_t *format, va_list arg);
287int vfscanf(FILE *stream, const char *format, va_list arg);
288int vfwscanf(FILE *stream, const wchar_t *format, va_list arg);
289int sscanf(const char *s, const char *format, ...);
290int swscanf(const wchar_t *ws, const wchar_t *format, ...);
291int vsscanf(const char *s, const char *format, va_list arg);
292int vswscanf(const wchar_t *ws, const wchar_t *format, va_list arg);
293int swprintf(wchar_t *ws, size_t len, const wchar_t *format, ...);
294int snprintf(char *s, size_t n, const char *format, ...);
295int vswprintf(wchar_t *ws, size_t len, const wchar_t *format, va_list arg);
296int vsnprintf(char *s, size_t n, const char *format, va_list arg);
297void *memcpy(void *destination, const void *source, size_t num);
298void *memmove(void *destination, const void *source, size_t num);
299char *strncpy(char *destination, const char *source, size_t num);
300char *strncat(char *destination, const char *source, size_t num);
301void *memset(void *ptr, int value, size_t num);
302
303void test_deprecated_or_unsafe_buffer_handling_1() {
304  char buf [5];
305  wchar_t wbuf [5];
306  int a;
307  FILE *file;
308  sprintf(buf, "a"); // expected-warning{{Call to function 'sprintf' is insecure}}
309  scanf("%d", &a); // expected-warning{{Call to function 'scanf' is insecure}}
310  scanf("%s", buf); // expected-warning{{Call to function 'scanf' is insecure}}
311  scanf("%4s", buf); // expected-warning{{Call to function 'scanf' is insecure}}
312  wscanf((const wchar_t*) L"%s", buf); // expected-warning{{Call to function 'wscanf' is insecure}}
313  fscanf(file, "%d", &a); // expected-warning{{Call to function 'fscanf' is insecure}}
314  fscanf(file, "%s", buf); // expected-warning{{Call to function 'fscanf' is insecure}}
315  fscanf(file, "%4s", buf); // expected-warning{{Call to function 'fscanf' is insecure}}
316  fwscanf(file, (const wchar_t*) L"%s", wbuf); // expected-warning{{Call to function 'fwscanf' is insecure}}
317  sscanf("5", "%d", &a); // expected-warning{{Call to function 'sscanf' is insecure}}
318  sscanf("5", "%s", buf); // expected-warning{{Call to function 'sscanf' is insecure}}
319  sscanf("5", "%4s", buf); // expected-warning{{Call to function 'sscanf' is insecure}}
320  swscanf(L"5", (const wchar_t*) L"%s", wbuf); // expected-warning{{Call to function 'swscanf' is insecure}}
321  swprintf(L"5", 1, (const wchar_t*) L"%s", wbuf); // expected-warning{{Call to function 'swprintf' is insecure}}
322  snprintf("5", 1, "%s", buf); // expected-warning{{Call to function 'snprintf' is insecure}}
323  memcpy(buf, wbuf, 1); // expected-warning{{Call to function 'memcpy' is insecure}}
324  memmove(buf, wbuf, 1); // expected-warning{{Call to function 'memmove' is insecure}}
325  strncpy(buf, "a", 1); // expected-warning{{Call to function 'strncpy' is insecure}}
326  strncat(buf, "a", 1); // expected-warning{{Call to function 'strncat' is insecure}}
327  memset(buf, 'a', 1); // expected-warning{{Call to function 'memset' is insecure}}
328}
329
330void test_deprecated_or_unsafe_buffer_handling_2(const char *format, ...) {
331  char buf [5];
332  FILE *file;
333  va_list args;
334  va_start(args, format);
335  vsprintf(buf, format, args); // expected-warning{{Call to function 'vsprintf' is insecure}}
336  vscanf(format, args); // expected-warning{{Call to function 'vscanf' is insecure}}
337  vfscanf(file, format, args); // expected-warning{{Call to function 'vfscanf' is insecure}}
338  vsscanf("a", format, args); // expected-warning{{Call to function 'vsscanf' is insecure}}
339  vsnprintf("a", 1, format, args); // expected-warning{{Call to function 'vsnprintf' is insecure}}
340}
341
342void test_deprecated_or_unsafe_buffer_handling_3(const wchar_t *format, ...) {
343  wchar_t wbuf [5];
344  FILE *file;
345  va_list args;
346  va_start(args, format);
347  vwscanf(format, args); // expected-warning{{Call to function 'vwscanf' is insecure}}
348  vfwscanf(file, format, args); // expected-warning{{Call to function 'vfwscanf' is insecure}}
349  vswscanf(L"a", format, args); // expected-warning{{Call to function 'vswscanf' is insecure}}
350  vswprintf(L"a", 1, format, args); // expected-warning{{Call to function 'vswprintf' is insecure}}
351}
352