blob: cf31e689653f0ef4e6aa9929d339127c2f7b64a5 [file] [log] [blame]
Alexey Samsonov603c4be2012-06-04 13:55:19 +00001//===-- sanitizer_libc.cc -------------------------------------------------===//
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +00002//
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
Kostya Serebryany16e00752012-05-31 13:42:53 +000011// run-time libraries. See sanitizer_libc.h for details.
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +000012//===----------------------------------------------------------------------===//
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080013
Alexey Samsonov1f3c2fe2013-05-29 09:15:39 +000014#include "sanitizer_allocator_internal.h"
Alexey Samsonovf7667cc2012-06-07 11:54:08 +000015#include "sanitizer_common.h"
Kostya Serebryany16e00752012-05-31 13:42:53 +000016#include "sanitizer_libc.h"
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +000017
18namespace __sanitizer {
19
Alexey Samsonovc9256972012-06-15 13:09:52 +000020s64 internal_atoll(const char *nptr) {
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080021 return internal_simple_strtoll(nptr, nullptr, 10);
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +000022}
23
Alexey Samsonov1f11d312012-06-05 09:49:25 +000024void *internal_memchr(const void *s, int c, uptr n) {
Stephen Hines6d186232014-11-26 17:56:19 -080025 const char *t = (const char *)s;
Alexey Samsonov1f11d312012-06-05 09:49:25 +000026 for (uptr i = 0; i < n; ++i, ++t)
27 if (*t == c)
Stephen Hines6d186232014-11-26 17:56:19 -080028 return reinterpret_cast<void *>(const_cast<char *>(t));
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080029 return nullptr;
Alexey Samsonov1f11d312012-06-05 09:49:25 +000030}
31
Stephen Hines86277eb2015-03-23 12:06:32 -070032void *internal_memrchr(const void *s, int c, uptr n) {
33 const char *t = (const char *)s;
34 void *res = nullptr;
35 for (uptr i = 0; i < n; ++i, ++t) {
36 if (*t == c) res = reinterpret_cast<void *>(const_cast<char *>(t));
37 }
38 return res;
39}
40
Alexey Samsonov327c1c12012-06-14 14:04:54 +000041int internal_memcmp(const void* s1, const void* s2, uptr n) {
Stephen Hines6d186232014-11-26 17:56:19 -080042 const char *t1 = (const char *)s1;
43 const char *t2 = (const char *)s2;
Alexey Samsonov327c1c12012-06-14 14:04:54 +000044 for (uptr i = 0; i < n; ++i, ++t1, ++t2)
45 if (*t1 != *t2)
46 return *t1 < *t2 ? -1 : 1;
47 return 0;
48}
49
Alexey Samsonovf7667cc2012-06-07 11:54:08 +000050void *internal_memcpy(void *dest, const void *src, uptr n) {
51 char *d = (char*)dest;
Stephen Hines6d186232014-11-26 17:56:19 -080052 const char *s = (const char *)src;
Alexey Samsonovf7667cc2012-06-07 11:54:08 +000053 for (uptr i = 0; i < n; ++i)
54 d[i] = s[i];
55 return dest;
56}
57
Alexander Potapenkof1673e62012-10-15 15:34:41 +000058void *internal_memmove(void *dest, const void *src, uptr n) {
59 char *d = (char*)dest;
Stephen Hines6d186232014-11-26 17:56:19 -080060 const char *s = (const char *)src;
Alexander Potapenko71a82732012-10-26 13:47:36 +000061 sptr i, signed_n = (sptr)n;
62 CHECK_GE(signed_n, 0);
Alexander Potapenkof1673e62012-10-15 15:34:41 +000063 if (d < s) {
Alexander Potapenko71a82732012-10-26 13:47:36 +000064 for (i = 0; i < signed_n; ++i)
Alexander Potapenkof1673e62012-10-15 15:34:41 +000065 d[i] = s[i];
66 } else {
Alexander Potapenko71a82732012-10-26 13:47:36 +000067 if (d > s && signed_n > 0)
68 for (i = signed_n - 1; i >= 0 ; --i) {
Kostya Serebryany5759d922012-10-16 04:50:32 +000069 d[i] = s[i];
Alexander Potapenkof1673e62012-10-15 15:34:41 +000070 }
71 }
72 return dest;
73}
74
Stephen Hines2d1fdb22014-05-28 23:58:16 -070075// Semi-fast bzero for 16-aligned data. Still far from peak performance.
76void internal_bzero_aligned16(void *s, uptr n) {
77 struct S16 { u64 a, b; } ALIGNED(16);
78 CHECK_EQ((reinterpret_cast<uptr>(s) | n) & 15, 0);
79 for (S16 *p = reinterpret_cast<S16*>(s), *end = p + n / 16; p < end; p++) {
80 p->a = p->b = 0;
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080081 // Make sure this does not become memset.
82 SanitizerBreakOptimization(nullptr);
Stephen Hines2d1fdb22014-05-28 23:58:16 -070083 }
84}
85
Alexey Samsonov4fac1482012-06-08 14:11:12 +000086void *internal_memset(void* s, int c, uptr n) {
87 // The next line prevents Clang from making a call to memset() instead of the
88 // loop below.
89 // FIXME: building the runtime with -ffreestanding is a better idea. However
90 // there currently are linktime problems due to PR12396.
91 char volatile *t = (char*)s;
92 for (uptr i = 0; i < n; ++i, ++t) {
93 *t = c;
94 }
95 return s;
96}
97
Alexey Samsonov25113472012-08-21 09:26:26 +000098uptr internal_strcspn(const char *s, const char *reject) {
99 uptr i;
100 for (i = 0; s[i]; i++) {
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800101 if (internal_strchr(reject, s[i]))
Alexey Samsonov25113472012-08-21 09:26:26 +0000102 return i;
103 }
104 return i;
105}
106
Alexey Samsonovf7667cc2012-06-07 11:54:08 +0000107char* internal_strdup(const char *s) {
108 uptr len = internal_strlen(s);
109 char *s2 = (char*)InternalAlloc(len + 1);
110 internal_memcpy(s2, s, len);
111 s2[len] = 0;
112 return s2;
113}
114
Stephen Hines86277eb2015-03-23 12:06:32 -0700115char* internal_strndup(const char *s, uptr n) {
116 uptr len = internal_strnlen(s, n);
117 char *s2 = (char*)InternalAlloc(len + 1);
118 internal_memcpy(s2, s, len);
119 s2[len] = 0;
120 return s2;
121}
122
Alexey Samsonovc0d78c12012-06-04 13:27:49 +0000123int internal_strcmp(const char *s1, const char *s2) {
124 while (true) {
125 unsigned c1 = *s1;
126 unsigned c2 = *s2;
127 if (c1 != c2) return (c1 < c2) ? -1 : 1;
128 if (c1 == 0) break;
129 s1++;
130 s2++;
131 }
132 return 0;
133}
134
Alexey Samsonov8cd0df72012-06-18 14:34:59 +0000135int internal_strncmp(const char *s1, const char *s2, uptr n) {
136 for (uptr i = 0; i < n; i++) {
137 unsigned c1 = *s1;
138 unsigned c2 = *s2;
139 if (c1 != c2) return (c1 < c2) ? -1 : 1;
140 if (c1 == 0) break;
141 s1++;
142 s2++;
143 }
144 return 0;
145}
146
Alexey Samsonov88207ab2012-06-15 12:24:07 +0000147char* internal_strchr(const char *s, int c) {
148 while (true) {
149 if (*s == (char)c)
Stephen Hines6d186232014-11-26 17:56:19 -0800150 return const_cast<char *>(s);
Alexey Samsonov88207ab2012-06-15 12:24:07 +0000151 if (*s == 0)
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800152 return nullptr;
Alexey Samsonov88207ab2012-06-15 12:24:07 +0000153 s++;
154 }
155}
156
Alexey Samsonov72870db2013-09-03 13:09:28 +0000157char *internal_strchrnul(const char *s, int c) {
158 char *res = internal_strchr(s, c);
159 if (!res)
Stephen Hines6d186232014-11-26 17:56:19 -0800160 res = const_cast<char *>(s) + internal_strlen(s);
Alexey Samsonov72870db2013-09-03 13:09:28 +0000161 return res;
162}
163
Alexey Samsonov4fac1482012-06-08 14:11:12 +0000164char *internal_strrchr(const char *s, int c) {
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800165 const char *res = nullptr;
Alexey Samsonov4fac1482012-06-08 14:11:12 +0000166 for (uptr i = 0; s[i]; i++) {
167 if (s[i] == c) res = s + i;
168 }
Stephen Hines6d186232014-11-26 17:56:19 -0800169 return const_cast<char *>(res);
Alexey Samsonov4fac1482012-06-08 14:11:12 +0000170}
171
Alexey Samsonov230c3be2012-06-06 09:26:25 +0000172uptr internal_strlen(const char *s) {
173 uptr i = 0;
174 while (s[i]) i++;
175 return i;
176}
177
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800178uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {
179 const uptr srclen = internal_strlen(src);
180 const uptr dstlen = internal_strnlen(dst, maxlen);
181 if (dstlen == maxlen) return maxlen + srclen;
182 if (srclen < maxlen - dstlen) {
183 internal_memmove(dst + dstlen, src, srclen + 1);
184 } else {
185 internal_memmove(dst + dstlen, src, maxlen - dstlen - 1);
186 dst[maxlen - 1] = '\0';
187 }
188 return dstlen + srclen;
189}
190
Alexey Samsonovc9256972012-06-15 13:09:52 +0000191char *internal_strncat(char *dst, const char *src, uptr n) {
192 uptr len = internal_strlen(dst);
193 uptr i;
194 for (i = 0; i < n && src[i]; i++)
195 dst[len + i] = src[i];
196 dst[len + i] = 0;
197 return dst;
198}
199
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800200uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {
201 const uptr srclen = internal_strlen(src);
202 if (srclen < maxlen) {
203 internal_memmove(dst, src, srclen + 1);
204 } else if (maxlen != 0) {
205 internal_memmove(dst, src, maxlen - 1);
206 dst[maxlen - 1] = '\0';
207 }
208 return srclen;
209}
210
Alexey Samsonov3836ff22012-06-04 10:30:16 +0000211char *internal_strncpy(char *dst, const char *src, uptr n) {
212 uptr i;
213 for (i = 0; i < n && src[i]; i++)
214 dst[i] = src[i];
Will Dietz98432982013-08-30 19:53:55 +0000215 internal_memset(dst + i, '\0', n - i);
Alexey Samsonov3836ff22012-06-04 10:30:16 +0000216 return dst;
217}
218
Alexey Samsonovc9256972012-06-15 13:09:52 +0000219uptr internal_strnlen(const char *s, uptr maxlen) {
220 uptr i = 0;
221 while (i < maxlen && s[i]) i++;
222 return i;
223}
224
225char *internal_strstr(const char *haystack, const char *needle) {
226 // This is O(N^2), but we are not using it in hot places.
227 uptr len1 = internal_strlen(haystack);
228 uptr len2 = internal_strlen(needle);
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800229 if (len1 < len2) return nullptr;
Alexey Samsonovc9256972012-06-15 13:09:52 +0000230 for (uptr pos = 0; pos <= len1 - len2; pos++) {
231 if (internal_memcmp(haystack + pos, needle, len2) == 0)
Stephen Hines6d186232014-11-26 17:56:19 -0800232 return const_cast<char *>(haystack) + pos;
Alexey Samsonovc9256972012-06-15 13:09:52 +0000233 }
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800234 return nullptr;
Alexey Samsonovc9256972012-06-15 13:09:52 +0000235}
236
237s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
Kostya Serebryany69850852012-06-20 15:19:17 +0000238 CHECK_EQ(base, 10);
Alexey Samsonovc9256972012-06-15 13:09:52 +0000239 while (IsSpace(*nptr)) nptr++;
240 int sgn = 1;
241 u64 res = 0;
242 bool have_digits = false;
Stephen Hines6d186232014-11-26 17:56:19 -0800243 char *old_nptr = const_cast<char *>(nptr);
Alexey Samsonovc9256972012-06-15 13:09:52 +0000244 if (*nptr == '+') {
245 sgn = 1;
246 nptr++;
247 } else if (*nptr == '-') {
248 sgn = -1;
249 nptr++;
250 }
251 while (IsDigit(*nptr)) {
252 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
253 int digit = ((*nptr) - '0');
254 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
255 have_digits = true;
256 nptr++;
257 }
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800258 if (endptr) {
Stephen Hines6d186232014-11-26 17:56:19 -0800259 *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr;
Alexey Samsonovc9256972012-06-15 13:09:52 +0000260 }
261 if (sgn > 0) {
262 return (s64)(Min((u64)INT64_MAX, res));
263 } else {
264 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
265 }
266}
267
Kostya Serebryanyeb280932012-12-28 15:24:16 +0000268bool mem_is_zero(const char *beg, uptr size) {
Dmitry Vyukov8ceeec42013-02-04 08:07:45 +0000269 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
Kostya Serebryanyeb280932012-12-28 15:24:16 +0000270 const char *end = beg + size;
271 uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
272 uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
273 uptr all = 0;
274 // Prologue.
275 for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
276 all |= *mem;
277 // Aligned loop.
278 for (; aligned_beg < aligned_end; aligned_beg++)
279 all |= *aligned_beg;
280 // Epilogue.
281 if ((char*)aligned_end >= beg)
282 for (const char *mem = (char*)aligned_end; mem < end; mem++)
283 all |= *mem;
284 return all == 0;
285}
286
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800287} // namespace __sanitizer