bstring.c revision ccbf7eebc8425429e8fd9f9124770f86a74864eb
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 -DCHECK -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s 4// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DCHECK -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 having a checking variant, which checks if there is overflow 11// using a flow-insensitive calculation of the buffer size. If CHECK is defined, 12// use those instead to make sure they are still checked by the analyzer. 13 14// Some functions are implemented as builtins. These should be #defined as 15// BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined. 16 17// Functions that have both checking and builtin variants should be declared 18// carefully! See memcpy() for an example. 19 20#ifdef USE_BUILTINS 21# define BUILTIN(f) __builtin_ ## f 22#else /* USE_BUILTINS */ 23# define BUILTIN(f) f 24#endif /* USE_BUILTINS */ 25 26typedef typeof(sizeof(int)) size_t; 27 28//===----------------------------------------------------------------------=== 29// memcpy() 30//===----------------------------------------------------------------------=== 31 32#ifdef CHECK 33 34#define __memcpy_chk BUILTIN(__memcpy_chk) 35void *__memcpy_chk(void *restrict s1, const void *restrict s2, size_t n, 36 size_t destlen); 37 38#define memcpy(a,b,c) __memcpy_chk(a,b,c,(size_t)-1) 39 40#else /* CHECK */ 41 42#define memcpy BUILTIN(memcpy) 43void *memcpy(void *restrict s1, const void *restrict s2, size_t n); 44 45#endif /* CHECK */ 46 47 48void memcpy0 () { 49 char src[] = {1, 2, 3, 4}; 50 char dst[4]; 51 52 memcpy(dst, src, 4); // no-warning 53 54 if (memcpy(dst, src, 4) != dst) { 55 (void)*(char*)0; // no-warning -- should be unreachable 56 } 57} 58 59void memcpy1 () { 60 char src[] = {1, 2, 3, 4}; 61 char dst[10]; 62 63 memcpy(dst, src, 5); // expected-warning{{out-of-bound}} 64} 65 66void memcpy2 () { 67 char src[] = {1, 2, 3, 4}; 68 char dst[1]; 69 70 memcpy(dst, src, 4); // expected-warning{{out-of-bound}} 71} 72 73void memcpy3 () { 74 char src[] = {1, 2, 3, 4}; 75 char dst[3]; 76 77 memcpy(dst+1, src+2, 2); // no-warning 78} 79 80void memcpy4 () { 81 char src[] = {1, 2, 3, 4}; 82 char dst[10]; 83 84 memcpy(dst+2, src+2, 3); // expected-warning{{out-of-bound}} 85} 86 87void memcpy5() { 88 char src[] = {1, 2, 3, 4}; 89 char dst[3]; 90 91 memcpy(dst+2, src+2, 2); // expected-warning{{out-of-bound}} 92} 93 94void memcpy6() { 95 int a[4] = {0}; 96 memcpy(a, a, 8); // expected-warning{{overlapping}} 97} 98 99void memcpy7() { 100 int a[4] = {0}; 101 memcpy(a+2, a+1, 8); // expected-warning{{overlapping}} 102} 103 104void memcpy8() { 105 int a[4] = {0}; 106 memcpy(a+1, a+2, 8); // expected-warning{{overlapping}} 107} 108 109void memcpy9() { 110 int a[4] = {0}; 111 memcpy(a+2, a+1, 4); // no-warning 112 memcpy(a+1, a+2, 4); // no-warning 113} 114 115//===----------------------------------------------------------------------=== 116// memmove() 117//===----------------------------------------------------------------------=== 118 119#ifdef CHECK 120 121#define __memmove_chk BUILTIN(__memmove_chk) 122void *__memmove_chk(void *s1, const void *s2, size_t n, size_t destlen); 123 124#define memmove(a,b,c) __memmove_chk(a,b,c,(size_t)-1) 125 126#else /* CHECK */ 127 128#define memmove BUILTIN(memmove) 129void *memmove(void *s1, const void *s2, size_t n); 130 131#endif /* CHECK */ 132 133 134void memmove0 () { 135 char src[] = {1, 2, 3, 4}; 136 char dst[4]; 137 138 memmove(dst, src, 4); // no-warning 139 140 if (memmove(dst, src, 4) != dst) { 141 (void)*(char*)0; // no-warning -- should be unreachable 142 } 143} 144 145void memmove1 () { 146 char src[] = {1, 2, 3, 4}; 147 char dst[10]; 148 149 memmove(dst, src, 5); // expected-warning{{out-of-bound}} 150} 151 152void memmove2 () { 153 char src[] = {1, 2, 3, 4}; 154 char dst[1]; 155 156 memmove(dst, src, 4); // expected-warning{{out-of-bound}} 157} 158 159//===----------------------------------------------------------------------=== 160// bcopy() 161//===----------------------------------------------------------------------=== 162 163#define bcopy BUILTIN(bcopy) 164// __builtin_bcopy is not defined with const in Builtins.def. 165void bcopy(/*const*/ void *s1, void *s2, size_t n); 166 167 168void bcopy0 () { 169 char src[] = {1, 2, 3, 4}; 170 char dst[4]; 171 172 bcopy(src, dst, 4); // no-warning 173} 174 175void bcopy1 () { 176 char src[] = {1, 2, 3, 4}; 177 char dst[10]; 178 179 bcopy(src, dst, 5); // expected-warning{{out-of-bound}} 180} 181 182void bcopy2 () { 183 char src[] = {1, 2, 3, 4}; 184 char dst[1]; 185 186 bcopy(src, dst, 4); // expected-warning{{out-of-bound}} 187} 188