1*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 2*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -DUSE_BUILTINS -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 3*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 4*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 5*f4a2713aSLionel Sambuc 6*f4a2713aSLionel Sambuc#ifdef USE_BUILTINS 7*f4a2713aSLionel Sambuc# define BUILTIN(f) __builtin_ ## f 8*f4a2713aSLionel Sambuc#else /* USE_BUILTINS */ 9*f4a2713aSLionel Sambuc# define BUILTIN(f) f 10*f4a2713aSLionel Sambuc#endif /* USE_BUILTINS */ 11*f4a2713aSLionel Sambuc 12*f4a2713aSLionel Sambuctypedef typeof(sizeof(int)) size_t; 13*f4a2713aSLionel Sambuc 14*f4a2713aSLionel Sambuc 15*f4a2713aSLionel Sambuc// <rdar://problem/6336718> rule request: floating point used as loop 16*f4a2713aSLionel Sambuc// condition (FLP30-C, FLP-30-CPP) 17*f4a2713aSLionel Sambuc// 18*f4a2713aSLionel Sambuc// For reference: https://www.securecoding.cert.org/confluence/display/seccode/FLP30-C.+Do+not+use+floating+point+variables+as+loop+counters 19*f4a2713aSLionel Sambuc// 20*f4a2713aSLionel Sambucvoid test_float_condition() { 21*f4a2713aSLionel Sambuc for (float x = 0.1f; x <= 1.0f; x += 0.1f) {} // expected-warning{{Variable 'x' with floating point type 'float'}} 22*f4a2713aSLionel Sambuc for (float x = 100000001.0f; x <= 100000010.0f; x += 1.0f) {} // expected-warning{{Variable 'x' with floating point type 'float'}} 23*f4a2713aSLionel Sambuc for (float x = 100000001.0f; x <= 100000010.0f; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'float'}} 24*f4a2713aSLionel Sambuc for (double x = 100000001.0; x <= 100000010.0; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'double'}} 25*f4a2713aSLionel Sambuc for (double x = 100000001.0; ((x)) <= 100000010.0; ((x))++ ) {} // expected-warning{{Variable 'x' with floating point type 'double'}} 26*f4a2713aSLionel Sambuc 27*f4a2713aSLionel Sambuc for (double x = 100000001.0; 100000010.0 >= x; x = x + 1.0 ) {} // expected-warning{{Variable 'x' with floating point type 'double'}} 28*f4a2713aSLionel Sambuc 29*f4a2713aSLionel Sambuc int i = 0; 30*f4a2713aSLionel Sambuc for (double x = 100000001.0; ((x)) <= 100000010.0; ((x))++, ++i ) {} // expected-warning{{Variable 'x' with floating point type 'double'}} 31*f4a2713aSLionel Sambuc 32*f4a2713aSLionel Sambuc typedef float FooType; 33*f4a2713aSLionel Sambuc for (FooType x = 100000001.0f; x <= 100000010.0f; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'FooType'}} 34*f4a2713aSLionel Sambuc} 35*f4a2713aSLionel Sambuc 36*f4a2713aSLionel Sambuc// <rdar://problem/6335715> rule request: gets() buffer overflow 37*f4a2713aSLionel Sambuc// Part of recommendation: 300-BSI (buildsecurityin.us-cert.gov) 38*f4a2713aSLionel Sambucchar* gets(char *buf); 39*f4a2713aSLionel Sambuc 40*f4a2713aSLionel Sambucvoid test_gets() { 41*f4a2713aSLionel Sambuc char buff[1024]; 42*f4a2713aSLionel Sambuc gets(buff); // expected-warning{{Call to function 'gets' is extremely insecure as it can always result in a buffer overflow}} 43*f4a2713aSLionel Sambuc} 44*f4a2713aSLionel Sambuc 45*f4a2713aSLionel Sambucint getpw(unsigned int uid, char *buf); 46*f4a2713aSLionel Sambuc 47*f4a2713aSLionel Sambucvoid test_getpw() { 48*f4a2713aSLionel Sambuc char buff[1024]; 49*f4a2713aSLionel Sambuc getpw(2, buff); // expected-warning{{The getpw() function is dangerous as it may overflow the provided buffer. It is obsoleted by getpwuid()}} 50*f4a2713aSLionel Sambuc} 51*f4a2713aSLionel Sambuc 52*f4a2713aSLionel Sambuc// <rdar://problem/6337132> CWE-273: Failure to Check Whether Privileges Were 53*f4a2713aSLionel Sambuc// Dropped Successfully 54*f4a2713aSLionel Sambuctypedef unsigned int __uint32_t; 55*f4a2713aSLionel Sambuctypedef __uint32_t __darwin_uid_t; 56*f4a2713aSLionel Sambuctypedef __uint32_t __darwin_gid_t; 57*f4a2713aSLionel Sambuctypedef __darwin_uid_t uid_t; 58*f4a2713aSLionel Sambuctypedef __darwin_gid_t gid_t; 59*f4a2713aSLionel Sambucint setuid(uid_t); 60*f4a2713aSLionel Sambucint setregid(gid_t, gid_t); 61*f4a2713aSLionel Sambucint setreuid(uid_t, uid_t); 62*f4a2713aSLionel Sambucextern void check(int); 63*f4a2713aSLionel Sambucvoid abort(void); 64*f4a2713aSLionel Sambuc 65*f4a2713aSLionel Sambucvoid test_setuid() 66*f4a2713aSLionel Sambuc{ 67*f4a2713aSLionel Sambuc 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}} 68*f4a2713aSLionel Sambuc 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}} 69*f4a2713aSLionel Sambuc if (setuid (2) != 0) 70*f4a2713aSLionel Sambuc abort(); 71*f4a2713aSLionel Sambuc 72*f4a2713aSLionel Sambuc // Currently the 'setuid' check is not flow-sensitive, and only looks 73*f4a2713aSLionel Sambuc // at whether the function was called in a compound statement. This 74*f4a2713aSLionel Sambuc // will lead to false negatives, but there should be no false positives. 75*f4a2713aSLionel Sambuc int t = setuid(2); // no-warning 76*f4a2713aSLionel Sambuc (void)setuid (2); // no-warning 77*f4a2713aSLionel Sambuc 78*f4a2713aSLionel Sambuc check(setuid (2)); // no-warning 79*f4a2713aSLionel Sambuc 80*f4a2713aSLionel Sambuc 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}} 81*f4a2713aSLionel Sambuc 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}} 82*f4a2713aSLionel Sambuc} 83*f4a2713aSLionel Sambuc 84*f4a2713aSLionel Sambuc// <rdar://problem/6337100> CWE-338: Use of cryptographically weak prng 85*f4a2713aSLionel Sambuctypedef unsigned short *ushort_ptr_t; // Test that sugar doesn't confuse the warning. 86*f4a2713aSLionel Sambucint rand(void); 87*f4a2713aSLionel Sambucdouble drand48(void); 88*f4a2713aSLionel Sambucdouble erand48(unsigned short[3]); 89*f4a2713aSLionel Sambuclong jrand48(ushort_ptr_t); 90*f4a2713aSLionel Sambucvoid lcong48(unsigned short[7]); 91*f4a2713aSLionel Sambuclong lrand48(void); 92*f4a2713aSLionel Sambuclong mrand48(void); 93*f4a2713aSLionel Sambuclong nrand48(unsigned short[3]); 94*f4a2713aSLionel Sambuclong random(void); 95*f4a2713aSLionel Sambucint rand_r(unsigned *); 96*f4a2713aSLionel Sambuc 97*f4a2713aSLionel Sambucvoid test_rand() 98*f4a2713aSLionel Sambuc{ 99*f4a2713aSLionel Sambuc unsigned short a[7]; 100*f4a2713aSLionel Sambuc unsigned b; 101*f4a2713aSLionel Sambuc 102*f4a2713aSLionel Sambuc rand(); // expected-warning{{Function 'rand' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 103*f4a2713aSLionel Sambuc drand48(); // expected-warning{{Function 'drand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 104*f4a2713aSLionel Sambuc erand48(a); // expected-warning{{Function 'erand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 105*f4a2713aSLionel Sambuc jrand48(a); // expected-warning{{Function 'jrand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 106*f4a2713aSLionel Sambuc lcong48(a); // expected-warning{{Function 'lcong48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 107*f4a2713aSLionel Sambuc lrand48(); // expected-warning{{Function 'lrand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 108*f4a2713aSLionel Sambuc mrand48(); // expected-warning{{Function 'mrand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 109*f4a2713aSLionel Sambuc nrand48(a); // expected-warning{{Function 'nrand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 110*f4a2713aSLionel Sambuc rand_r(&b); // expected-warning{{Function 'rand_r' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 111*f4a2713aSLionel Sambuc random(); // expected-warning{{The 'random' function produces a sequence of values that an adversary may be able to predict. Use 'arc4random' instead}} 112*f4a2713aSLionel Sambuc} 113*f4a2713aSLionel Sambuc 114*f4a2713aSLionel Sambucchar *mktemp(char *buf); 115*f4a2713aSLionel Sambuc 116*f4a2713aSLionel Sambucvoid test_mktemp() { 117*f4a2713aSLionel Sambuc char *x = mktemp("/tmp/zxcv"); // expected-warning{{Call to function 'mktemp' is insecure as it always creates or uses insecure temporary file}} 118*f4a2713aSLionel Sambuc} 119*f4a2713aSLionel Sambuc 120*f4a2713aSLionel Sambuc 121*f4a2713aSLionel Sambuc//===----------------------------------------------------------------------=== 122*f4a2713aSLionel Sambuc// strcpy() 123*f4a2713aSLionel Sambuc//===----------------------------------------------------------------------=== 124*f4a2713aSLionel Sambuc#ifdef VARIANT 125*f4a2713aSLionel Sambuc 126*f4a2713aSLionel Sambuc#define __strcpy_chk BUILTIN(__strcpy_chk) 127*f4a2713aSLionel Sambucchar *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen); 128*f4a2713aSLionel Sambuc 129*f4a2713aSLionel Sambuc#define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1) 130*f4a2713aSLionel Sambuc 131*f4a2713aSLionel Sambuc#else /* VARIANT */ 132*f4a2713aSLionel Sambuc 133*f4a2713aSLionel Sambuc#define strcpy BUILTIN(strcpy) 134*f4a2713aSLionel Sambucchar *strcpy(char *restrict s1, const char *restrict s2); 135*f4a2713aSLionel Sambuc 136*f4a2713aSLionel Sambuc#endif /* VARIANT */ 137*f4a2713aSLionel Sambuc 138*f4a2713aSLionel Sambucvoid test_strcpy() { 139*f4a2713aSLionel Sambuc char x[4]; 140*f4a2713aSLionel Sambuc char *y; 141*f4a2713aSLionel Sambuc 142*f4a2713aSLionel Sambuc 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}} 143*f4a2713aSLionel Sambuc} 144*f4a2713aSLionel Sambuc 145*f4a2713aSLionel Sambuc//===----------------------------------------------------------------------=== 146*f4a2713aSLionel Sambuc// strcat() 147*f4a2713aSLionel Sambuc//===----------------------------------------------------------------------=== 148*f4a2713aSLionel Sambuc#ifdef VARIANT 149*f4a2713aSLionel Sambuc 150*f4a2713aSLionel Sambuc#define __strcat_chk BUILTIN(__strcat_chk) 151*f4a2713aSLionel Sambucchar *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen); 152*f4a2713aSLionel Sambuc 153*f4a2713aSLionel Sambuc#define strcat(a,b) __strcat_chk(a,b,(size_t)-1) 154*f4a2713aSLionel Sambuc 155*f4a2713aSLionel Sambuc#else /* VARIANT */ 156*f4a2713aSLionel Sambuc 157*f4a2713aSLionel Sambuc#define strcat BUILTIN(strcat) 158*f4a2713aSLionel Sambucchar *strcat(char *restrict s1, const char *restrict s2); 159*f4a2713aSLionel Sambuc 160*f4a2713aSLionel Sambuc#endif /* VARIANT */ 161*f4a2713aSLionel Sambuc 162*f4a2713aSLionel Sambucvoid test_strcat() { 163*f4a2713aSLionel Sambuc char x[4]; 164*f4a2713aSLionel Sambuc char *y; 165*f4a2713aSLionel Sambuc 166*f4a2713aSLionel Sambuc 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}} 167*f4a2713aSLionel Sambuc} 168*f4a2713aSLionel Sambuc 169*f4a2713aSLionel Sambuc//===----------------------------------------------------------------------=== 170*f4a2713aSLionel Sambuc// vfork() 171*f4a2713aSLionel Sambuc//===----------------------------------------------------------------------=== 172*f4a2713aSLionel Sambuctypedef int __int32_t; 173*f4a2713aSLionel Sambuctypedef __int32_t pid_t; 174*f4a2713aSLionel Sambucpid_t vfork(void); 175*f4a2713aSLionel Sambuc 176*f4a2713aSLionel Sambucvoid test_vfork() { 177*f4a2713aSLionel Sambuc vfork(); //expected-warning{{Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process}} 178*f4a2713aSLionel Sambuc} 179*f4a2713aSLionel Sambuc 180*f4a2713aSLionel Sambuc//===----------------------------------------------------------------------=== 181*f4a2713aSLionel Sambuc// mkstemp() 182*f4a2713aSLionel Sambuc//===----------------------------------------------------------------------=== 183*f4a2713aSLionel Sambuc 184*f4a2713aSLionel Sambucchar *mkdtemp(char *template); 185*f4a2713aSLionel Sambucint mkstemps(char *template, int suffixlen); 186*f4a2713aSLionel Sambucint mkstemp(char *template); 187*f4a2713aSLionel Sambucchar *mktemp(char *template); 188*f4a2713aSLionel Sambuc 189*f4a2713aSLionel Sambucvoid test_mkstemp() { 190*f4a2713aSLionel Sambuc 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)}} 191*f4a2713aSLionel Sambuc mkstemp("XXXXXX"); 192*f4a2713aSLionel Sambuc mkstemp("XXXXXXX"); 193*f4a2713aSLionel Sambuc mkstemps("XXXXXX", 0); 194*f4a2713aSLionel Sambuc mkstemps("XXXXXX", 1); // expected-warning {{5 'X's seen}} 195*f4a2713aSLionel Sambuc 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)}} 196*f4a2713aSLionel Sambuc mkdtemp("XX"); // expected-warning {{2 'X's seen}} 197*f4a2713aSLionel Sambuc mkstemp("X"); // expected-warning {{Call to 'mkstemp' should have at least 6 'X's in the format string to be secure (1 'X' seen)}} 198*f4a2713aSLionel Sambuc mkdtemp("XXXXXX"); 199*f4a2713aSLionel Sambuc} 200*f4a2713aSLionel Sambuc 201