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