brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · 9318066 Raw
318 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is shared between AddressSanitizer and ThreadSanitizer10// 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_BUILTINS15 16#include "sanitizer_allocator_internal.h"17#include "sanitizer_common.h"18#include "sanitizer_libc.h"19 20namespace __sanitizer {21 22s64 internal_atoll(const char *nptr) {23  return internal_simple_strtoll(nptr, nullptr, 10);24}25 26void *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 34void *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 43int 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 52extern "C" {53SANITIZER_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 63SANITIZER_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 82SANITIZER_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 the97  // loop below.98  // FIXME: building the runtime with -ffreestanding is a better idea. However99  // 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 108uptr 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 117char* 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 125int 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 137int 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 149char* 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 159char *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 166char *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 174uptr internal_strlen(const char *s) {175  uptr i = 0;176  while (s[i]) i++;177  return i;178}179 180uptr 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 193char *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 202wchar_t *internal_wcscpy(wchar_t *dst, const wchar_t *src) {203  wchar_t *dst_it = dst;204  do {205    *dst_it++ = *src++;206  } while (*src);207  return dst;208}209 210uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {211  const uptr srclen = internal_strlen(src);212  if (srclen < maxlen) {213    internal_memmove(dst, src, srclen + 1);214  } else if (maxlen != 0) {215    internal_memmove(dst, src, maxlen - 1);216    dst[maxlen - 1] = '\0';217  }218  return srclen;219}220 221char *internal_strncpy(char *dst, const char *src, uptr n) {222  uptr i;223  for (i = 0; i < n && src[i]; i++)224    dst[i] = src[i];225  internal_memset(dst + i, '\0', n - i);226  return dst;227}228 229wchar_t *internal_wcsncpy(wchar_t *dst, const wchar_t *src, uptr n) {230  uptr i;231  for (i = 0; i < n && src[i]; ++i)232    dst[i] = src[i];233  internal_memset(dst + i, 0, (n - i) * sizeof(wchar_t));234  return dst;235}236 237uptr internal_strnlen(const char *s, uptr maxlen) {238  uptr i = 0;239  while (i < maxlen && s[i]) i++;240  return i;241}242 243char *internal_strstr(const char *haystack, const char *needle) {244  // This is O(N^2), but we are not using it in hot places.245  uptr len1 = internal_strlen(haystack);246  uptr len2 = internal_strlen(needle);247  if (len1 < len2) return nullptr;248  for (uptr pos = 0; pos <= len1 - len2; pos++) {249    if (internal_memcmp(haystack + pos, needle, len2) == 0)250      return const_cast<char *>(haystack) + pos;251  }252  return nullptr;253}254 255s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) {256  CHECK_EQ(base, 10);257  while (IsSpace(*nptr)) nptr++;258  int sgn = 1;259  u64 res = 0;260  bool have_digits = false;261  char *old_nptr = const_cast<char *>(nptr);262  if (*nptr == '+') {263    sgn = 1;264    nptr++;265  } else if (*nptr == '-') {266    sgn = -1;267    nptr++;268  }269  while (IsDigit(*nptr)) {270    res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;271    int digit = ((*nptr) - '0');272    res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;273    have_digits = true;274    nptr++;275  }276  if (endptr) {277    *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr;278  }279  if (sgn > 0) {280    return (s64)(Min((u64)INT64_MAX, res));281  } else {282    return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);283  }284}285 286uptr internal_wcslen(const wchar_t *s) {287  uptr i = 0;288  while (s[i]) i++;289  return i;290}291 292uptr internal_wcsnlen(const wchar_t *s, uptr maxlen) {293  uptr i = 0;294  while (i < maxlen && s[i]) i++;295  return i;296}297 298bool mem_is_zero(const char *beg, uptr size) {299  CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40));  // Sanity check.300  const char *end = beg + size;301  uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));302  uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));303  uptr all = 0;304  // Prologue.305  for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)306    all |= *mem;307  // Aligned loop.308  for (; aligned_beg < aligned_end; aligned_beg++)309    all |= *aligned_beg;310  // Epilogue.311  if ((char *)aligned_end >= beg) {312    for (const char *mem = (char *)aligned_end; mem < end; mem++) all |= *mem;313  }314  return all == 0;315}316 317} // namespace __sanitizer318