]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / sanitizer_common / sanitizer_libc.cc
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 //===----------------------------------------------------------------------===//
13
14 #include "sanitizer_allocator_internal.h"
15 #include "sanitizer_common.h"
16 #include "sanitizer_libc.h"
17
18 namespace __sanitizer {
19
20 s64 internal_atoll(const char *nptr) {
21   return internal_simple_strtoll(nptr, nullptr, 10);
22 }
23
24 void *internal_memchr(const void *s, int c, uptr n) {
25   const char *t = (const char *)s;
26   for (uptr i = 0; i < n; ++i, ++t)
27     if (*t == c)
28       return reinterpret_cast<void *>(const_cast<char *>(t));
29   return nullptr;
30 }
31
32 void *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
41 int internal_memcmp(const void* s1, const void* s2, uptr n) {
42   const char *t1 = (const char *)s1;
43   const char *t2 = (const char *)s2;
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
50 void *internal_memcpy(void *dest, const void *src, uptr n) {
51   char *d = (char*)dest;
52   const char *s = (const char *)src;
53   for (uptr i = 0; i < n; ++i)
54     d[i] = s[i];
55   return dest;
56 }
57
58 void *internal_memmove(void *dest, const void *src, uptr n) {
59   char *d = (char*)dest;
60   const char *s = (const char *)src;
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 void *internal_memset(void* s, int c, uptr n) {
76   // The next line prevents Clang from making a call to memset() instead of the
77   // loop below.
78   // FIXME: building the runtime with -ffreestanding is a better idea. However
79   // there currently are linktime problems due to PR12396.
80   char volatile *t = (char*)s;
81   for (uptr i = 0; i < n; ++i, ++t) {
82     *t = c;
83   }
84   return s;
85 }
86
87 uptr internal_strcspn(const char *s, const char *reject) {
88   uptr i;
89   for (i = 0; s[i]; i++) {
90     if (internal_strchr(reject, s[i]))
91       return i;
92   }
93   return i;
94 }
95
96 char* internal_strdup(const char *s) {
97   uptr len = internal_strlen(s);
98   char *s2 = (char*)InternalAlloc(len + 1);
99   internal_memcpy(s2, s, len);
100   s2[len] = 0;
101   return s2;
102 }
103
104 int internal_strcmp(const char *s1, const char *s2) {
105   while (true) {
106     unsigned c1 = *s1;
107     unsigned c2 = *s2;
108     if (c1 != c2) return (c1 < c2) ? -1 : 1;
109     if (c1 == 0) break;
110     s1++;
111     s2++;
112   }
113   return 0;
114 }
115
116 int internal_strncmp(const char *s1, const char *s2, uptr n) {
117   for (uptr i = 0; i < n; i++) {
118     unsigned c1 = *s1;
119     unsigned c2 = *s2;
120     if (c1 != c2) return (c1 < c2) ? -1 : 1;
121     if (c1 == 0) break;
122     s1++;
123     s2++;
124   }
125   return 0;
126 }
127
128 char* internal_strchr(const char *s, int c) {
129   while (true) {
130     if (*s == (char)c)
131       return const_cast<char *>(s);
132     if (*s == 0)
133       return nullptr;
134     s++;
135   }
136 }
137
138 char *internal_strchrnul(const char *s, int c) {
139   char *res = internal_strchr(s, c);
140   if (!res)
141     res = const_cast<char *>(s) + internal_strlen(s);
142   return res;
143 }
144
145 char *internal_strrchr(const char *s, int c) {
146   const char *res = nullptr;
147   for (uptr i = 0; s[i]; i++) {
148     if (s[i] == c) res = s + i;
149   }
150   return const_cast<char *>(res);
151 }
152
153 uptr internal_strlen(const char *s) {
154   uptr i = 0;
155   while (s[i]) i++;
156   return i;
157 }
158
159 uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {
160   const uptr srclen = internal_strlen(src);
161   const uptr dstlen = internal_strnlen(dst, maxlen);
162   if (dstlen == maxlen) return maxlen + srclen;
163   if (srclen < maxlen - dstlen) {
164     internal_memmove(dst + dstlen, src, srclen + 1);
165   } else {
166     internal_memmove(dst + dstlen, src, maxlen - dstlen - 1);
167     dst[maxlen - 1] = '\0';
168   }
169   return dstlen + srclen;
170 }
171
172 char *internal_strncat(char *dst, const char *src, uptr n) {
173   uptr len = internal_strlen(dst);
174   uptr i;
175   for (i = 0; i < n && src[i]; i++)
176     dst[len + i] = src[i];
177   dst[len + i] = 0;
178   return dst;
179 }
180
181 uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {
182   const uptr srclen = internal_strlen(src);
183   if (srclen < maxlen) {
184     internal_memmove(dst, src, srclen + 1);
185   } else if (maxlen != 0) {
186     internal_memmove(dst, src, maxlen - 1);
187     dst[maxlen - 1] = '\0';
188   }
189   return srclen;
190 }
191
192 char *internal_strncpy(char *dst, const char *src, uptr n) {
193   uptr i;
194   for (i = 0; i < n && src[i]; i++)
195     dst[i] = src[i];
196   internal_memset(dst + i, '\0', n - i);
197   return dst;
198 }
199
200 uptr internal_strnlen(const char *s, uptr maxlen) {
201   uptr i = 0;
202   while (i < maxlen && s[i]) i++;
203   return i;
204 }
205
206 char *internal_strstr(const char *haystack, const char *needle) {
207   // This is O(N^2), but we are not using it in hot places.
208   uptr len1 = internal_strlen(haystack);
209   uptr len2 = internal_strlen(needle);
210   if (len1 < len2) return nullptr;
211   for (uptr pos = 0; pos <= len1 - len2; pos++) {
212     if (internal_memcmp(haystack + pos, needle, len2) == 0)
213       return const_cast<char *>(haystack) + pos;
214   }
215   return nullptr;
216 }
217
218 s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) {
219   CHECK_EQ(base, 10);
220   while (IsSpace(*nptr)) nptr++;
221   int sgn = 1;
222   u64 res = 0;
223   bool have_digits = false;
224   char *old_nptr = const_cast<char *>(nptr);
225   if (*nptr == '+') {
226     sgn = 1;
227     nptr++;
228   } else if (*nptr == '-') {
229     sgn = -1;
230     nptr++;
231   }
232   while (IsDigit(*nptr)) {
233     res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
234     int digit = ((*nptr) - '0');
235     res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
236     have_digits = true;
237     nptr++;
238   }
239   if (endptr) {
240     *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr;
241   }
242   if (sgn > 0) {
243     return (s64)(Min((u64)INT64_MAX, res));
244   } else {
245     return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
246   }
247 }
248
249 bool mem_is_zero(const char *beg, uptr size) {
250   CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
251   const char *end = beg + size;
252   uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
253   uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
254   uptr all = 0;
255   // Prologue.
256   for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
257     all |= *mem;
258   // Aligned loop.
259   for (; aligned_beg < aligned_end; aligned_beg++)
260     all |= *aligned_beg;
261   // Epilogue.
262   if ((char*)aligned_end >= beg)
263     for (const char *mem = (char*)aligned_end; mem < end; mem++)
264       all |= *mem;
265   return all == 0;
266 }
267
268 } // namespace __sanitizer