Home | History | Annotate | Line # | Download | only in sanitizer_common
      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 
     14 #include "sanitizer_allocator_internal.h"
     15 #include "sanitizer_common.h"
     16 #include "sanitizer_libc.h"
     17 
     18 namespace __sanitizer {
     19 
     20 s64 internal_atoll(const char *nptr) {
     21   return internal_simple_strtoll(nptr, nullptr, 10);
     22 }
     23 
     24 void *internal_memchr(const void *s, int c, uptr n) {
     25   const char *t = (const char *)s;
     26   for (uptr i = 0; i < n; ++i, ++t)
     27     if (*t == c)
     28       return reinterpret_cast<void *>(const_cast<char *>(t));
     29   return nullptr;
     30 }
     31 
     32 void *internal_memrchr(const void *s, int c, uptr n) {
     33   const char *t = (const char *)s;
     34   void *res = nullptr;
     35   for (uptr i = 0; i < n; ++i, ++t) {
     36     if (*t == c) res = reinterpret_cast<void *>(const_cast<char *>(t));
     37   }
     38   return res;
     39 }
     40 
     41 int internal_memcmp(const void* s1, const void* s2, uptr n) {
     42   const char *t1 = (const char *)s1;
     43   const char *t2 = (const 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   const char *s = (const 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   const char *s = (const 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 void *internal_memset(void* s, int c, uptr n) {
     76   // Optimize for the most performance-critical case:
     77   if ((reinterpret_cast<uptr>(s) % 16) == 0 && (n % 16) == 0) {
     78     u64 *p = reinterpret_cast<u64*>(s);
     79     u64 *e = p + n / 8;
     80     u64 v = c;
     81     v |= v << 8;
     82     v |= v << 16;
     83     v |= v << 32;
     84     for (; p < e; p += 2)
     85       p[0] = p[1] = v;
     86     return s;
     87   }
     88   // The next line prevents Clang from making a call to memset() instead of the
     89   // loop below.
     90   // FIXME: building the runtime with -ffreestanding is a better idea. However
     91   // there currently are linktime problems due to PR12396.
     92   char volatile *t = (char*)s;
     93   for (uptr i = 0; i < n; ++i, ++t) {
     94     *t = c;
     95   }
     96   return s;
     97 }
     98 
     99 uptr internal_strcspn(const char *s, const char *reject) {
    100   uptr i;
    101   for (i = 0; s[i]; i++) {
    102     if (internal_strchr(reject, s[i]))
    103       return i;
    104   }
    105   return i;
    106 }
    107 
    108 char* internal_strdup(const char *s) {
    109   uptr len = internal_strlen(s);
    110   char *s2 = (char*)InternalAlloc(len + 1);
    111   internal_memcpy(s2, s, len);
    112   s2[len] = 0;
    113   return s2;
    114 }
    115 
    116 int internal_strcmp(const char *s1, const char *s2) {
    117   while (true) {
    118     unsigned c1 = *s1;
    119     unsigned c2 = *s2;
    120     if (c1 != c2) return (c1 < c2) ? -1 : 1;
    121     if (c1 == 0) break;
    122     s1++;
    123     s2++;
    124   }
    125   return 0;
    126 }
    127 
    128 int internal_strncmp(const char *s1, const char *s2, uptr n) {
    129   for (uptr i = 0; i < n; i++) {
    130     unsigned c1 = *s1;
    131     unsigned c2 = *s2;
    132     if (c1 != c2) return (c1 < c2) ? -1 : 1;
    133     if (c1 == 0) break;
    134     s1++;
    135     s2++;
    136   }
    137   return 0;
    138 }
    139 
    140 char* internal_strchr(const char *s, int c) {
    141   while (true) {
    142     if (*s == (char)c)
    143       return const_cast<char *>(s);
    144     if (*s == 0)
    145       return nullptr;
    146     s++;
    147   }
    148 }
    149 
    150 char *internal_strchrnul(const char *s, int c) {
    151   char *res = internal_strchr(s, c);
    152   if (!res)
    153     res = const_cast<char *>(s) + internal_strlen(s);
    154   return res;
    155 }
    156 
    157 char *internal_strrchr(const char *s, int c) {
    158   const char *res = nullptr;
    159   for (uptr i = 0; s[i]; i++) {
    160     if (s[i] == c) res = s + i;
    161   }
    162   return const_cast<char *>(res);
    163 }
    164 
    165 uptr internal_strlen(const char *s) {
    166   uptr i = 0;
    167   while (s[i]) i++;
    168   return i;
    169 }
    170 
    171 uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {
    172   const uptr srclen = internal_strlen(src);
    173   const uptr dstlen = internal_strnlen(dst, maxlen);
    174   if (dstlen == maxlen) return maxlen + srclen;
    175   if (srclen < maxlen - dstlen) {
    176     internal_memmove(dst + dstlen, src, srclen + 1);
    177   } else {
    178     internal_memmove(dst + dstlen, src, maxlen - dstlen - 1);
    179     dst[maxlen - 1] = '\0';
    180   }
    181   return dstlen + srclen;
    182 }
    183 
    184 char *internal_strncat(char *dst, const char *src, uptr n) {
    185   uptr len = internal_strlen(dst);
    186   uptr i;
    187   for (i = 0; i < n && src[i]; i++)
    188     dst[len + i] = src[i];
    189   dst[len + i] = 0;
    190   return dst;
    191 }
    192 
    193 uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {
    194   const uptr srclen = internal_strlen(src);
    195   if (srclen < maxlen) {
    196     internal_memmove(dst, src, srclen + 1);
    197   } else if (maxlen != 0) {
    198     internal_memmove(dst, src, maxlen - 1);
    199     dst[maxlen - 1] = '\0';
    200   }
    201   return srclen;
    202 }
    203 
    204 char *internal_strncpy(char *dst, const char *src, uptr n) {
    205   uptr i;
    206   for (i = 0; i < n && src[i]; i++)
    207     dst[i] = src[i];
    208   internal_memset(dst + i, '\0', n - i);
    209   return dst;
    210 }
    211 
    212 uptr internal_strnlen(const char *s, uptr maxlen) {
    213   uptr i = 0;
    214   while (i < maxlen && s[i]) i++;
    215   return i;
    216 }
    217 
    218 char *internal_strstr(const char *haystack, const char *needle) {
    219   // This is O(N^2), but we are not using it in hot places.
    220   uptr len1 = internal_strlen(haystack);
    221   uptr len2 = internal_strlen(needle);
    222   if (len1 < len2) return nullptr;
    223   for (uptr pos = 0; pos <= len1 - len2; pos++) {
    224     if (internal_memcmp(haystack + pos, needle, len2) == 0)
    225       return const_cast<char *>(haystack) + pos;
    226   }
    227   return nullptr;
    228 }
    229 
    230 s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) {
    231   CHECK_EQ(base, 10);
    232   while (IsSpace(*nptr)) nptr++;
    233   int sgn = 1;
    234   u64 res = 0;
    235   bool have_digits = false;
    236   char *old_nptr = const_cast<char *>(nptr);
    237   if (*nptr == '+') {
    238     sgn = 1;
    239     nptr++;
    240   } else if (*nptr == '-') {
    241     sgn = -1;
    242     nptr++;
    243   }
    244   while (IsDigit(*nptr)) {
    245     res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
    246     int digit = ((*nptr) - '0');
    247     res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
    248     have_digits = true;
    249     nptr++;
    250   }
    251   if (endptr) {
    252     *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr;
    253   }
    254   if (sgn > 0) {
    255     return (s64)(Min((u64)INT64_MAX, res));
    256   } else {
    257     return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
    258   }
    259 }
    260 
    261 bool mem_is_zero(const char *beg, uptr size) {
    262   CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
    263   const char *end = beg + size;
    264   uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
    265   uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
    266   uptr all = 0;
    267   // Prologue.
    268   for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
    269     all |= *mem;
    270   // Aligned loop.
    271   for (; aligned_beg < aligned_end; aligned_beg++)
    272     all |= *aligned_beg;
    273   // Epilogue.
    274   if ((char*)aligned_end >= beg)
    275     for (const char *mem = (char*)aligned_end; mem < end; mem++)
    276       all |= *mem;
    277   return all == 0;
    278 }
    279 
    280 } // namespace __sanitizer
    281