Last active
September 29, 2020 14:00
-
-
Save dougpuob/79ab4309c2240d378d0cac2659617152 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// /home/dougpuob/petzone/llvm/llvm-project.git/compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp | |
//===-- sanitizer_libc.cpp ------------------------------------------------===// | |
// | |
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
// See https://llvm.org/LICENSE.txt for license information. | |
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
// | |
//===----------------------------------------------------------------------===// | |
// | |
// This file is shared between AddressSanitizer and ThreadSanitizer | |
// run-time libraries. See sanitizer_libc.h for details. | |
//===----------------------------------------------------------------------===// | |
#include "sanitizer_allocator_internal.h" | |
#include "sanitizer_common.h" | |
#include "sanitizer_libc.h" | |
namespace __sanitizer { | |
s64 internal_atoll(const char *nptr) { | |
return internal_simple_strtoll(nptr, nullptr, 10); | |
} | |
void *internal_memchr(const void *s, int c, uptr n) { | |
const char *t = (const char *)s; | |
for (uptr i = 0; i < n; ++i, ++t) | |
if (*t == c) | |
return reinterpret_cast<void *>(const_cast<char *>(t)); | |
return nullptr; | |
} | |
void *internal_memrchr(const void *s, int c, uptr n) { | |
const char *t = (const char *)s; | |
void *res = nullptr; | |
for (uptr i = 0; i < n; ++i, ++t) { | |
if (*t == c) res = reinterpret_cast<void *>(const_cast<char *>(t)); | |
} | |
return res; | |
} | |
int internal_memcmp(const void* s1, const void* s2, uptr n) { | |
const char *t1 = (const char *)s1; | |
const char *t2 = (const char *)s2; | |
for (uptr i = 0; i < n; ++i, ++t1, ++t2) | |
if (*t1 != *t2) | |
return *t1 < *t2 ? -1 : 1; | |
return 0; | |
} | |
void *internal_memcpy(void *dest, const void *src, uptr n) { | |
char *d = (char*)dest; | |
const char *s = (const char *)src; | |
for (uptr i = 0; i < n; ++i) | |
d[i] = s[i]; | |
return dest; | |
} | |
void *internal_memmove(void *dest, const void *src, uptr n) { | |
char *d = (char*)dest; | |
const char *s = (const char *)src; | |
sptr i, signed_n = (sptr)n; | |
CHECK_GE(signed_n, 0); | |
if (d < s) { | |
for (i = 0; i < signed_n; ++i) | |
d[i] = s[i]; | |
} else { | |
if (d > s && signed_n > 0) { | |
for (i = signed_n - 1; i >= 0; --i) { | |
d[i] = s[i]; | |
} | |
} | |
} | |
return dest; | |
} | |
void *internal_memset(void* s, int c, uptr n) { | |
// Optimize for the most performance-critical case: | |
if ((reinterpret_cast<uptr>(s) % 16) == 0 && (n % 16) == 0) { | |
u64 *p = reinterpret_cast<u64*>(s); | |
u64 *e = p + n / 8; | |
u64 v = c; | |
v |= v << 8; | |
v |= v << 16; | |
v |= v << 32; | |
for (; p < e; p += 2) | |
p[0] = p[1] = v; | |
return s; | |
} | |
// The next line prevents Clang from making a call to memset() instead of the | |
// loop below. | |
// FIXME: building the runtime with -ffreestanding is a better idea. However | |
// there currently are linktime problems due to PR12396. | |
char volatile *t = (char*)s; | |
for (uptr i = 0; i < n; ++i, ++t) { | |
*t = c; | |
} | |
return s; | |
} | |
uptr internal_strcspn(const char *s, const char *reject) { | |
uptr i; | |
for (i = 0; s[i]; i++) { | |
if (internal_strchr(reject, s[i])) | |
return i; | |
} | |
return i; | |
} | |
char* internal_strdup(const char *s) { | |
uptr len = internal_strlen(s); | |
char *s2 = (char*)InternalAlloc(len + 1); | |
internal_memcpy(s2, s, len); | |
s2[len] = 0; | |
return s2; | |
} | |
int internal_strcmp(const char *s1, const char *s2) { | |
while (true) { | |
unsigned c1 = *s1; | |
unsigned c2 = *s2; | |
if (c1 != c2) return (c1 < c2) ? -1 : 1; | |
if (c1 == 0) break; | |
s1++; | |
s2++; | |
} | |
return 0; | |
} | |
int internal_strncmp(const char *s1, const char *s2, uptr n) { | |
for (uptr i = 0; i < n; i++) { | |
unsigned c1 = *s1; | |
unsigned c2 = *s2; | |
if (c1 != c2) return (c1 < c2) ? -1 : 1; | |
if (c1 == 0) break; | |
s1++; | |
s2++; | |
} | |
return 0; | |
} | |
char* internal_strchr(const char *s, int c) { | |
while (true) { | |
if (*s == (char)c) | |
return const_cast<char *>(s); | |
if (*s == 0) | |
return nullptr; | |
s++; | |
} | |
} | |
char *internal_strchrnul(const char *s, int c) { | |
char *res = internal_strchr(s, c); | |
if (!res) | |
res = const_cast<char *>(s) + internal_strlen(s); | |
return res; | |
} | |
char *internal_strrchr(const char *s, int c) { | |
const char *res = nullptr; | |
for (uptr i = 0; s[i]; i++) { | |
if (s[i] == c) res = s + i; | |
} | |
return const_cast<char *>(res); | |
} | |
uptr internal_strlen(const char *s) { | |
uptr i = 0; | |
while (s[i]) i++; | |
return i; | |
} | |
uptr internal_strlcat(char *dst, const char *src, uptr maxlen) { | |
const uptr srclen = internal_strlen(src); | |
const uptr dstlen = internal_strnlen(dst, maxlen); | |
if (dstlen == maxlen) return maxlen + srclen; | |
if (srclen < maxlen - dstlen) { | |
internal_memmove(dst + dstlen, src, srclen + 1); | |
} else { | |
internal_memmove(dst + dstlen, src, maxlen - dstlen - 1); | |
dst[maxlen - 1] = '\0'; | |
} | |
return dstlen + srclen; | |
} | |
char *internal_strncat(char *dst, const char *src, uptr n) { | |
uptr len = internal_strlen(dst); | |
uptr i; | |
for (i = 0; i < n && src[i]; i++) | |
dst[len + i] = src[i]; | |
dst[len + i] = 0; | |
return dst; | |
} | |
uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) { | |
const uptr srclen = internal_strlen(src); | |
if (srclen < maxlen) { | |
internal_memmove(dst, src, srclen + 1); | |
} else if (maxlen != 0) { | |
internal_memmove(dst, src, maxlen - 1); | |
dst[maxlen - 1] = '\0'; | |
} | |
return srclen; | |
} | |
char *internal_strncpy(char *dst, const char *src, uptr n) { | |
uptr i; | |
for (i = 0; i < n && src[i]; i++) | |
dst[i] = src[i]; | |
internal_memset(dst + i, '\0', n - i); | |
return dst; | |
} | |
uptr internal_strnlen(const char *s, uptr maxlen) { | |
uptr i = 0; | |
while (i < maxlen && s[i]) i++; | |
return i; | |
} | |
char *internal_strstr(const char *haystack, const char *needle) { | |
// This is O(N^2), but we are not using it in hot places. | |
uptr len1 = internal_strlen(haystack); | |
uptr len2 = internal_strlen(needle); | |
if (len1 < len2) return nullptr; | |
for (uptr pos = 0; pos <= len1 - len2; pos++) { | |
if (internal_memcmp(haystack + pos, needle, len2) == 0) | |
return const_cast<char *>(haystack) + pos; | |
} | |
return nullptr; | |
} | |
s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) { | |
CHECK_EQ(base, 10); | |
while (IsSpace(*nptr)) nptr++; | |
int sgn = 1; | |
u64 res = 0; | |
bool have_digits = false; | |
char *old_nptr = const_cast<char *>(nptr); | |
if (*nptr == '+') { | |
sgn = 1; | |
nptr++; | |
} else if (*nptr == '-') { | |
sgn = -1; | |
nptr++; | |
} | |
while (IsDigit(*nptr)) { | |
res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX; | |
int digit = ((*nptr) - '0'); | |
res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX; | |
have_digits = true; | |
nptr++; | |
} | |
if (endptr) { | |
*endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr; | |
} | |
if (sgn > 0) { | |
return (s64)(Min((u64)INT64_MAX, res)); | |
} else { | |
return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1); | |
} | |
} | |
bool mem_is_zero(const char *beg, uptr size) { | |
CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check. | |
const char *end = beg + size; | |
uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr)); | |
uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr)); | |
uptr all = 0; | |
// Prologue. | |
for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++) | |
all |= *mem; | |
// Aligned loop. | |
for (; aligned_beg < aligned_end; aligned_beg++) | |
all |= *aligned_beg; | |
// Epilogue. | |
if ((char *)aligned_end >= beg) { | |
for (const char *mem = (char *)aligned_end; mem < end; mem++) all |= *mem; | |
} | |
return all == 0; | |
} | |
} // namespace __sanitizer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment