bstring.c revision 6dd4dffe1090e820e9b5b25eee8ad3907a1aa679
1// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.CString -analyzer-check-objc-mem -analyzer-store=region -verify %s 2// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core.experimental.CString -analyzer-check-objc-mem -analyzer-store=region -verify %s 3// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core.experimental.CString -analyzer-check-objc-mem -analyzer-store=region -verify %s 4// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core.experimental.CString -analyzer-check-objc-mem -analyzer-store=region -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// memcpy() 31//===----------------------------------------------------------------------=== 32 33#ifdef VARIANT 34 35#define __memcpy_chk BUILTIN(__memcpy_chk) 36void *__memcpy_chk(void *restrict s1, const void *restrict s2, size_t n, 37 size_t destlen); 38 39#define memcpy(a,b,c) __memcpy_chk(a,b,c,(size_t)-1) 40 41#else /* VARIANT */ 42 43#define memcpy BUILTIN(memcpy) 44void *memcpy(void *restrict s1, const void *restrict s2, size_t n); 45 46#endif /* VARIANT */ 47 48 49void memcpy0 () { 50 char src[] = {1, 2, 3, 4}; 51 char dst[4] = {0}; 52 53 memcpy(dst, src, 4); // no-warning 54 55 if (memcpy(dst, src, 4) != dst) { 56 (void)*(char*)0; // no-warning 57 } 58 59 if (dst[0] != 0) 60 (void)*(char*)0; // expected-warning{{null}} 61} 62 63void memcpy1 () { 64 char src[] = {1, 2, 3, 4}; 65 char dst[10]; 66 67 memcpy(dst, src, 5); // expected-warning{{Byte string function accesses out-of-bound array element}} 68} 69 70void memcpy2 () { 71 char src[] = {1, 2, 3, 4}; 72 char dst[1]; 73 74 memcpy(dst, src, 4); // expected-warning{{Byte string function overflows destination buffer}} 75} 76 77void memcpy3 () { 78 char src[] = {1, 2, 3, 4}; 79 char dst[3]; 80 81 memcpy(dst+1, src+2, 2); // no-warning 82} 83 84void memcpy4 () { 85 char src[] = {1, 2, 3, 4}; 86 char dst[10]; 87 88 memcpy(dst+2, src+2, 3); // expected-warning{{Byte string function accesses out-of-bound array element}} 89} 90 91void memcpy5() { 92 char src[] = {1, 2, 3, 4}; 93 char dst[3]; 94 95 memcpy(dst+2, src+2, 2); // expected-warning{{Byte string function overflows destination buffer}} 96} 97 98void memcpy6() { 99 int a[4] = {0}; 100 memcpy(a, a, 8); // expected-warning{{overlapping}} 101} 102 103void memcpy7() { 104 int a[4] = {0}; 105 memcpy(a+2, a+1, 8); // expected-warning{{overlapping}} 106} 107 108void memcpy8() { 109 int a[4] = {0}; 110 memcpy(a+1, a+2, 8); // expected-warning{{overlapping}} 111} 112 113void memcpy9() { 114 int a[4] = {0}; 115 memcpy(a+2, a+1, 4); // no-warning 116 memcpy(a+1, a+2, 4); // no-warning 117} 118 119void memcpy10() { 120 char a[4] = {0}; 121 memcpy(0, a, 4); // expected-warning{{Null pointer argument in call to byte string function}} 122} 123 124void memcpy11() { 125 char a[4] = {0}; 126 memcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to byte string function}} 127} 128 129void memcpy12() { 130 char a[4] = {0}; 131 memcpy(0, a, 0); // no-warning 132 memcpy(a, 0, 0); // no-warning 133} 134 135//===----------------------------------------------------------------------=== 136// memmove() 137//===----------------------------------------------------------------------=== 138 139#ifdef VARIANT 140 141#define __memmove_chk BUILTIN(__memmove_chk) 142void *__memmove_chk(void *s1, const void *s2, size_t n, size_t destlen); 143 144#define memmove(a,b,c) __memmove_chk(a,b,c,(size_t)-1) 145 146#else /* VARIANT */ 147 148#define memmove BUILTIN(memmove) 149void *memmove(void *s1, const void *s2, size_t n); 150 151#endif /* VARIANT */ 152 153 154void memmove0 () { 155 char src[] = {1, 2, 3, 4}; 156 char dst[4] = {0}; 157 158 memmove(dst, src, 4); // no-warning 159 160 if (memmove(dst, src, 4) != dst) { 161 (void)*(char*)0; // no-warning 162 } 163 164 if (dst[0] != 0) 165 (void)*(char*)0; // expected-warning{{null}} 166} 167 168void memmove1 () { 169 char src[] = {1, 2, 3, 4}; 170 char dst[10]; 171 172 memmove(dst, src, 5); // expected-warning{{out-of-bound}} 173} 174 175void memmove2 () { 176 char src[] = {1, 2, 3, 4}; 177 char dst[1]; 178 179 memmove(dst, src, 4); // expected-warning{{overflow}} 180} 181 182//===----------------------------------------------------------------------=== 183// memcmp() 184//===----------------------------------------------------------------------=== 185 186#ifdef VARIANT 187 188#define bcmp BUILTIN(bcmp) 189// __builtin_bcmp is not defined with const in Builtins.def. 190int bcmp(/*const*/ void *s1, /*const*/ void *s2, size_t n); 191#define memcmp bcmp 192 193#else /* VARIANT */ 194 195#define memcmp BUILTIN(memcmp) 196int memcmp(const void *s1, const void *s2, size_t n); 197 198#endif /* VARIANT */ 199 200 201void memcmp0 () { 202 char a[] = {1, 2, 3, 4}; 203 char b[4] = { 0 }; 204 205 memcmp(a, b, 4); // no-warning 206} 207 208void memcmp1 () { 209 char a[] = {1, 2, 3, 4}; 210 char b[10] = { 0 }; 211 212 memcmp(a, b, 5); // expected-warning{{out-of-bound}} 213} 214 215void memcmp2 () { 216 char a[] = {1, 2, 3, 4}; 217 char b[1] = { 0 }; 218 219 memcmp(a, b, 4); // expected-warning{{out-of-bound}} 220} 221 222void memcmp3 () { 223 char a[] = {1, 2, 3, 4}; 224 225 if (memcmp(a, a, 4)) 226 (void)*(char*)0; // no-warning 227} 228 229void memcmp4 (char *input) { 230 char a[] = {1, 2, 3, 4}; 231 232 if (memcmp(a, input, 4)) 233 (void)*(char*)0; // expected-warning{{null}} 234} 235 236void memcmp5 (char *input) { 237 char a[] = {1, 2, 3, 4}; 238 239 if (memcmp(a, 0, 0)) // no-warning 240 (void)*(char*)0; // no-warning 241 if (memcmp(0, a, 0)) // no-warning 242 (void)*(char*)0; // no-warning 243 if (memcmp(a, input, 0)) // no-warning 244 (void)*(char*)0; // no-warning 245} 246 247void memcmp6 (char *a, char *b, size_t n) { 248 int result = memcmp(a, b, n); 249 if (result != 0) 250 return; 251 if (n == 0) 252 (void)*(char*)0; // expected-warning{{null}} 253} 254 255int memcmp7 (char *a, size_t x, size_t y, size_t n) { 256 // We used to crash when either of the arguments was unknown. 257 return memcmp(a, &a[x*y], n) + 258 memcmp(&a[x*y], a, n); 259} 260 261//===----------------------------------------------------------------------=== 262// bcopy() 263//===----------------------------------------------------------------------=== 264 265#define bcopy BUILTIN(bcopy) 266// __builtin_bcopy is not defined with const in Builtins.def. 267void bcopy(/*const*/ void *s1, void *s2, size_t n); 268 269 270void bcopy0 () { 271 char src[] = {1, 2, 3, 4}; 272 char dst[4] = {0}; 273 274 bcopy(src, dst, 4); // no-warning 275 276 if (dst[0] != 0) 277 (void)*(char*)0; // expected-warning{{null}} 278} 279 280void bcopy1 () { 281 char src[] = {1, 2, 3, 4}; 282 char dst[10]; 283 284 bcopy(src, dst, 5); // expected-warning{{out-of-bound}} 285} 286 287void bcopy2 () { 288 char src[] = {1, 2, 3, 4}; 289 char dst[1]; 290 291 bcopy(src, dst, 4); // expected-warning{{overflow}} 292} 293