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 // Do not redefine builtins; this file is defining the builtin replacements.
14 #define SANITIZER_COMMON_NO_REDEFINE_BUILTINS
16 #include "sanitizer_allocator_internal.h"
17 #include "sanitizer_common.h"
18 #include "sanitizer_libc.h"
20 namespace __sanitizer
{
22 s64
internal_atoll(const char *nptr
) {
23 return internal_simple_strtoll(nptr
, nullptr, 10);
26 void *internal_memchr(const void *s
, int c
, uptr n
) {
27 const char *t
= (const char *)s
;
28 for (uptr i
= 0; i
< n
; ++i
, ++t
)
30 return reinterpret_cast<void *>(const_cast<char *>(t
));
34 void *internal_memrchr(const void *s
, int c
, uptr n
) {
35 const char *t
= (const char *)s
;
37 for (uptr i
= 0; i
< n
; ++i
, ++t
) {
38 if (*t
== c
) res
= reinterpret_cast<void *>(const_cast<char *>(t
));
43 int internal_memcmp(const void* s1
, const void* s2
, uptr n
) {
44 const char *t1
= (const char *)s1
;
45 const char *t2
= (const char *)s2
;
46 for (uptr i
= 0; i
< n
; ++i
, ++t1
, ++t2
)
48 return *t1
< *t2
? -1 : 1;
53 SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_internal_memcpy(void *dest
,
56 char *d
= (char*)dest
;
57 const char *s
= (const char *)src
;
58 for (uptr i
= 0; i
< n
; ++i
)
63 SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_internal_memmove(
64 void *dest
, const void *src
, uptr n
) {
65 char *d
= (char*)dest
;
66 const char *s
= (const char *)src
;
67 sptr i
, signed_n
= (sptr
)n
;
68 CHECK_GE(signed_n
, 0);
70 for (i
= 0; i
< signed_n
; ++i
)
73 if (d
> s
&& signed_n
> 0) {
74 for (i
= signed_n
- 1; i
>= 0; --i
) {
82 SANITIZER_INTERFACE_ATTRIBUTE
void *__sanitizer_internal_memset(void *s
, int c
,
84 // Optimize for the most performance-critical case:
85 if ((reinterpret_cast<uptr
>(s
) % 16) == 0 && (n
% 16) == 0) {
86 u64
*p
= reinterpret_cast<u64
*>(s
);
96 // The next line prevents Clang from making a call to memset() instead of the
98 // FIXME: building the runtime with -ffreestanding is a better idea. However
99 // there currently are linktime problems due to PR12396.
100 char volatile *t
= (char*)s
;
101 for (uptr i
= 0; i
< n
; ++i
, ++t
) {
108 uptr
internal_strcspn(const char *s
, const char *reject
) {
110 for (i
= 0; s
[i
]; i
++) {
111 if (internal_strchr(reject
, s
[i
]))
117 char* internal_strdup(const char *s
) {
118 uptr len
= internal_strlen(s
);
119 char *s2
= (char*)InternalAlloc(len
+ 1);
120 internal_memcpy(s2
, s
, len
);
125 int internal_strcmp(const char *s1
, const char *s2
) {
129 if (c1
!= c2
) return (c1
< c2
) ? -1 : 1;
137 int internal_strncmp(const char *s1
, const char *s2
, uptr n
) {
138 for (uptr i
= 0; i
< n
; i
++) {
141 if (c1
!= c2
) return (c1
< c2
) ? -1 : 1;
149 char* internal_strchr(const char *s
, int c
) {
152 return const_cast<char *>(s
);
159 char *internal_strchrnul(const char *s
, int c
) {
160 char *res
= internal_strchr(s
, c
);
162 res
= const_cast<char *>(s
) + internal_strlen(s
);
166 char *internal_strrchr(const char *s
, int c
) {
167 const char *res
= nullptr;
168 for (uptr i
= 0; s
[i
]; i
++) {
169 if (s
[i
] == c
) res
= s
+ i
;
171 return const_cast<char *>(res
);
174 uptr
internal_strlen(const char *s
) {
180 uptr
internal_strlcat(char *dst
, const char *src
, uptr maxlen
) {
181 const uptr srclen
= internal_strlen(src
);
182 const uptr dstlen
= internal_strnlen(dst
, maxlen
);
183 if (dstlen
== maxlen
) return maxlen
+ srclen
;
184 if (srclen
< maxlen
- dstlen
) {
185 internal_memmove(dst
+ dstlen
, src
, srclen
+ 1);
187 internal_memmove(dst
+ dstlen
, src
, maxlen
- dstlen
- 1);
188 dst
[maxlen
- 1] = '\0';
190 return dstlen
+ srclen
;
193 char *internal_strncat(char *dst
, const char *src
, uptr n
) {
194 uptr len
= internal_strlen(dst
);
196 for (i
= 0; i
< n
&& src
[i
]; i
++)
197 dst
[len
+ i
] = src
[i
];
202 wchar_t *internal_wcscpy(wchar_t *dst
, const wchar_t *src
) {
203 wchar_t *dst_it
= dst
;
210 uptr
internal_strlcpy(char *dst
, const char *src
, uptr maxlen
) {
211 const uptr srclen
= internal_strlen(src
);
212 if (srclen
< maxlen
) {
213 internal_memmove(dst
, src
, srclen
+ 1);
214 } else if (maxlen
!= 0) {
215 internal_memmove(dst
, src
, maxlen
- 1);
216 dst
[maxlen
- 1] = '\0';
221 char *internal_strncpy(char *dst
, const char *src
, uptr n
) {
223 for (i
= 0; i
< n
&& src
[i
]; i
++)
225 internal_memset(dst
+ i
, '\0', n
- i
);
229 wchar_t *internal_wcsncpy(wchar_t *dst
, const wchar_t *src
, uptr n
) {
231 for (i
= 0; i
< n
&& src
[i
]; ++i
)
233 internal_memset(dst
+ i
, 0, (n
- i
) * sizeof(wchar_t));
237 uptr
internal_strnlen(const char *s
, uptr maxlen
) {
239 while (i
< maxlen
&& s
[i
]) i
++;
243 char *internal_strstr(const char *haystack
, const char *needle
) {
244 // This is O(N^2), but we are not using it in hot places.
245 uptr len1
= internal_strlen(haystack
);
246 uptr len2
= internal_strlen(needle
);
247 if (len1
< len2
) return nullptr;
248 for (uptr pos
= 0; pos
<= len1
- len2
; pos
++) {
249 if (internal_memcmp(haystack
+ pos
, needle
, len2
) == 0)
250 return const_cast<char *>(haystack
) + pos
;
255 s64
internal_simple_strtoll(const char *nptr
, const char **endptr
, int base
) {
257 while (IsSpace(*nptr
)) nptr
++;
260 bool have_digits
= false;
261 char *old_nptr
= const_cast<char *>(nptr
);
265 } else if (*nptr
== '-') {
269 while (IsDigit(*nptr
)) {
270 res
= (res
<= UINT64_MAX
/ 10) ? res
* 10 : UINT64_MAX
;
271 int digit
= ((*nptr
) - '0');
272 res
= (res
<= UINT64_MAX
- digit
) ? res
+ digit
: UINT64_MAX
;
277 *endptr
= (have_digits
) ? const_cast<char *>(nptr
) : old_nptr
;
280 return (s64
)(Min((u64
)INT64_MAX
, res
));
282 return (res
> INT64_MAX
) ? INT64_MIN
: ((s64
)res
* -1);
286 uptr
internal_wcslen(const wchar_t *s
) {
292 uptr
internal_wcsnlen(const wchar_t *s
, uptr maxlen
) {
294 while (i
< maxlen
&& s
[i
]) i
++;
298 bool mem_is_zero(const char *beg
, uptr size
) {
299 CHECK_LE(size
, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
300 const char *end
= beg
+ size
;
301 uptr
*aligned_beg
= (uptr
*)RoundUpTo((uptr
)beg
, sizeof(uptr
));
302 uptr
*aligned_end
= (uptr
*)RoundDownTo((uptr
)end
, sizeof(uptr
));
305 for (const char *mem
= beg
; mem
< (char*)aligned_beg
&& mem
< end
; mem
++)
308 for (; aligned_beg
< aligned_end
; aligned_beg
++)
311 if ((char *)aligned_end
>= beg
) {
312 for (const char *mem
= (char *)aligned_end
; mem
< end
; mem
++) all
|= *mem
;
317 } // namespace __sanitizer