1 //===-- sanitizer_libc.cc -------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries. See sanitizer_libc.h for details.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_allocator_internal.h"
15 #include "sanitizer_common.h"
16 #include "sanitizer_libc.h"
18 namespace __sanitizer {
20 s64 internal_atoll(const char *nptr) {
21 return internal_simple_strtoll(nptr, nullptr, 10);
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)
28 return reinterpret_cast<void *>(const_cast<char *>(t));
32 void *internal_memrchr(const void *s, int c, uptr n) {
33 const char *t = (const char *)s;
35 for (uptr i = 0; i < n; ++i, ++t) {
36 if (*t == c) res = reinterpret_cast<void *>(const_cast<char *>(t));
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)
46 return *t1 < *t2 ? -1 : 1;
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)
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);
64 for (i = 0; i < signed_n; ++i)
67 if (d > s && signed_n > 0)
68 for (i = signed_n - 1; i >= 0 ; --i) {
75 void *internal_memset(void* s, int c, uptr n) {
76 // The next line prevents Clang from making a call to memset() instead of the
78 // FIXME: building the runtime with -ffreestanding is a better idea. However
79 // there currently are linktime problems due to PR12396.
80 char volatile *t = (char*)s;
81 for (uptr i = 0; i < n; ++i, ++t) {
87 uptr internal_strcspn(const char *s, const char *reject) {
89 for (i = 0; s[i]; i++) {
90 if (internal_strchr(reject, s[i]))
96 char* internal_strdup(const char *s) {
97 uptr len = internal_strlen(s);
98 char *s2 = (char*)InternalAlloc(len + 1);
99 internal_memcpy(s2, s, len);
104 int internal_strcmp(const char *s1, const char *s2) {
108 if (c1 != c2) return (c1 < c2) ? -1 : 1;
116 int internal_strncmp(const char *s1, const char *s2, uptr n) {
117 for (uptr i = 0; i < n; i++) {
120 if (c1 != c2) return (c1 < c2) ? -1 : 1;
128 char* internal_strchr(const char *s, int c) {
131 return const_cast<char *>(s);
138 char *internal_strchrnul(const char *s, int c) {
139 char *res = internal_strchr(s, c);
141 res = const_cast<char *>(s) + internal_strlen(s);
145 char *internal_strrchr(const char *s, int c) {
146 const char *res = nullptr;
147 for (uptr i = 0; s[i]; i++) {
148 if (s[i] == c) res = s + i;
150 return const_cast<char *>(res);
153 uptr internal_strlen(const char *s) {
159 uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {
160 const uptr srclen = internal_strlen(src);
161 const uptr dstlen = internal_strnlen(dst, maxlen);
162 if (dstlen == maxlen) return maxlen + srclen;
163 if (srclen < maxlen - dstlen) {
164 internal_memmove(dst + dstlen, src, srclen + 1);
166 internal_memmove(dst + dstlen, src, maxlen - dstlen - 1);
167 dst[maxlen - 1] = '\0';
169 return dstlen + srclen;
172 char *internal_strncat(char *dst, const char *src, uptr n) {
173 uptr len = internal_strlen(dst);
175 for (i = 0; i < n && src[i]; i++)
176 dst[len + i] = src[i];
181 uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {
182 const uptr srclen = internal_strlen(src);
183 if (srclen < maxlen) {
184 internal_memmove(dst, src, srclen + 1);
185 } else if (maxlen != 0) {
186 internal_memmove(dst, src, maxlen - 1);
187 dst[maxlen - 1] = '\0';
192 char *internal_strncpy(char *dst, const char *src, uptr n) {
194 for (i = 0; i < n && src[i]; i++)
196 internal_memset(dst + i, '\0', n - i);
200 uptr internal_strnlen(const char *s, uptr maxlen) {
202 while (i < maxlen && s[i]) i++;
206 char *internal_strstr(const char *haystack, const char *needle) {
207 // This is O(N^2), but we are not using it in hot places.
208 uptr len1 = internal_strlen(haystack);
209 uptr len2 = internal_strlen(needle);
210 if (len1 < len2) return nullptr;
211 for (uptr pos = 0; pos <= len1 - len2; pos++) {
212 if (internal_memcmp(haystack + pos, needle, len2) == 0)
213 return const_cast<char *>(haystack) + pos;
218 s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) {
220 while (IsSpace(*nptr)) nptr++;
223 bool have_digits = false;
224 char *old_nptr = const_cast<char *>(nptr);
228 } else if (*nptr == '-') {
232 while (IsDigit(*nptr)) {
233 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
234 int digit = ((*nptr) - '0');
235 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
240 *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr;
243 return (s64)(Min((u64)INT64_MAX, res));
245 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
249 bool mem_is_zero(const char *beg, uptr size) {
250 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
251 const char *end = beg + size;
252 uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
253 uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
256 for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
259 for (; aligned_beg < aligned_end; aligned_beg++)
262 if ((char*)aligned_end >= beg)
263 for (const char *mem = (char*)aligned_end; mem < end; mem++)
268 } // namespace __sanitizer