1// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 2// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -DUSE_BUILTINS -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 3// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 4// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 5// RUN: %clang_cc1 -triple x86_64-unknown-cloudabi -analyze -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 6// RUN: %clang_cc1 -triple x86_64-unknown-cloudabi -analyze -DUSE_BUILTINS -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 7// RUN: %clang_cc1 -triple x86_64-unknown-cloudabi -analyze -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify 8// RUN: %clang_cc1 -triple x86_64-unknown-cloudabi -analyze -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 149//===----------------------------------------------------------------------=== 150// strcat() 151//===----------------------------------------------------------------------=== 152#ifdef VARIANT 153 154#define __strcat_chk BUILTIN(__strcat_chk) 155char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen); 156 157#define strcat(a,b) __strcat_chk(a,b,(size_t)-1) 158 159#else /* VARIANT */ 160 161#define strcat BUILTIN(strcat) 162char *strcat(char *restrict s1, const char *restrict s2); 163 164#endif /* VARIANT */ 165 166void test_strcat() { 167 char x[4]; 168 char *y; 169 170 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}} 171} 172 173//===----------------------------------------------------------------------=== 174// vfork() 175//===----------------------------------------------------------------------=== 176typedef int __int32_t; 177typedef __int32_t pid_t; 178pid_t vfork(void); 179 180void test_vfork() { 181 vfork(); //expected-warning{{Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process}} 182} 183 184//===----------------------------------------------------------------------=== 185// mkstemp() 186//===----------------------------------------------------------------------=== 187 188char *mkdtemp(char *template); 189int mkstemps(char *template, int suffixlen); 190int mkstemp(char *template); 191char *mktemp(char *template); 192 193void test_mkstemp() { 194 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)}} 195 mkstemp("XXXXXX"); 196 mkstemp("XXXXXXX"); 197 mkstemps("XXXXXX", 0); 198 mkstemps("XXXXXX", 1); // expected-warning {{5 'X's seen}} 199 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)}} 200 mkdtemp("XX"); // expected-warning {{2 'X's seen}} 201 mkstemp("X"); // expected-warning {{Call to 'mkstemp' should have at least 6 'X's in the format string to be secure (1 'X' seen)}} 202 mkdtemp("XXXXXX"); 203} 204 205