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