]> git.proxmox.com Git - rustc.git/blame - src/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / compiler-rt / lib / sanitizer_common / sanitizer_libc.cc
CommitLineData
1a4d82fc
JJ
1//===-- sanitizer_libc.cc -------------------------------------------------===//
2//
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
11// run-time libraries. See sanitizer_libc.h for details.
12//===----------------------------------------------------------------------===//
92a42be0 13
1a4d82fc
JJ
14#include "sanitizer_allocator_internal.h"
15#include "sanitizer_common.h"
16#include "sanitizer_libc.h"
17
18namespace __sanitizer {
19
1a4d82fc 20s64 internal_atoll(const char *nptr) {
92a42be0 21 return internal_simple_strtoll(nptr, nullptr, 10);
1a4d82fc
JJ
22}
23
24void *internal_memchr(const void *s, int c, uptr n) {
92a42be0 25 const char *t = (const char *)s;
1a4d82fc
JJ
26 for (uptr i = 0; i < n; ++i, ++t)
27 if (*t == c)
92a42be0
SL
28 return reinterpret_cast<void *>(const_cast<char *>(t));
29 return nullptr;
30}
31
32void *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;
1a4d82fc
JJ
39}
40
41int internal_memcmp(const void* s1, const void* s2, uptr n) {
92a42be0
SL
42 const char *t1 = (const char *)s1;
43 const char *t2 = (const char *)s2;
1a4d82fc
JJ
44 for (uptr i = 0; i < n; ++i, ++t1, ++t2)
45 if (*t1 != *t2)
46 return *t1 < *t2 ? -1 : 1;
47 return 0;
48}
49
50void *internal_memcpy(void *dest, const void *src, uptr n) {
51 char *d = (char*)dest;
92a42be0 52 const char *s = (const char *)src;
1a4d82fc
JJ
53 for (uptr i = 0; i < n; ++i)
54 d[i] = s[i];
55 return dest;
56}
57
58void *internal_memmove(void *dest, const void *src, uptr n) {
59 char *d = (char*)dest;
92a42be0 60 const char *s = (const char *)src;
1a4d82fc
JJ
61 sptr i, signed_n = (sptr)n;
62 CHECK_GE(signed_n, 0);
63 if (d < s) {
64 for (i = 0; i < signed_n; ++i)
65 d[i] = s[i];
66 } else {
67 if (d > s && signed_n > 0)
68 for (i = signed_n - 1; i >= 0 ; --i) {
69 d[i] = s[i];
70 }
71 }
72 return dest;
73}
74
75// 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;
92a42be0
SL
81 // Make sure this does not become memset.
82 SanitizerBreakOptimization(nullptr);
1a4d82fc
JJ
83 }
84}
85
86void *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
98uptr internal_strcspn(const char *s, const char *reject) {
99 uptr i;
100 for (i = 0; s[i]; i++) {
92a42be0 101 if (internal_strchr(reject, s[i]))
1a4d82fc
JJ
102 return i;
103 }
104 return i;
105}
106
107char* 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
92a42be0
SL
115char* 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
1a4d82fc
JJ
123int 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
135int 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
147char* internal_strchr(const char *s, int c) {
148 while (true) {
149 if (*s == (char)c)
92a42be0 150 return const_cast<char *>(s);
1a4d82fc 151 if (*s == 0)
92a42be0 152 return nullptr;
1a4d82fc
JJ
153 s++;
154 }
155}
156
157char *internal_strchrnul(const char *s, int c) {
158 char *res = internal_strchr(s, c);
159 if (!res)
92a42be0 160 res = const_cast<char *>(s) + internal_strlen(s);
1a4d82fc
JJ
161 return res;
162}
163
164char *internal_strrchr(const char *s, int c) {
92a42be0 165 const char *res = nullptr;
1a4d82fc
JJ
166 for (uptr i = 0; s[i]; i++) {
167 if (s[i] == c) res = s + i;
168 }
92a42be0 169 return const_cast<char *>(res);
1a4d82fc
JJ
170}
171
172uptr internal_strlen(const char *s) {
173 uptr i = 0;
174 while (s[i]) i++;
175 return i;
176}
177
178char *internal_strncat(char *dst, const char *src, uptr n) {
179 uptr len = internal_strlen(dst);
180 uptr i;
181 for (i = 0; i < n && src[i]; i++)
182 dst[len + i] = src[i];
183 dst[len + i] = 0;
184 return dst;
185}
186
187char *internal_strncpy(char *dst, const char *src, uptr n) {
188 uptr i;
189 for (i = 0; i < n && src[i]; i++)
190 dst[i] = src[i];
191 internal_memset(dst + i, '\0', n - i);
192 return dst;
193}
194
195uptr internal_strnlen(const char *s, uptr maxlen) {
196 uptr i = 0;
197 while (i < maxlen && s[i]) i++;
198 return i;
199}
200
201char *internal_strstr(const char *haystack, const char *needle) {
202 // This is O(N^2), but we are not using it in hot places.
203 uptr len1 = internal_strlen(haystack);
204 uptr len2 = internal_strlen(needle);
92a42be0 205 if (len1 < len2) return nullptr;
1a4d82fc
JJ
206 for (uptr pos = 0; pos <= len1 - len2; pos++) {
207 if (internal_memcmp(haystack + pos, needle, len2) == 0)
92a42be0 208 return const_cast<char *>(haystack) + pos;
1a4d82fc 209 }
92a42be0 210 return nullptr;
1a4d82fc
JJ
211}
212
213s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
214 CHECK_EQ(base, 10);
215 while (IsSpace(*nptr)) nptr++;
216 int sgn = 1;
217 u64 res = 0;
218 bool have_digits = false;
92a42be0 219 char *old_nptr = const_cast<char *>(nptr);
1a4d82fc
JJ
220 if (*nptr == '+') {
221 sgn = 1;
222 nptr++;
223 } else if (*nptr == '-') {
224 sgn = -1;
225 nptr++;
226 }
227 while (IsDigit(*nptr)) {
228 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
229 int digit = ((*nptr) - '0');
230 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
231 have_digits = true;
232 nptr++;
233 }
92a42be0
SL
234 if (endptr) {
235 *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr;
1a4d82fc
JJ
236 }
237 if (sgn > 0) {
238 return (s64)(Min((u64)INT64_MAX, res));
239 } else {
240 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
241 }
242}
243
244bool mem_is_zero(const char *beg, uptr size) {
245 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
246 const char *end = beg + size;
247 uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
248 uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
249 uptr all = 0;
250 // Prologue.
251 for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
252 all |= *mem;
253 // Aligned loop.
254 for (; aligned_beg < aligned_end; aligned_beg++)
255 all |= *aligned_beg;
256 // Epilogue.
257 if ((char*)aligned_end >= beg)
258 for (const char *mem = (char*)aligned_end; mem < end; mem++)
259 all |= *mem;
260 return all == 0;
261}
262
92a42be0 263} // namespace __sanitizer