1 //===-- sanitizer_libc.cc -------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is shared between AddressSanitizer and ThreadSanitizer 11 // run-time libraries. See sanitizer_libc.h for details. 12 //===----------------------------------------------------------------------===// 13 #include "sanitizer_allocator_internal.h" 14 #include "sanitizer_common.h" 15 #include "sanitizer_libc.h" 16 17 namespace __sanitizer { 18 19 // Make the compiler think that something is going on there. 20 static inline void break_optimization(void *arg) { 21 #if _MSC_VER 22 // FIXME: make sure this is actually enough. 23 __asm; 24 #else 25 __asm__ __volatile__("" : : "r" (arg) : "memory"); 26 #endif 27 } 28 29 s64 internal_atoll(const char *nptr) { 30 return internal_simple_strtoll(nptr, (char**)0, 10); 31 } 32 33 void *internal_memchr(const void *s, int c, uptr n) { 34 const char* t = (char*)s; 35 for (uptr i = 0; i < n; ++i, ++t) 36 if (*t == c) 37 return (void*)t; 38 return 0; 39 } 40 41 int internal_memcmp(const void* s1, const void* s2, uptr n) { 42 const char* t1 = (char*)s1; 43 const char* t2 = (char*)s2; 44 for (uptr i = 0; i < n; ++i, ++t1, ++t2) 45 if (*t1 != *t2) 46 return *t1 < *t2 ? -1 : 1; 47 return 0; 48 } 49 50 void *internal_memcpy(void *dest, const void *src, uptr n) { 51 char *d = (char*)dest; 52 char *s = (char*)src; 53 for (uptr i = 0; i < n; ++i) 54 d[i] = s[i]; 55 return dest; 56 } 57 58 void *internal_memmove(void *dest, const void *src, uptr n) { 59 char *d = (char*)dest; 60 char *s = (char*)src; 61 sptr i, signed_n = (sptr)n; 62 CHECK_GE(signed_n, 0); 63 if (d < s) { 64 for (i = 0; i < signed_n; ++i) 65 d[i] = s[i]; 66 } else { 67 if (d > s && signed_n > 0) 68 for (i = signed_n - 1; i >= 0 ; --i) { 69 d[i] = s[i]; 70 } 71 } 72 return dest; 73 } 74 75 // Semi-fast bzero for 16-aligned data. Still far from peak performance. 76 void internal_bzero_aligned16(void *s, uptr n) { 77 struct S16 { u64 a, b; } ALIGNED(16); 78 CHECK_EQ((reinterpret_cast<uptr>(s) | n) & 15, 0); 79 for (S16 *p = reinterpret_cast<S16*>(s), *end = p + n / 16; p < end; p++) { 80 p->a = p->b = 0; 81 break_optimization(0); // Make sure this does not become memset. 82 } 83 } 84 85 void *internal_memset(void* s, int c, uptr n) { 86 // The next line prevents Clang from making a call to memset() instead of the 87 // loop below. 88 // FIXME: building the runtime with -ffreestanding is a better idea. However 89 // there currently are linktime problems due to PR12396. 90 char volatile *t = (char*)s; 91 for (uptr i = 0; i < n; ++i, ++t) { 92 *t = c; 93 } 94 return s; 95 } 96 97 uptr internal_strcspn(const char *s, const char *reject) { 98 uptr i; 99 for (i = 0; s[i]; i++) { 100 if (internal_strchr(reject, s[i]) != 0) 101 return i; 102 } 103 return i; 104 } 105 106 char* internal_strdup(const char *s) { 107 uptr len = internal_strlen(s); 108 char *s2 = (char*)InternalAlloc(len + 1); 109 internal_memcpy(s2, s, len); 110 s2[len] = 0; 111 return s2; 112 } 113 114 int internal_strcmp(const char *s1, const char *s2) { 115 while (true) { 116 unsigned c1 = *s1; 117 unsigned c2 = *s2; 118 if (c1 != c2) return (c1 < c2) ? -1 : 1; 119 if (c1 == 0) break; 120 s1++; 121 s2++; 122 } 123 return 0; 124 } 125 126 int internal_strncmp(const char *s1, const char *s2, uptr n) { 127 for (uptr i = 0; i < n; i++) { 128 unsigned c1 = *s1; 129 unsigned c2 = *s2; 130 if (c1 != c2) return (c1 < c2) ? -1 : 1; 131 if (c1 == 0) break; 132 s1++; 133 s2++; 134 } 135 return 0; 136 } 137 138 char* internal_strchr(const char *s, int c) { 139 while (true) { 140 if (*s == (char)c) 141 return (char*)s; 142 if (*s == 0) 143 return 0; 144 s++; 145 } 146 } 147 148 char *internal_strchrnul(const char *s, int c) { 149 char *res = internal_strchr(s, c); 150 if (!res) 151 res = (char*)s + internal_strlen(s); 152 return res; 153 } 154 155 char *internal_strrchr(const char *s, int c) { 156 const char *res = 0; 157 for (uptr i = 0; s[i]; i++) { 158 if (s[i] == c) res = s + i; 159 } 160 return (char*)res; 161 } 162 163 uptr internal_strlen(const char *s) { 164 uptr i = 0; 165 while (s[i]) i++; 166 return i; 167 } 168 169 char *internal_strncat(char *dst, const char *src, uptr n) { 170 uptr len = internal_strlen(dst); 171 uptr i; 172 for (i = 0; i < n && src[i]; i++) 173 dst[len + i] = src[i]; 174 dst[len + i] = 0; 175 return dst; 176 } 177 178 char *internal_strncpy(char *dst, const char *src, uptr n) { 179 uptr i; 180 for (i = 0; i < n && src[i]; i++) 181 dst[i] = src[i]; 182 internal_memset(dst + i, '\0', n - i); 183 return dst; 184 } 185 186 uptr internal_strnlen(const char *s, uptr maxlen) { 187 uptr i = 0; 188 while (i < maxlen && s[i]) i++; 189 return i; 190 } 191 192 char *internal_strstr(const char *haystack, const char *needle) { 193 // This is O(N^2), but we are not using it in hot places. 194 uptr len1 = internal_strlen(haystack); 195 uptr len2 = internal_strlen(needle); 196 if (len1 < len2) return 0; 197 for (uptr pos = 0; pos <= len1 - len2; pos++) { 198 if (internal_memcmp(haystack + pos, needle, len2) == 0) 199 return (char*)haystack + pos; 200 } 201 return 0; 202 } 203 204 s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) { 205 CHECK_EQ(base, 10); 206 while (IsSpace(*nptr)) nptr++; 207 int sgn = 1; 208 u64 res = 0; 209 bool have_digits = false; 210 char *old_nptr = (char*)nptr; 211 if (*nptr == '+') { 212 sgn = 1; 213 nptr++; 214 } else if (*nptr == '-') { 215 sgn = -1; 216 nptr++; 217 } 218 while (IsDigit(*nptr)) { 219 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX; 220 int digit = ((*nptr) - '0'); 221 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX; 222 have_digits = true; 223 nptr++; 224 } 225 if (endptr != 0) { 226 *endptr = (have_digits) ? (char*)nptr : old_nptr; 227 } 228 if (sgn > 0) { 229 return (s64)(Min((u64)INT64_MAX, res)); 230 } else { 231 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1); 232 } 233 } 234 235 bool mem_is_zero(const char *beg, uptr size) { 236 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check. 237 const char *end = beg + size; 238 uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr)); 239 uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr)); 240 uptr all = 0; 241 // Prologue. 242 for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++) 243 all |= *mem; 244 // Aligned loop. 245 for (; aligned_beg < aligned_end; aligned_beg++) 246 all |= *aligned_beg; 247 // Epilogue. 248 if ((char*)aligned_end >= beg) 249 for (const char *mem = (char*)aligned_end; mem < end; mem++) 250 all |= *mem; 251 return all == 0; 252 } 253 254 } // namespace __sanitizer 255