1 //===-- sanitizer_libc.cpp ------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is shared between AddressSanitizer and ThreadSanitizer
10 // run-time libraries. See sanitizer_libc.h for details.
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_allocator_internal.h"
14 #include "sanitizer_common.h"
15 #include "sanitizer_libc.h"
17 namespace __sanitizer
{
19 s64
internal_atoll(const char *nptr
) {
20 return internal_simple_strtoll(nptr
, nullptr, 10);
23 void *internal_memchr(const void *s
, int c
, uptr n
) {
24 const char *t
= (const char *)s
;
25 for (uptr i
= 0; i
< n
; ++i
, ++t
)
27 return reinterpret_cast<void *>(const_cast<char *>(t
));
31 void *internal_memrchr(const void *s
, int c
, uptr n
) {
32 const char *t
= (const char *)s
;
34 for (uptr i
= 0; i
< n
; ++i
, ++t
) {
35 if (*t
== c
) res
= reinterpret_cast<void *>(const_cast<char *>(t
));
40 int internal_memcmp(const void* s1
, const void* s2
, uptr n
) {
41 const char *t1
= (const char *)s1
;
42 const char *t2
= (const char *)s2
;
43 for (uptr i
= 0; i
< n
; ++i
, ++t1
, ++t2
)
45 return *t1
< *t2
? -1 : 1;
49 void *internal_memcpy(void *dest
, const void *src
, uptr n
) {
50 char *d
= (char*)dest
;
51 const char *s
= (const char *)src
;
52 for (uptr i
= 0; i
< n
; ++i
)
57 void *internal_memmove(void *dest
, const void *src
, uptr n
) {
58 char *d
= (char*)dest
;
59 const char *s
= (const char *)src
;
60 sptr i
, signed_n
= (sptr
)n
;
61 CHECK_GE(signed_n
, 0);
63 for (i
= 0; i
< signed_n
; ++i
)
66 if (d
> s
&& signed_n
> 0) {
67 for (i
= signed_n
- 1; i
>= 0; --i
) {
75 void *internal_memset(void* s
, int c
, uptr n
) {
76 // Optimize for the most performance-critical case:
77 if ((reinterpret_cast<uptr
>(s
) % 16) == 0 && (n
% 16) == 0) {
78 u64
*p
= reinterpret_cast<u64
*>(s
);
88 // The next line prevents Clang from making a call to memset() instead of the
90 // FIXME: building the runtime with -ffreestanding is a better idea. However
91 // there currently are linktime problems due to PR12396.
92 char volatile *t
= (char*)s
;
93 for (uptr i
= 0; i
< n
; ++i
, ++t
) {
99 uptr
internal_strcspn(const char *s
, const char *reject
) {
101 for (i
= 0; s
[i
]; i
++) {
102 if (internal_strchr(reject
, s
[i
]))
108 char* internal_strdup(const char *s
) {
109 uptr len
= internal_strlen(s
);
110 char *s2
= (char*)InternalAlloc(len
+ 1);
111 internal_memcpy(s2
, s
, len
);
116 int internal_strcmp(const char *s1
, const char *s2
) {
120 if (c1
!= c2
) return (c1
< c2
) ? -1 : 1;
128 int internal_strncmp(const char *s1
, const char *s2
, uptr n
) {
129 for (uptr i
= 0; i
< n
; i
++) {
132 if (c1
!= c2
) return (c1
< c2
) ? -1 : 1;
140 char* internal_strchr(const char *s
, int c
) {
143 return const_cast<char *>(s
);
150 char *internal_strchrnul(const char *s
, int c
) {
151 char *res
= internal_strchr(s
, c
);
153 res
= const_cast<char *>(s
) + internal_strlen(s
);
157 char *internal_strrchr(const char *s
, int c
) {
158 const char *res
= nullptr;
159 for (uptr i
= 0; s
[i
]; i
++) {
160 if (s
[i
] == c
) res
= s
+ i
;
162 return const_cast<char *>(res
);
165 uptr
internal_strlen(const char *s
) {
171 uptr
internal_strlcat(char *dst
, const char *src
, uptr maxlen
) {
172 const uptr srclen
= internal_strlen(src
);
173 const uptr dstlen
= internal_strnlen(dst
, maxlen
);
174 if (dstlen
== maxlen
) return maxlen
+ srclen
;
175 if (srclen
< maxlen
- dstlen
) {
176 internal_memmove(dst
+ dstlen
, src
, srclen
+ 1);
178 internal_memmove(dst
+ dstlen
, src
, maxlen
- dstlen
- 1);
179 dst
[maxlen
- 1] = '\0';
181 return dstlen
+ srclen
;
184 char *internal_strncat(char *dst
, const char *src
, uptr n
) {
185 uptr len
= internal_strlen(dst
);
187 for (i
= 0; i
< n
&& src
[i
]; i
++)
188 dst
[len
+ i
] = src
[i
];
193 uptr
internal_strlcpy(char *dst
, const char *src
, uptr maxlen
) {
194 const uptr srclen
= internal_strlen(src
);
195 if (srclen
< maxlen
) {
196 internal_memmove(dst
, src
, srclen
+ 1);
197 } else if (maxlen
!= 0) {
198 internal_memmove(dst
, src
, maxlen
- 1);
199 dst
[maxlen
- 1] = '\0';
204 char *internal_strncpy(char *dst
, const char *src
, uptr n
) {
206 for (i
= 0; i
< n
&& src
[i
]; i
++)
208 internal_memset(dst
+ i
, '\0', n
- i
);
212 uptr
internal_strnlen(const char *s
, uptr maxlen
) {
214 while (i
< maxlen
&& s
[i
]) i
++;
218 char *internal_strstr(const char *haystack
, const char *needle
) {
219 // This is O(N^2), but we are not using it in hot places.
220 uptr len1
= internal_strlen(haystack
);
221 uptr len2
= internal_strlen(needle
);
222 if (len1
< len2
) return nullptr;
223 for (uptr pos
= 0; pos
<= len1
- len2
; pos
++) {
224 if (internal_memcmp(haystack
+ pos
, needle
, len2
) == 0)
225 return const_cast<char *>(haystack
) + pos
;
230 s64
internal_simple_strtoll(const char *nptr
, const char **endptr
, int base
) {
232 while (IsSpace(*nptr
)) nptr
++;
235 bool have_digits
= false;
236 char *old_nptr
= const_cast<char *>(nptr
);
240 } else if (*nptr
== '-') {
244 while (IsDigit(*nptr
)) {
245 res
= (res
<= UINT64_MAX
/ 10) ? res
* 10 : UINT64_MAX
;
246 int digit
= ((*nptr
) - '0');
247 res
= (res
<= UINT64_MAX
- digit
) ? res
+ digit
: UINT64_MAX
;
252 *endptr
= (have_digits
) ? const_cast<char *>(nptr
) : old_nptr
;
255 return (s64
)(Min((u64
)INT64_MAX
, res
));
257 return (res
> INT64_MAX
) ? INT64_MIN
: ((s64
)res
* -1);
261 uptr
internal_wcslen(const wchar_t *s
) {
267 uptr
internal_wcsnlen(const wchar_t *s
, uptr maxlen
) {
269 while (i
< maxlen
&& s
[i
]) i
++;
273 bool mem_is_zero(const char *beg
, uptr size
) {
274 CHECK_LE(size
, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
275 const char *end
= beg
+ size
;
276 uptr
*aligned_beg
= (uptr
*)RoundUpTo((uptr
)beg
, sizeof(uptr
));
277 uptr
*aligned_end
= (uptr
*)RoundDownTo((uptr
)end
, sizeof(uptr
));
280 for (const char *mem
= beg
; mem
< (char*)aligned_beg
&& mem
< end
; mem
++)
283 for (; aligned_beg
< aligned_end
; aligned_beg
++)
286 if ((char *)aligned_end
>= beg
) {
287 for (const char *mem
= (char *)aligned_end
; mem
< end
; mem
++) all
|= *mem
;
292 } // namespace __sanitizer