Home | History | Annotate | 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 #include "sanitizer_common.h"
     14 #include "sanitizer_libc.h"
     15 
     16 namespace __sanitizer {
     17 
     18 s64 internal_atoll(const char *nptr) {
     19   return internal_simple_strtoll(nptr, (char**)0, 10);
     20 }
     21 
     22 void *internal_memchr(const void *s, int c, uptr n) {
     23   const char* t = (char*)s;
     24   for (uptr i = 0; i < n; ++i, ++t)
     25     if (*t == c)
     26       return (void*)t;
     27   return 0;
     28 }
     29 
     30 int internal_memcmp(const void* s1, const void* s2, uptr n) {
     31   const char* t1 = (char*)s1;
     32   const char* t2 = (char*)s2;
     33   for (uptr i = 0; i < n; ++i, ++t1, ++t2)
     34     if (*t1 != *t2)
     35       return *t1 < *t2 ? -1 : 1;
     36   return 0;
     37 }
     38 
     39 void *internal_memcpy(void *dest, const void *src, uptr n) {
     40   char *d = (char*)dest;
     41   char *s = (char*)src;
     42   for (uptr i = 0; i < n; ++i)
     43     d[i] = s[i];
     44   return dest;
     45 }
     46 
     47 void *internal_memmove(void *dest, const void *src, uptr n) {
     48   char *d = (char*)dest;
     49   char *s = (char*)src;
     50   sptr i, signed_n = (sptr)n;
     51   CHECK_GE(signed_n, 0);
     52   if (d < s) {
     53     for (i = 0; i < signed_n; ++i)
     54       d[i] = s[i];
     55   } else {
     56     if (d > s && signed_n > 0)
     57       for (i = signed_n - 1; i >= 0 ; --i) {
     58         d[i] = s[i];
     59       }
     60   }
     61   return dest;
     62 }
     63 
     64 void *internal_memset(void* s, int c, uptr n) {
     65   // The next line prevents Clang from making a call to memset() instead of the
     66   // loop below.
     67   // FIXME: building the runtime with -ffreestanding is a better idea. However
     68   // there currently are linktime problems due to PR12396.
     69   char volatile *t = (char*)s;
     70   for (uptr i = 0; i < n; ++i, ++t) {
     71     *t = c;
     72   }
     73   return s;
     74 }
     75 
     76 uptr internal_strcspn(const char *s, const char *reject) {
     77   uptr i;
     78   for (i = 0; s[i]; i++) {
     79     if (internal_strchr(reject, s[i]) != 0)
     80       return i;
     81   }
     82   return i;
     83 }
     84 
     85 char* internal_strdup(const char *s) {
     86   uptr len = internal_strlen(s);
     87   char *s2 = (char*)InternalAlloc(len + 1);
     88   internal_memcpy(s2, s, len);
     89   s2[len] = 0;
     90   return s2;
     91 }
     92 
     93 int internal_strcmp(const char *s1, const char *s2) {
     94   while (true) {
     95     unsigned c1 = *s1;
     96     unsigned c2 = *s2;
     97     if (c1 != c2) return (c1 < c2) ? -1 : 1;
     98     if (c1 == 0) break;
     99     s1++;
    100     s2++;
    101   }
    102   return 0;
    103 }
    104 
    105 int internal_strncmp(const char *s1, const char *s2, uptr n) {
    106   for (uptr i = 0; i < n; i++) {
    107     unsigned c1 = *s1;
    108     unsigned c2 = *s2;
    109     if (c1 != c2) return (c1 < c2) ? -1 : 1;
    110     if (c1 == 0) break;
    111     s1++;
    112     s2++;
    113   }
    114   return 0;
    115 }
    116 
    117 char* internal_strchr(const char *s, int c) {
    118   while (true) {
    119     if (*s == (char)c)
    120       return (char*)s;
    121     if (*s == 0)
    122       return 0;
    123     s++;
    124   }
    125 }
    126 
    127 char *internal_strrchr(const char *s, int c) {
    128   const char *res = 0;
    129   for (uptr i = 0; s[i]; i++) {
    130     if (s[i] == c) res = s + i;
    131   }
    132   return (char*)res;
    133 }
    134 
    135 uptr internal_strlen(const char *s) {
    136   uptr i = 0;
    137   while (s[i]) i++;
    138   return i;
    139 }
    140 
    141 char *internal_strncat(char *dst, const char *src, uptr n) {
    142   uptr len = internal_strlen(dst);
    143   uptr i;
    144   for (i = 0; i < n && src[i]; i++)
    145     dst[len + i] = src[i];
    146   dst[len + i] = 0;
    147   return dst;
    148 }
    149 
    150 char *internal_strncpy(char *dst, const char *src, uptr n) {
    151   uptr i;
    152   for (i = 0; i < n && src[i]; i++)
    153     dst[i] = src[i];
    154   for (; i < n; i++)
    155     dst[i] = '\0';
    156   return dst;
    157 }
    158 
    159 uptr internal_strnlen(const char *s, uptr maxlen) {
    160   uptr i = 0;
    161   while (i < maxlen && s[i]) i++;
    162   return i;
    163 }
    164 
    165 char *internal_strstr(const char *haystack, const char *needle) {
    166   // This is O(N^2), but we are not using it in hot places.
    167   uptr len1 = internal_strlen(haystack);
    168   uptr len2 = internal_strlen(needle);
    169   if (len1 < len2) return 0;
    170   for (uptr pos = 0; pos <= len1 - len2; pos++) {
    171     if (internal_memcmp(haystack + pos, needle, len2) == 0)
    172       return (char*)haystack + pos;
    173   }
    174   return 0;
    175 }
    176 
    177 s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
    178   CHECK_EQ(base, 10);
    179   while (IsSpace(*nptr)) nptr++;
    180   int sgn = 1;
    181   u64 res = 0;
    182   bool have_digits = false;
    183   char *old_nptr = (char*)nptr;
    184   if (*nptr == '+') {
    185     sgn = 1;
    186     nptr++;
    187   } else if (*nptr == '-') {
    188     sgn = -1;
    189     nptr++;
    190   }
    191   while (IsDigit(*nptr)) {
    192     res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
    193     int digit = ((*nptr) - '0');
    194     res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
    195     have_digits = true;
    196     nptr++;
    197   }
    198   if (endptr != 0) {
    199     *endptr = (have_digits) ? (char*)nptr : old_nptr;
    200   }
    201   if (sgn > 0) {
    202     return (s64)(Min((u64)INT64_MAX, res));
    203   } else {
    204     return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
    205   }
    206 }
    207 
    208 bool mem_is_zero(const char *beg, uptr size) {
    209   CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
    210   const char *end = beg + size;
    211   uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
    212   uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
    213   uptr all = 0;
    214   // Prologue.
    215   for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
    216     all |= *mem;
    217   // Aligned loop.
    218   for (; aligned_beg < aligned_end; aligned_beg++)
    219     all |= *aligned_beg;
    220   // Epilogue.
    221   if ((char*)aligned_end >= beg)
    222     for (const char *mem = (char*)aligned_end; mem < end; mem++)
    223       all |= *mem;
    224   return all == 0;
    225 }
    226 
    227 }  // namespace __sanitizer
    228