Home | History | Annotate | Download | only in Analysis
      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 
     16 typedef 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 //
     24 void 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)
     42 char* gets(char *buf);
     43 
     44 void 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 
     49 int getpw(unsigned int uid, char *buf);
     50 
     51 void 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
     58 typedef unsigned int __uint32_t;
     59 typedef __uint32_t __darwin_uid_t;
     60 typedef __uint32_t __darwin_gid_t;
     61 typedef __darwin_uid_t uid_t;
     62 typedef __darwin_gid_t gid_t;
     63 int setuid(uid_t);
     64 int setregid(gid_t, gid_t);
     65 int setreuid(uid_t, uid_t);
     66 extern void check(int);
     67 void abort(void);
     68 
     69 void 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
     89 typedef  unsigned short *ushort_ptr_t;  // Test that sugar doesn't confuse the warning.
     90 int      rand(void);
     91 double   drand48(void);
     92 double   erand48(unsigned short[3]);
     93 long     jrand48(ushort_ptr_t);
     94 void     lcong48(unsigned short[7]);
     95 long     lrand48(void);
     96 long     mrand48(void);
     97 long     nrand48(unsigned short[3]);
     98 long     random(void);
     99 int      rand_r(unsigned *);
    100 
    101 void 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 
    118 char *mktemp(char *buf);
    119 
    120 void 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)
    131 char *__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)
    138 char *strcpy(char *restrict s1, const char *restrict s2);
    139 
    140 #endif /* VARIANT */
    141 
    142 void 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)
    155 char *__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)
    162 char *strcat(char *restrict s1, const char *restrict s2);
    163 
    164 #endif /* VARIANT */
    165 
    166 void 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 //===----------------------------------------------------------------------===
    176 typedef int __int32_t;
    177 typedef __int32_t pid_t;
    178 pid_t vfork(void);
    179 
    180 void 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 
    188 char *mkdtemp(char *template);
    189 int mkstemps(char *template, int suffixlen);
    190 int mkstemp(char *template);
    191 char *mktemp(char *template);
    192 
    193 void 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