1// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 %s -verify \ 2// RUN: -analyzer-checker=security.insecureAPI \ 3// RUN: -analyzer-checker=security.FloatLoopCounter 4 5// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 %s -verify \ 6// RUN: -DUSE_BUILTINS \ 7// RUN: -analyzer-checker=security.insecureAPI \ 8// RUN: -analyzer-checker=security.FloatLoopCounter 9 10// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 %s -verify \ 11// RUN: -DVARIANT \ 12// RUN: -analyzer-checker=security.insecureAPI \ 13// RUN: -analyzer-checker=security.FloatLoopCounter 14 15// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 %s -verify \ 16// RUN: -DUSE_BUILTINS -DVARIANT \ 17// RUN: -analyzer-checker=security.insecureAPI \ 18// RUN: -analyzer-checker=security.FloatLoopCounter 19 20// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi %s -verify \ 21// RUN: -analyzer-checker=security.insecureAPI \ 22// RUN: -analyzer-checker=security.FloatLoopCounter 23 24// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi %s -verify \ 25// RUN: -DUSE_BUILTINS \ 26// RUN: -analyzer-checker=security.insecureAPI \ 27// RUN: -analyzer-checker=security.FloatLoopCounter 28 29// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi %s -verify \ 30// RUN: -DVARIANT \ 31// RUN: -analyzer-checker=security.insecureAPI \ 32// RUN: -analyzer-checker=security.FloatLoopCounter 33 34// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi %s -verify \ 35// RUN: -DUSE_BUILTINS -DVARIANT \ 36// RUN: -analyzer-checker=security.insecureAPI \ 37// RUN: -analyzer-checker=security.FloatLoopCounter 38 39#ifdef USE_BUILTINS 40# define BUILTIN(f) __builtin_ ## f 41#else /* USE_BUILTINS */ 42# define BUILTIN(f) f 43#endif /* USE_BUILTINS */ 44 45#include "Inputs/system-header-simulator-for-valist.h" 46#include "Inputs/system-header-simulator-for-simple-stream.h" 47 48typedef typeof(sizeof(int)) size_t; 49 50 51// <rdar://problem/6336718> rule request: floating point used as loop 52// condition (FLP30-C, FLP-30-CPP) 53// 54// For reference: https://www.securecoding.cert.org/confluence/display/seccode/FLP30-C.+Do+not+use+floating+point+variables+as+loop+counters 55// 56void test_float_condition() { 57 for (float x = 0.1f; x <= 1.0f; x += 0.1f) {} // expected-warning{{Variable 'x' with floating point type 'float'}} 58 for (float x = 100000001.0f; x <= 100000010.0f; x += 1.0f) {} // expected-warning{{Variable 'x' with floating point type 'float'}} 59 for (float x = 100000001.0f; x <= 100000010.0f; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'float'}} 60 for (double x = 100000001.0; x <= 100000010.0; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'double'}} 61 for (double x = 100000001.0; ((x)) <= 100000010.0; ((x))++ ) {} // expected-warning{{Variable 'x' with floating point type 'double'}} 62 63 for (double x = 100000001.0; 100000010.0 >= x; x = x + 1.0 ) {} // expected-warning{{Variable 'x' with floating point type 'double'}} 64 65 int i = 0; 66 for (double x = 100000001.0; ((x)) <= 100000010.0; ((x))++, ++i ) {} // expected-warning{{Variable 'x' with floating point type 'double'}} 67 68 typedef float FooType; 69 for (FooType x = 100000001.0f; x <= 100000010.0f; x++ ) {} // expected-warning{{Variable 'x' with floating point type 'FooType'}} 70} 71 72// Obsolete function bcmp 73int bcmp(const void *, const void *, size_t); 74 75int test_bcmp(void *a, void *b, size_t n) { 76 return bcmp(a, b, n); // expected-warning{{The bcmp() function is obsoleted by memcmp()}} 77} 78 79// Obsolete function bcopy 80void bcopy(void *, void *, size_t); 81 82void test_bcopy(void *a, void *b, size_t n) { 83 bcopy(a, b, n); // expected-warning{{The bcopy() function is obsoleted by memcpy() or memmove(}} 84} 85 86// Obsolete function bzero 87void bzero(void *, size_t); 88 89void test_bzero(void *a, size_t n) { 90 bzero(a, n); // expected-warning{{The bzero() function is obsoleted by memset()}} 91} 92 93// <rdar://problem/6335715> rule request: gets() buffer overflow 94// Part of recommendation: 300-BSI (buildsecurityin.us-cert.gov) 95char* gets(char *buf); 96 97void test_gets() { 98 char buff[1024]; 99 gets(buff); // expected-warning{{Call to function 'gets' is extremely insecure as it can always result in a buffer overflow}} 100} 101 102int getpw(unsigned int uid, char *buf); 103 104void test_getpw() { 105 char buff[1024]; 106 getpw(2, buff); // expected-warning{{The getpw() function is dangerous as it may overflow the provided buffer. It is obsoleted by getpwuid()}} 107} 108 109// <rdar://problem/6337132> CWE-273: Failure to Check Whether Privileges Were 110// Dropped Successfully 111typedef unsigned int __uint32_t; 112typedef __uint32_t __darwin_uid_t; 113typedef __uint32_t __darwin_gid_t; 114typedef __darwin_uid_t uid_t; 115typedef __darwin_gid_t gid_t; 116int setuid(uid_t); 117int setregid(gid_t, gid_t); 118int setreuid(uid_t, uid_t); 119extern void check(int); 120void abort(void); 121 122void test_setuid() 123{ 124 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}} 125 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}} 126 if (setuid (2) != 0) 127 abort(); 128 129 // Currently the 'setuid' check is not flow-sensitive, and only looks 130 // at whether the function was called in a compound statement. This 131 // will lead to false negatives, but there should be no false positives. 132 int t = setuid(2); // no-warning 133 (void)setuid (2); // no-warning 134 135 check(setuid (2)); // no-warning 136 137 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}} 138 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}} 139} 140 141// <rdar://problem/6337100> CWE-338: Use of cryptographically weak prng 142typedef unsigned short *ushort_ptr_t; // Test that sugar doesn't confuse the warning. 143int rand(void); 144double drand48(void); 145double erand48(unsigned short[3]); 146long jrand48(ushort_ptr_t); 147void lcong48(unsigned short[7]); 148long lrand48(void); 149long mrand48(void); 150long nrand48(unsigned short[3]); 151long random(void); 152int rand_r(unsigned *); 153 154void test_rand() 155{ 156 unsigned short a[7]; 157 unsigned b; 158 159 rand(); // expected-warning{{Function 'rand' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 160 drand48(); // expected-warning{{Function 'drand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 161 erand48(a); // expected-warning{{Function 'erand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 162 jrand48(a); // expected-warning{{Function 'jrand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 163 lcong48(a); // expected-warning{{Function 'lcong48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 164 lrand48(); // expected-warning{{Function 'lrand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 165 mrand48(); // expected-warning{{Function 'mrand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 166 nrand48(a); // expected-warning{{Function 'nrand48' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 167 rand_r(&b); // expected-warning{{Function 'rand_r' is obsolete because it implements a poor random number generator. Use 'arc4random' instead}} 168 random(); // expected-warning{{The 'random' function produces a sequence of values that an adversary may be able to predict. Use 'arc4random' instead}} 169} 170 171char *mktemp(char *buf); 172 173void test_mktemp() { 174 char *x = mktemp("/tmp/zxcv"); // expected-warning{{Call to function 'mktemp' is insecure as it always creates or uses insecure temporary file}} 175} 176 177 178//===----------------------------------------------------------------------=== 179// strcpy() 180//===----------------------------------------------------------------------=== 181#ifdef VARIANT 182 183#define __strcpy_chk BUILTIN(__strcpy_chk) 184char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen); 185 186#define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1) 187 188#else /* VARIANT */ 189 190#define strcpy BUILTIN(strcpy) 191char *strcpy(char *restrict s1, const char *restrict s2); 192 193#endif /* VARIANT */ 194 195void test_strcpy() { 196 char x[4]; 197 char *y; 198 199 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}} 200} 201 202void test_strcpy_2() { 203 char x[4]; 204 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}} 205} 206 207void test_strcpy_safe() { 208 char x[5]; 209 strcpy(x, "abcd"); 210} 211 212void test_strcpy_safe_2() { 213 struct {char s1[100];} s; 214 strcpy(s.s1, "hello"); 215} 216 217//===----------------------------------------------------------------------=== 218// strcat() 219//===----------------------------------------------------------------------=== 220#ifdef VARIANT 221 222#define __strcat_chk BUILTIN(__strcat_chk) 223char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen); 224 225#define strcat(a,b) __strcat_chk(a,b,(size_t)-1) 226 227#else /* VARIANT */ 228 229#define strcat BUILTIN(strcat) 230char *strcat(char *restrict s1, const char *restrict s2); 231 232#endif /* VARIANT */ 233 234void test_strcat() { 235 char x[4]; 236 char *y; 237 238 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}} 239} 240 241//===----------------------------------------------------------------------=== 242// vfork() 243//===----------------------------------------------------------------------=== 244typedef int __int32_t; 245typedef __int32_t pid_t; 246pid_t vfork(void); 247 248void test_vfork() { 249 vfork(); //expected-warning{{Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process}} 250} 251 252//===----------------------------------------------------------------------=== 253// mkstemp() 254//===----------------------------------------------------------------------=== 255 256char *mkdtemp(char *template); 257int mkstemps(char *template, int suffixlen); 258int mkstemp(char *template); 259char *mktemp(char *template); 260 261void test_mkstemp() { 262 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)}} 263 mkstemp("XXXXXX"); 264 mkstemp("XXXXXXX"); 265 mkstemps("XXXXXX", 0); 266 mkstemps("XXXXXX", 1); // expected-warning {{5 'X's seen}} 267 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)}} 268 mkdtemp("XX"); // expected-warning {{2 'X's seen}} 269 mkstemp("X"); // expected-warning {{Call to 'mkstemp' should have at least 6 'X's in the format string to be secure (1 'X' seen)}} 270 mkdtemp("XXXXXX"); 271} 272 273 274//===----------------------------------------------------------------------=== 275// deprecated or unsafe buffer handling 276//===----------------------------------------------------------------------=== 277typedef int wchar_t; 278 279int sprintf(char *str, const char *format, ...); 280//int vsprintf (char *s, const char *format, va_list arg); 281int scanf(const char *format, ...); 282int wscanf(const wchar_t *format, ...); 283int fscanf(FILE *stream, const char *format, ...); 284int fwscanf(FILE *stream, const wchar_t *format, ...); 285int vscanf(const char *format, va_list arg); 286int vwscanf(const wchar_t *format, va_list arg); 287int vfscanf(FILE *stream, const char *format, va_list arg); 288int vfwscanf(FILE *stream, const wchar_t *format, va_list arg); 289int sscanf(const char *s, const char *format, ...); 290int swscanf(const wchar_t *ws, const wchar_t *format, ...); 291int vsscanf(const char *s, const char *format, va_list arg); 292int vswscanf(const wchar_t *ws, const wchar_t *format, va_list arg); 293int swprintf(wchar_t *ws, size_t len, const wchar_t *format, ...); 294int snprintf(char *s, size_t n, const char *format, ...); 295int vswprintf(wchar_t *ws, size_t len, const wchar_t *format, va_list arg); 296int vsnprintf(char *s, size_t n, const char *format, va_list arg); 297void *memcpy(void *destination, const void *source, size_t num); 298void *memmove(void *destination, const void *source, size_t num); 299char *strncpy(char *destination, const char *source, size_t num); 300char *strncat(char *destination, const char *source, size_t num); 301void *memset(void *ptr, int value, size_t num); 302 303void test_deprecated_or_unsafe_buffer_handling_1() { 304 char buf [5]; 305 wchar_t wbuf [5]; 306 int a; 307 FILE *file; 308 sprintf(buf, "a"); // expected-warning{{Call to function 'sprintf' is insecure}} 309 scanf("%d", &a); // expected-warning{{Call to function 'scanf' is insecure}} 310 scanf("%s", buf); // expected-warning{{Call to function 'scanf' is insecure}} 311 scanf("%4s", buf); // expected-warning{{Call to function 'scanf' is insecure}} 312 wscanf((const wchar_t*) L"%s", buf); // expected-warning{{Call to function 'wscanf' is insecure}} 313 fscanf(file, "%d", &a); // expected-warning{{Call to function 'fscanf' is insecure}} 314 fscanf(file, "%s", buf); // expected-warning{{Call to function 'fscanf' is insecure}} 315 fscanf(file, "%4s", buf); // expected-warning{{Call to function 'fscanf' is insecure}} 316 fwscanf(file, (const wchar_t*) L"%s", wbuf); // expected-warning{{Call to function 'fwscanf' is insecure}} 317 sscanf("5", "%d", &a); // expected-warning{{Call to function 'sscanf' is insecure}} 318 sscanf("5", "%s", buf); // expected-warning{{Call to function 'sscanf' is insecure}} 319 sscanf("5", "%4s", buf); // expected-warning{{Call to function 'sscanf' is insecure}} 320 swscanf(L"5", (const wchar_t*) L"%s", wbuf); // expected-warning{{Call to function 'swscanf' is insecure}} 321 swprintf(L"5", 1, (const wchar_t*) L"%s", wbuf); // expected-warning{{Call to function 'swprintf' is insecure}} 322 snprintf("5", 1, "%s", buf); // expected-warning{{Call to function 'snprintf' is insecure}} 323 memcpy(buf, wbuf, 1); // expected-warning{{Call to function 'memcpy' is insecure}} 324 memmove(buf, wbuf, 1); // expected-warning{{Call to function 'memmove' is insecure}} 325 strncpy(buf, "a", 1); // expected-warning{{Call to function 'strncpy' is insecure}} 326 strncat(buf, "a", 1); // expected-warning{{Call to function 'strncat' is insecure}} 327 memset(buf, 'a', 1); // expected-warning{{Call to function 'memset' is insecure}} 328} 329 330void test_deprecated_or_unsafe_buffer_handling_2(const char *format, ...) { 331 char buf [5]; 332 FILE *file; 333 va_list args; 334 va_start(args, format); 335 vsprintf(buf, format, args); // expected-warning{{Call to function 'vsprintf' is insecure}} 336 vscanf(format, args); // expected-warning{{Call to function 'vscanf' is insecure}} 337 vfscanf(file, format, args); // expected-warning{{Call to function 'vfscanf' is insecure}} 338 vsscanf("a", format, args); // expected-warning{{Call to function 'vsscanf' is insecure}} 339 vsnprintf("a", 1, format, args); // expected-warning{{Call to function 'vsnprintf' is insecure}} 340} 341 342void test_deprecated_or_unsafe_buffer_handling_3(const wchar_t *format, ...) { 343 wchar_t wbuf [5]; 344 FILE *file; 345 va_list args; 346 va_start(args, format); 347 vwscanf(format, args); // expected-warning{{Call to function 'vwscanf' is insecure}} 348 vfwscanf(file, format, args); // expected-warning{{Call to function 'vfwscanf' is insecure}} 349 vswscanf(L"a", format, args); // expected-warning{{Call to function 'vswscanf' is insecure}} 350 vswprintf(L"a", 1, format, args); // expected-warning{{Call to function 'vswprintf' is insecure}} 351} 352