sanitizer_libc.cc revision eb2809311c94b73c269ccef8d68ae368642e5754
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#include "sanitizer_common.h"
14#include "sanitizer_libc.h"
15
16namespace __sanitizer {
17
18s64 internal_atoll(const char *nptr) {
19  return internal_simple_strtoll(nptr, (char**)0, 10);
20}
21
22void *internal_memchr(const void *s, int c, uptr n) {
23  const char* t = (char*)s;
24  for (uptr i = 0; i < n; ++i, ++t)
25    if (*t == c)
26      return (void*)t;
27  return 0;
28}
29
30int internal_memcmp(const void* s1, const void* s2, uptr n) {
31  const char* t1 = (char*)s1;
32  const char* t2 = (char*)s2;
33  for (uptr i = 0; i < n; ++i, ++t1, ++t2)
34    if (*t1 != *t2)
35      return *t1 < *t2 ? -1 : 1;
36  return 0;
37}
38
39void *internal_memcpy(void *dest, const void *src, uptr n) {
40  char *d = (char*)dest;
41  char *s = (char*)src;
42  for (uptr i = 0; i < n; ++i)
43    d[i] = s[i];
44  return dest;
45}
46
47void *internal_memmove(void *dest, const void *src, uptr n) {
48  char *d = (char*)dest;
49  char *s = (char*)src;
50  sptr i, signed_n = (sptr)n;
51  CHECK_GE(signed_n, 0);
52  if (d < s) {
53    for (i = 0; i < signed_n; ++i)
54      d[i] = s[i];
55  } else {
56    if (d > s && signed_n > 0)
57      for (i = signed_n - 1; i >= 0 ; --i) {
58        d[i] = s[i];
59      }
60  }
61  return dest;
62}
63
64void *internal_memset(void* s, int c, uptr n) {
65  // The next line prevents Clang from making a call to memset() instead of the
66  // loop below.
67  // FIXME: building the runtime with -ffreestanding is a better idea. However
68  // there currently are linktime problems due to PR12396.
69  char volatile *t = (char*)s;
70  for (uptr i = 0; i < n; ++i, ++t) {
71    *t = c;
72  }
73  return s;
74}
75
76uptr internal_strcspn(const char *s, const char *reject) {
77  uptr i;
78  for (i = 0; s[i]; i++) {
79    if (internal_strchr(reject, s[i]) != 0)
80      return i;
81  }
82  return i;
83}
84
85char* internal_strdup(const char *s) {
86  uptr len = internal_strlen(s);
87  char *s2 = (char*)InternalAlloc(len + 1);
88  internal_memcpy(s2, s, len);
89  s2[len] = 0;
90  return s2;
91}
92
93int internal_strcmp(const char *s1, const char *s2) {
94  while (true) {
95    unsigned c1 = *s1;
96    unsigned c2 = *s2;
97    if (c1 != c2) return (c1 < c2) ? -1 : 1;
98    if (c1 == 0) break;
99    s1++;
100    s2++;
101  }
102  return 0;
103}
104
105int internal_strncmp(const char *s1, const char *s2, uptr n) {
106  for (uptr i = 0; i < n; i++) {
107    unsigned c1 = *s1;
108    unsigned c2 = *s2;
109    if (c1 != c2) return (c1 < c2) ? -1 : 1;
110    if (c1 == 0) break;
111    s1++;
112    s2++;
113  }
114  return 0;
115}
116
117char* internal_strchr(const char *s, int c) {
118  while (true) {
119    if (*s == (char)c)
120      return (char*)s;
121    if (*s == 0)
122      return 0;
123    s++;
124  }
125}
126
127char *internal_strrchr(const char *s, int c) {
128  const char *res = 0;
129  for (uptr i = 0; s[i]; i++) {
130    if (s[i] == c) res = s + i;
131  }
132  return (char*)res;
133}
134
135uptr internal_strlen(const char *s) {
136  uptr i = 0;
137  while (s[i]) i++;
138  return i;
139}
140
141char *internal_strncat(char *dst, const char *src, uptr n) {
142  uptr len = internal_strlen(dst);
143  uptr i;
144  for (i = 0; i < n && src[i]; i++)
145    dst[len + i] = src[i];
146  dst[len + i] = 0;
147  return dst;
148}
149
150char *internal_strncpy(char *dst, const char *src, uptr n) {
151  uptr i;
152  for (i = 0; i < n && src[i]; i++)
153    dst[i] = src[i];
154  for (; i < n; i++)
155    dst[i] = '\0';
156  return dst;
157}
158
159uptr internal_strnlen(const char *s, uptr maxlen) {
160  uptr i = 0;
161  while (i < maxlen && s[i]) i++;
162  return i;
163}
164
165char *internal_strstr(const char *haystack, const char *needle) {
166  // This is O(N^2), but we are not using it in hot places.
167  uptr len1 = internal_strlen(haystack);
168  uptr len2 = internal_strlen(needle);
169  if (len1 < len2) return 0;
170  for (uptr pos = 0; pos <= len1 - len2; pos++) {
171    if (internal_memcmp(haystack + pos, needle, len2) == 0)
172      return (char*)haystack + pos;
173  }
174  return 0;
175}
176
177s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
178  CHECK_EQ(base, 10);
179  while (IsSpace(*nptr)) nptr++;
180  int sgn = 1;
181  u64 res = 0;
182  bool have_digits = false;
183  char *old_nptr = (char*)nptr;
184  if (*nptr == '+') {
185    sgn = 1;
186    nptr++;
187  } else if (*nptr == '-') {
188    sgn = -1;
189    nptr++;
190  }
191  while (IsDigit(*nptr)) {
192    res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
193    int digit = ((*nptr) - '0');
194    res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
195    have_digits = true;
196    nptr++;
197  }
198  if (endptr != 0) {
199    *endptr = (have_digits) ? (char*)nptr : old_nptr;
200  }
201  if (sgn > 0) {
202    return (s64)(Min((u64)INT64_MAX, res));
203  } else {
204    return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
205  }
206}
207
208bool mem_is_zero(const char *beg, uptr size) {
209  CHECK_LE(size, 1UL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
210  const char *end = beg + size;
211  uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
212  uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
213  uptr all = 0;
214  // Prologue.
215  for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
216    all |= *mem;
217  // Aligned loop.
218  for (; aligned_beg < aligned_end; aligned_beg++)
219    all |= *aligned_beg;
220  // Epilogue.
221  if ((char*)aligned_end >= beg)
222    for (const char *mem = (char*)aligned_end; mem < end; mem++)
223      all |= *mem;
224  return all == 0;
225}
226
227}  // namespace __sanitizer
228