1 //===-- sanitizer_libc.cc -------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries. See sanitizer_libc.h for details.
10 //===----------------------------------------------------------------------===//
12 #include "sanitizer_allocator_internal.h"
13 #include "sanitizer_common.h"
14 #include "sanitizer_libc.h"
16 namespace __sanitizer
{
18 s64
internal_atoll(const char *nptr
) {
19 return internal_simple_strtoll(nptr
, nullptr, 10);
22 void *internal_memchr(const void *s
, int c
, uptr n
) {
23 const char *t
= (const char *)s
;
24 for (uptr i
= 0; i
< n
; ++i
, ++t
)
26 return reinterpret_cast<void *>(const_cast<char *>(t
));
30 void *internal_memrchr(const void *s
, int c
, uptr n
) {
31 const char *t
= (const char *)s
;
33 for (uptr i
= 0; i
< n
; ++i
, ++t
) {
34 if (*t
== c
) res
= reinterpret_cast<void *>(const_cast<char *>(t
));
39 int internal_memcmp(const void* s1
, const void* s2
, uptr n
) {
40 const char *t1
= (const char *)s1
;
41 const char *t2
= (const char *)s2
;
42 for (uptr i
= 0; i
< n
; ++i
, ++t1
, ++t2
)
44 return *t1
< *t2
? -1 : 1;
48 void *internal_memcpy(void *dest
, const void *src
, uptr n
) {
49 char *d
= (char*)dest
;
50 const char *s
= (const char *)src
;
51 for (uptr i
= 0; i
< n
; ++i
)
56 void *internal_memmove(void *dest
, const void *src
, uptr n
) {
57 char *d
= (char*)dest
;
58 const char *s
= (const char *)src
;
59 sptr i
, signed_n
= (sptr
)n
;
60 CHECK_GE(signed_n
, 0);
62 for (i
= 0; i
< signed_n
; ++i
)
65 if (d
> s
&& signed_n
> 0)
66 for (i
= signed_n
- 1; i
>= 0 ; --i
) {
73 // Semi-fast bzero for 16-aligned data. Still far from peak performance.
74 void internal_bzero_aligned16(void *s
, uptr n
) {
75 struct ALIGNED(16) S16
{ u64 a
, b
; };
76 CHECK_EQ((reinterpret_cast<uptr
>(s
) | n
) & 15, 0);
77 for (S16
*p
= reinterpret_cast<S16
*>(s
), *end
= p
+ n
/ 16; p
< end
; p
++) {
79 // Make sure this does not become memset.
80 SanitizerBreakOptimization(nullptr);
84 void *internal_memset(void* s
, int c
, uptr n
) {
85 // The next line prevents Clang from making a call to memset() instead of the
87 // FIXME: building the runtime with -ffreestanding is a better idea. However
88 // there currently are linktime problems due to PR12396.
89 char volatile *t
= (char*)s
;
90 for (uptr i
= 0; i
< n
; ++i
, ++t
) {
96 uptr
internal_strcspn(const char *s
, const char *reject
) {
98 for (i
= 0; s
[i
]; i
++) {
99 if (internal_strchr(reject
, s
[i
]))
105 char* internal_strdup(const char *s
) {
106 uptr len
= internal_strlen(s
);
107 char *s2
= (char*)InternalAlloc(len
+ 1);
108 internal_memcpy(s2
, s
, len
);
113 char* internal_strndup(const char *s
, uptr n
) {
114 uptr len
= internal_strnlen(s
, n
);
115 char *s2
= (char*)InternalAlloc(len
+ 1);
116 internal_memcpy(s2
, s
, len
);
121 int internal_strcmp(const char *s1
, const char *s2
) {
125 if (c1
!= c2
) return (c1
< c2
) ? -1 : 1;
133 int internal_strncmp(const char *s1
, const char *s2
, uptr n
) {
134 for (uptr i
= 0; i
< n
; i
++) {
137 if (c1
!= c2
) return (c1
< c2
) ? -1 : 1;
145 char* internal_strchr(const char *s
, int c
) {
148 return const_cast<char *>(s
);
155 char *internal_strchrnul(const char *s
, int c
) {
156 char *res
= internal_strchr(s
, c
);
158 res
= const_cast<char *>(s
) + internal_strlen(s
);
162 char *internal_strrchr(const char *s
, int c
) {
163 const char *res
= nullptr;
164 for (uptr i
= 0; s
[i
]; i
++) {
165 if (s
[i
] == c
) res
= s
+ i
;
167 return const_cast<char *>(res
);
170 uptr
internal_strlen(const char *s
) {
176 uptr
internal_strlcat(char *dst
, const char *src
, uptr maxlen
) {
177 const uptr srclen
= internal_strlen(src
);
178 const uptr dstlen
= internal_strnlen(dst
, maxlen
);
179 if (dstlen
== maxlen
) return maxlen
+ srclen
;
180 if (srclen
< maxlen
- dstlen
) {
181 internal_memmove(dst
+ dstlen
, src
, srclen
+ 1);
183 internal_memmove(dst
+ dstlen
, src
, maxlen
- dstlen
- 1);
184 dst
[maxlen
- 1] = '\0';
186 return dstlen
+ srclen
;
189 char *internal_strncat(char *dst
, const char *src
, uptr n
) {
190 uptr len
= internal_strlen(dst
);
192 for (i
= 0; i
< n
&& src
[i
]; i
++)
193 dst
[len
+ i
] = src
[i
];
198 uptr
internal_strlcpy(char *dst
, const char *src
, uptr maxlen
) {
199 const uptr srclen
= internal_strlen(src
);
200 if (srclen
< maxlen
) {
201 internal_memmove(dst
, src
, srclen
+ 1);
202 } else if (maxlen
!= 0) {
203 internal_memmove(dst
, src
, maxlen
- 1);
204 dst
[maxlen
- 1] = '\0';
209 char *internal_strncpy(char *dst
, const char *src
, uptr n
) {
211 for (i
= 0; i
< n
&& src
[i
]; i
++)
213 internal_memset(dst
+ i
, '\0', n
- i
);
217 uptr
internal_strnlen(const char *s
, uptr maxlen
) {
219 while (i
< maxlen
&& s
[i
]) i
++;
223 char *internal_strstr(const char *haystack
, const char *needle
) {
224 // This is O(N^2), but we are not using it in hot places.
225 uptr len1
= internal_strlen(haystack
);
226 uptr len2
= internal_strlen(needle
);
227 if (len1
< len2
) return nullptr;
228 for (uptr pos
= 0; pos
<= len1
- len2
; pos
++) {
229 if (internal_memcmp(haystack
+ pos
, needle
, len2
) == 0)
230 return const_cast<char *>(haystack
) + pos
;
235 uptr
internal_wcslen(const wchar_t *s
) {
241 s64
internal_simple_strtoll(const char *nptr
, char **endptr
, int base
) {
243 while (IsSpace(*nptr
)) nptr
++;
246 bool have_digits
= false;
247 char *old_nptr
= const_cast<char *>(nptr
);
251 } else if (*nptr
== '-') {
255 while (IsDigit(*nptr
)) {
256 res
= (res
<= UINT64_MAX
/ 10) ? res
* 10 : UINT64_MAX
;
257 int digit
= ((*nptr
) - '0');
258 res
= (res
<= UINT64_MAX
- digit
) ? res
+ digit
: UINT64_MAX
;
263 *endptr
= (have_digits
) ? const_cast<char *>(nptr
) : old_nptr
;
266 return (s64
)(Min((u64
)INT64_MAX
, res
));
268 return (res
> INT64_MAX
) ? INT64_MIN
: ((s64
)res
* -1);
272 bool mem_is_zero(const char *beg
, uptr size
) {
273 CHECK_LE(size
, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
274 const char *end
= beg
+ size
;
275 uptr
*aligned_beg
= (uptr
*)RoundUpTo((uptr
)beg
, sizeof(uptr
));
276 uptr
*aligned_end
= (uptr
*)RoundDownTo((uptr
)end
, sizeof(uptr
));
279 for (const char *mem
= beg
; mem
< (char*)aligned_beg
&& mem
< end
; mem
++)
282 for (; aligned_beg
< aligned_end
; aligned_beg
++)
285 if ((char*)aligned_end
>= beg
)
286 for (const char *mem
= (char*)aligned_end
; mem
< end
; mem
++)
291 } // namespace __sanitizer