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