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
internal_atoll(const char * nptr)19 s64 internal_atoll(const char *nptr) {
20 return internal_simple_strtoll(nptr, (char**)0, 10);
21 }
22
internal_memchr(const void * s,int c,uptr n)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
internal_memcmp(const void * s1,const void * s2,uptr n)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
internal_memcpy(void * dest,const void * src,uptr n)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
internal_memmove(void * dest,const void * src,uptr n)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
internal_memset(void * s,int c,uptr n)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
internal_strcspn(const char * s,const char * reject)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
internal_strdup(const char * s)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
internal_strcmp(const char * s1,const char * s2)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
internal_strncmp(const char * s1,const char * s2,uptr n)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
internal_strchr(const char * s,int c)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
internal_strrchr(const char * s,int c)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
internal_strlen(const char * s)136 uptr internal_strlen(const char *s) {
137 uptr i = 0;
138 while (s[i]) i++;
139 return i;
140 }
141
internal_strncat(char * dst,const char * src,uptr n)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
internal_strncpy(char * dst,const char * src,uptr n)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
internal_strnlen(const char * s,uptr maxlen)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
internal_strstr(const char * haystack,const char * needle)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
internal_simple_strtoll(const char * nptr,char ** endptr,int base)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
mem_is_zero(const char * beg,uptr size)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