string.c revision a5261549754fab80e30e893d8fa706bfb31e430a
1// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s 2// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s 3// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s 4// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s 5 6//===----------------------------------------------------------------------=== 7// Declarations 8//===----------------------------------------------------------------------=== 9 10// Some functions are so similar to each other that they follow the same code 11// path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is 12// defined, make sure to use the variants instead to make sure they are still 13// checked by the analyzer. 14 15// Some functions are implemented as builtins. These should be #defined as 16// BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined. 17 18// Functions that have variants and are also availabe as builtins should be 19// declared carefully! See memcpy() for an example. 20 21#ifdef USE_BUILTINS 22# define BUILTIN(f) __builtin_ ## f 23#else /* USE_BUILTINS */ 24# define BUILTIN(f) f 25#endif /* USE_BUILTINS */ 26 27typedef typeof(sizeof(int)) size_t; 28 29//===----------------------------------------------------------------------=== 30// strlen() 31//===----------------------------------------------------------------------=== 32 33#define strlen BUILTIN(strlen) 34size_t strlen(const char *s); 35 36void strlen_constant0() { 37 if (strlen("123") != 3) 38 (void)*(char*)0; // no-warning 39} 40 41void strlen_constant1() { 42 const char *a = "123"; 43 if (strlen(a) != 3) 44 (void)*(char*)0; // no-warning 45} 46 47void strlen_constant2(char x) { 48 char a[] = "123"; 49 if (strlen(a) != 3) 50 (void)*(char*)0; // no-warning 51 a[0] = x; 52 if (strlen(a) != 3) 53 (void)*(char*)0; // expected-warning{{null}} 54} 55 56size_t strlen_null() { 57 return strlen(0); // expected-warning{{Null pointer argument in call to byte string function}} 58} 59 60size_t strlen_fn() { 61 return strlen((char*)&strlen_fn); // expected-warning{{Argument to byte string function is the address of the function 'strlen_fn', which is not a null-terminated string}} 62} 63 64size_t strlen_nonloc() { 65label: 66 return strlen((char*)&&label); // expected-warning{{Argument to byte string function is the address of the label 'label', which is not a null-terminated string}} 67} 68 69void strlen_subregion() { 70 struct two_strings { char a[2], b[2] }; 71 extern void use_two_strings(struct two_strings *); 72 73 struct two_strings z; 74 use_two_strings(&z); 75 76 size_t a = strlen(z.a); 77 z.b[0] = 5; 78 size_t b = strlen(z.a); 79 if (a == 0 && b != 0) 80 (void)*(char*)0; // expected-warning{{never executed}} 81 82 use_two_strings(&z); 83 84 size_t c = strlen(z.a); 85 if (a == 0 && c != 0) 86 (void)*(char*)0; // expected-warning{{null}} 87} 88 89extern void use_string(char *); 90void strlen_argument(char *x) { 91 size_t a = strlen(x); 92 size_t b = strlen(x); 93 if (a == 0 && b != 0) 94 (void)*(char*)0; // expected-warning{{never executed}} 95 96 use_string(x); 97 98 size_t c = strlen(x); 99 if (a == 0 && c != 0) 100 (void)*(char*)0; // expected-warning{{null}} 101} 102 103extern char global_str[]; 104void strlen_global() { 105 size_t a = strlen(global_str); 106 size_t b = strlen(global_str); 107 if (a == 0 && b != 0) 108 (void)*(char*)0; // expected-warning{{never executed}} 109 110 // Call a function with unknown effects, which should invalidate globals. 111 use_string(0); 112 113 size_t c = strlen(global_str); 114 if (a == 0 && c != 0) 115 (void)*(char*)0; // expected-warning{{null}} 116} 117 118void strlen_indirect(char *x) { 119 size_t a = strlen(x); 120 char *p = x; 121 char **p2 = &p; 122 size_t b = strlen(x); 123 if (a == 0 && b != 0) 124 (void)*(char*)0; // expected-warning{{never executed}} 125 126 extern void use_string_ptr(char*const*); 127 use_string_ptr(p2); 128 129 size_t c = strlen(x); 130 if (a == 0 && c != 0) 131 (void)*(char*)0; // expected-warning{{null}} 132} 133 134void strlen_liveness(const char *x) { 135 if (strlen(x) < 5) 136 return; 137 if (strlen(x) < 5) 138 (void)*(char*)0; // no-warning 139} 140