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