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