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