blob: f875f1fdc4f88d998414a95deb8987fab14da5bd [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//===----------------------------------------------------------------------===//
Alexey Samsonov1f3c2fe2013-05-29 09:15:39 +000013#include "sanitizer_allocator_internal.h"
Alexey Samsonovf7667cc2012-06-07 11:54:08 +000014#include "sanitizer_common.h"
Kostya Serebryany16e00752012-05-31 13:42:53 +000015#include "sanitizer_libc.h"
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +000016
17namespace __sanitizer {
18
Alexey Samsonovc9256972012-06-15 13:09:52 +000019s64 internal_atoll(const char *nptr) {
20 return internal_simple_strtoll(nptr, (char**)0, 10);
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +000021}
22
Alexey Samsonov1f11d312012-06-05 09:49:25 +000023void *internal_memchr(const void *s, int c, uptr n) {
24 const char* t = (char*)s;
25 for (uptr i = 0; i < n; ++i, ++t)
26 if (*t == c)
27 return (void*)t;
28 return 0;
29}
30
Alexey Samsonov327c1c12012-06-14 14:04:54 +000031int internal_memcmp(const void* s1, const void* s2, uptr n) {
32 const char* t1 = (char*)s1;
33 const char* t2 = (char*)s2;
34 for (uptr i = 0; i < n; ++i, ++t1, ++t2)
35 if (*t1 != *t2)
36 return *t1 < *t2 ? -1 : 1;
37 return 0;
38}
39
Alexey Samsonovf7667cc2012-06-07 11:54:08 +000040void *internal_memcpy(void *dest, const void *src, uptr n) {
41 char *d = (char*)dest;
42 char *s = (char*)src;
43 for (uptr i = 0; i < n; ++i)
44 d[i] = s[i];
45 return dest;
46}
47
Alexander Potapenkof1673e62012-10-15 15:34:41 +000048void *internal_memmove(void *dest, const void *src, uptr n) {
49 char *d = (char*)dest;
50 char *s = (char*)src;
Alexander Potapenko71a82732012-10-26 13:47:36 +000051 sptr i, signed_n = (sptr)n;
52 CHECK_GE(signed_n, 0);
Alexander Potapenkof1673e62012-10-15 15:34:41 +000053 if (d < s) {
Alexander Potapenko71a82732012-10-26 13:47:36 +000054 for (i = 0; i < signed_n; ++i)
Alexander Potapenkof1673e62012-10-15 15:34:41 +000055 d[i] = s[i];
56 } else {
Alexander Potapenko71a82732012-10-26 13:47:36 +000057 if (d > s && signed_n > 0)
58 for (i = signed_n - 1; i >= 0 ; --i) {
Kostya Serebryany5759d922012-10-16 04:50:32 +000059 d[i] = s[i];
Alexander Potapenkof1673e62012-10-15 15:34:41 +000060 }
61 }
62 return dest;
63}
64
Alexey Samsonov4fac1482012-06-08 14:11:12 +000065void *internal_memset(void* s, int c, uptr n) {
66 // The next line prevents Clang from making a call to memset() instead of the
67 // loop below.
68 // FIXME: building the runtime with -ffreestanding is a better idea. However
69 // there currently are linktime problems due to PR12396.
70 char volatile *t = (char*)s;
71 for (uptr i = 0; i < n; ++i, ++t) {
72 *t = c;
73 }
74 return s;
75}
76
Alexey Samsonov25113472012-08-21 09:26:26 +000077uptr internal_strcspn(const char *s, const char *reject) {
78 uptr i;
79 for (i = 0; s[i]; i++) {
80 if (internal_strchr(reject, s[i]) != 0)
81 return i;
82 }
83 return i;
84}
85
Alexey Samsonovf7667cc2012-06-07 11:54:08 +000086char* internal_strdup(const char *s) {
87 uptr len = internal_strlen(s);
88 char *s2 = (char*)InternalAlloc(len + 1);
89 internal_memcpy(s2, s, len);
90 s2[len] = 0;
91 return s2;
92}
93
Alexey Samsonovc0d78c12012-06-04 13:27:49 +000094int internal_strcmp(const char *s1, const char *s2) {
95 while (true) {
96 unsigned c1 = *s1;
97 unsigned c2 = *s2;
98 if (c1 != c2) return (c1 < c2) ? -1 : 1;
99 if (c1 == 0) break;
100 s1++;
101 s2++;
102 }
103 return 0;
104}
105
Alexey Samsonov8cd0df72012-06-18 14:34:59 +0000106int internal_strncmp(const char *s1, const char *s2, uptr n) {
107 for (uptr i = 0; i < n; i++) {
108 unsigned c1 = *s1;
109 unsigned c2 = *s2;
110 if (c1 != c2) return (c1 < c2) ? -1 : 1;
111 if (c1 == 0) break;
112 s1++;
113 s2++;
114 }
115 return 0;
116}
117
Alexey Samsonov88207ab2012-06-15 12:24:07 +0000118char* internal_strchr(const char *s, int c) {
119 while (true) {
120 if (*s == (char)c)
121 return (char*)s;
122 if (*s == 0)
123 return 0;
124 s++;
125 }
126}
127
Alexey Samsonov4fac1482012-06-08 14:11:12 +0000128char *internal_strrchr(const char *s, int c) {
129 const char *res = 0;
130 for (uptr i = 0; s[i]; i++) {
131 if (s[i] == c) res = s + i;
132 }
133 return (char*)res;
134}
135
Alexey Samsonov230c3be2012-06-06 09:26:25 +0000136uptr internal_strlen(const char *s) {
137 uptr i = 0;
138 while (s[i]) i++;
139 return i;
140}
141
Alexey Samsonovc9256972012-06-15 13:09:52 +0000142char *internal_strncat(char *dst, const char *src, uptr n) {
143 uptr len = internal_strlen(dst);
144 uptr i;
145 for (i = 0; i < n && src[i]; i++)
146 dst[len + i] = src[i];
147 dst[len + i] = 0;
148 return dst;
149}
150
Alexey Samsonov3836ff22012-06-04 10:30:16 +0000151char *internal_strncpy(char *dst, const char *src, uptr n) {
152 uptr i;
153 for (i = 0; i < n && src[i]; i++)
154 dst[i] = src[i];
155 for (; i < n; i++)
156 dst[i] = '\0';
157 return dst;
158}
159
Alexey Samsonovc9256972012-06-15 13:09:52 +0000160uptr internal_strnlen(const char *s, uptr maxlen) {
161 uptr i = 0;
162 while (i < maxlen && s[i]) i++;
163 return i;
164}
165
166char *internal_strstr(const char *haystack, const char *needle) {
167 // This is O(N^2), but we are not using it in hot places.
168 uptr len1 = internal_strlen(haystack);
169 uptr len2 = internal_strlen(needle);
170 if (len1 < len2) return 0;
171 for (uptr pos = 0; pos <= len1 - len2; pos++) {
172 if (internal_memcmp(haystack + pos, needle, len2) == 0)
173 return (char*)haystack + pos;
174 }
175 return 0;
176}
177
178s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
Kostya Serebryany69850852012-06-20 15:19:17 +0000179 CHECK_EQ(base, 10);
Alexey Samsonovc9256972012-06-15 13:09:52 +0000180 while (IsSpace(*nptr)) nptr++;
181 int sgn = 1;
182 u64 res = 0;
183 bool have_digits = false;
184 char *old_nptr = (char*)nptr;
185 if (*nptr == '+') {
186 sgn = 1;
187 nptr++;
188 } else if (*nptr == '-') {
189 sgn = -1;
190 nptr++;
191 }
192 while (IsDigit(*nptr)) {
193 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
194 int digit = ((*nptr) - '0');
195 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
196 have_digits = true;
197 nptr++;
198 }
199 if (endptr != 0) {
200 *endptr = (have_digits) ? (char*)nptr : old_nptr;
201 }
202 if (sgn > 0) {
203 return (s64)(Min((u64)INT64_MAX, res));
204 } else {
205 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
206 }
207}
208
Kostya Serebryanyeb280932012-12-28 15:24:16 +0000209bool mem_is_zero(const char *beg, uptr size) {
Dmitry Vyukov8ceeec42013-02-04 08:07:45 +0000210 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
Kostya Serebryanyeb280932012-12-28 15:24:16 +0000211 const char *end = beg + size;
212 uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
213 uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
214 uptr all = 0;
215 // Prologue.
216 for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
217 all |= *mem;
218 // Aligned loop.
219 for (; aligned_beg < aligned_end; aligned_beg++)
220 all |= *aligned_beg;
221 // Epilogue.
222 if ((char*)aligned_end >= beg)
223 for (const char *mem = (char*)aligned_end; mem < end; mem++)
224 all |= *mem;
225 return all == 0;
226}
227
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +0000228} // namespace __sanitizer