1 //===-- sanitizer_libc.cpp ------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is shared between AddressSanitizer and ThreadSanitizer 10 // run-time libraries. See sanitizer_libc.h for details. 11 //===----------------------------------------------------------------------===// 12 13 // Do not redefine builtins; this file is defining the builtin replacements. 14 #define SANITIZER_COMMON_NO_REDEFINE_BUILTINS 15 16 #include "sanitizer_allocator_internal.h" 17 #include "sanitizer_common.h" 18 #include "sanitizer_libc.h" 19 20 namespace __sanitizer { 21 22 s64 internal_atoll(const char *nptr) { 23 return internal_simple_strtoll(nptr, nullptr, 10); 24 } 25 26 void *internal_memchr(const void *s, int c, uptr n) { 27 const char *t = (const char *)s; 28 for (uptr i = 0; i < n; ++i, ++t) 29 if (*t == c) 30 return reinterpret_cast<void *>(const_cast<char *>(t)); 31 return nullptr; 32 } 33 34 void *internal_memrchr(const void *s, int c, uptr n) { 35 const char *t = (const char *)s; 36 void *res = nullptr; 37 for (uptr i = 0; i < n; ++i, ++t) { 38 if (*t == c) res = reinterpret_cast<void *>(const_cast<char *>(t)); 39 } 40 return res; 41 } 42 43 int internal_memcmp(const void* s1, const void* s2, uptr n) { 44 const char *t1 = (const char *)s1; 45 const char *t2 = (const char *)s2; 46 for (uptr i = 0; i < n; ++i, ++t1, ++t2) 47 if (*t1 != *t2) 48 return *t1 < *t2 ? -1 : 1; 49 return 0; 50 } 51 52 extern "C" { 53 SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memcpy(void *dest, 54 const void *src, 55 uptr n) { 56 char *d = (char*)dest; 57 const char *s = (const char *)src; 58 for (uptr i = 0; i < n; ++i) 59 d[i] = s[i]; 60 return dest; 61 } 62 63 SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memmove( 64 void *dest, const void *src, uptr n) { 65 char *d = (char*)dest; 66 const char *s = (const char *)src; 67 sptr i, signed_n = (sptr)n; 68 CHECK_GE(signed_n, 0); 69 if (d < s) { 70 for (i = 0; i < signed_n; ++i) 71 d[i] = s[i]; 72 } else { 73 if (d > s && signed_n > 0) { 74 for (i = signed_n - 1; i >= 0; --i) { 75 d[i] = s[i]; 76 } 77 } 78 } 79 return dest; 80 } 81 82 SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memset(void *s, int c, 83 uptr n) { 84 // Optimize for the most performance-critical case: 85 if ((reinterpret_cast<uptr>(s) % 16) == 0 && (n % 16) == 0) { 86 u64 *p = reinterpret_cast<u64*>(s); 87 u64 *e = p + n / 8; 88 u64 v = c; 89 v |= v << 8; 90 v |= v << 16; 91 v |= v << 32; 92 for (; p < e; p += 2) 93 p[0] = p[1] = v; 94 return s; 95 } 96 // The next line prevents Clang from making a call to memset() instead of the 97 // loop below. 98 // FIXME: building the runtime with -ffreestanding is a better idea. However 99 // there currently are linktime problems due to PR12396. 100 char volatile *t = (char*)s; 101 for (uptr i = 0; i < n; ++i, ++t) { 102 *t = c; 103 } 104 return s; 105 } 106 } // extern "C" 107 108 uptr internal_strcspn(const char *s, const char *reject) { 109 uptr i; 110 for (i = 0; s[i]; i++) { 111 if (internal_strchr(reject, s[i])) 112 return i; 113 } 114 return i; 115 } 116 117 char* internal_strdup(const char *s) { 118 uptr len = internal_strlen(s); 119 char *s2 = (char*)InternalAlloc(len + 1); 120 internal_memcpy(s2, s, len); 121 s2[len] = 0; 122 return s2; 123 } 124 125 int internal_strcmp(const char *s1, const char *s2) { 126 while (true) { 127 unsigned c1 = *s1; 128 unsigned c2 = *s2; 129 if (c1 != c2) return (c1 < c2) ? -1 : 1; 130 if (c1 == 0) break; 131 s1++; 132 s2++; 133 } 134 return 0; 135 } 136 137 int internal_strncmp(const char *s1, const char *s2, uptr n) { 138 for (uptr i = 0; i < n; i++) { 139 unsigned c1 = *s1; 140 unsigned c2 = *s2; 141 if (c1 != c2) return (c1 < c2) ? -1 : 1; 142 if (c1 == 0) break; 143 s1++; 144 s2++; 145 } 146 return 0; 147 } 148 149 char* internal_strchr(const char *s, int c) { 150 while (true) { 151 if (*s == (char)c) 152 return const_cast<char *>(s); 153 if (*s == 0) 154 return nullptr; 155 s++; 156 } 157 } 158 159 char *internal_strchrnul(const char *s, int c) { 160 char *res = internal_strchr(s, c); 161 if (!res) 162 res = const_cast<char *>(s) + internal_strlen(s); 163 return res; 164 } 165 166 char *internal_strrchr(const char *s, int c) { 167 const char *res = nullptr; 168 for (uptr i = 0; s[i]; i++) { 169 if (s[i] == c) res = s + i; 170 } 171 return const_cast<char *>(res); 172 } 173 174 uptr internal_strlen(const char *s) { 175 uptr i = 0; 176 while (s[i]) i++; 177 return i; 178 } 179 180 uptr internal_strlcat(char *dst, const char *src, uptr maxlen) { 181 const uptr srclen = internal_strlen(src); 182 const uptr dstlen = internal_strnlen(dst, maxlen); 183 if (dstlen == maxlen) return maxlen + srclen; 184 if (srclen < maxlen - dstlen) { 185 internal_memmove(dst + dstlen, src, srclen + 1); 186 } else { 187 internal_memmove(dst + dstlen, src, maxlen - dstlen - 1); 188 dst[maxlen - 1] = '\0'; 189 } 190 return dstlen + srclen; 191 } 192 193 char *internal_strncat(char *dst, const char *src, uptr n) { 194 uptr len = internal_strlen(dst); 195 uptr i; 196 for (i = 0; i < n && src[i]; i++) 197 dst[len + i] = src[i]; 198 dst[len + i] = 0; 199 return dst; 200 } 201 202 uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) { 203 const uptr srclen = internal_strlen(src); 204 if (srclen < maxlen) { 205 internal_memmove(dst, src, srclen + 1); 206 } else if (maxlen != 0) { 207 internal_memmove(dst, src, maxlen - 1); 208 dst[maxlen - 1] = '\0'; 209 } 210 return srclen; 211 } 212 213 char *internal_strncpy(char *dst, const char *src, uptr n) { 214 uptr i; 215 for (i = 0; i < n && src[i]; i++) 216 dst[i] = src[i]; 217 internal_memset(dst + i, '\0', n - i); 218 return dst; 219 } 220 221 uptr internal_strnlen(const char *s, uptr maxlen) { 222 uptr i = 0; 223 while (i < maxlen && s[i]) i++; 224 return i; 225 } 226 227 char *internal_strstr(const char *haystack, const char *needle) { 228 // This is O(N^2), but we are not using it in hot places. 229 uptr len1 = internal_strlen(haystack); 230 uptr len2 = internal_strlen(needle); 231 if (len1 < len2) return nullptr; 232 for (uptr pos = 0; pos <= len1 - len2; pos++) { 233 if (internal_memcmp(haystack + pos, needle, len2) == 0) 234 return const_cast<char *>(haystack) + pos; 235 } 236 return nullptr; 237 } 238 239 s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) { 240 CHECK_EQ(base, 10); 241 while (IsSpace(*nptr)) nptr++; 242 int sgn = 1; 243 u64 res = 0; 244 bool have_digits = false; 245 char *old_nptr = const_cast<char *>(nptr); 246 if (*nptr == '+') { 247 sgn = 1; 248 nptr++; 249 } else if (*nptr == '-') { 250 sgn = -1; 251 nptr++; 252 } 253 while (IsDigit(*nptr)) { 254 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX; 255 int digit = ((*nptr) - '0'); 256 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX; 257 have_digits = true; 258 nptr++; 259 } 260 if (endptr) { 261 *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr; 262 } 263 if (sgn > 0) { 264 return (s64)(Min((u64)INT64_MAX, res)); 265 } else { 266 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1); 267 } 268 } 269 270 uptr internal_wcslen(const wchar_t *s) { 271 uptr i = 0; 272 while (s[i]) i++; 273 return i; 274 } 275 276 uptr internal_wcsnlen(const wchar_t *s, uptr maxlen) { 277 uptr i = 0; 278 while (i < maxlen && s[i]) i++; 279 return i; 280 } 281 282 bool mem_is_zero(const char *beg, uptr size) { 283 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check. 284 const char *end = beg + size; 285 uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr)); 286 uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr)); 287 uptr all = 0; 288 // Prologue. 289 for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++) 290 all |= *mem; 291 // Aligned loop. 292 for (; aligned_beg < aligned_end; aligned_beg++) 293 all |= *aligned_beg; 294 // Epilogue. 295 if ((char *)aligned_end >= beg) { 296 for (const char *mem = (char *)aligned_end; mem < end; mem++) all |= *mem; 297 } 298 return all == 0; 299 } 300 301 } // namespace __sanitizer 302