Clang Project

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