sanitizer_libc.cc revision f1673e61768cb08d488a75584b61bfdf24ffdac1
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  uptr i;
51  if (d < s) {
52    for (i = 0; i < n; ++i)
53      d[i] = s[i];
54  } else {
55    if (d > s && n > 0)
56      for (i = n - 1; i > 0 ; --i) {
57	d[i] = s[i];
58      }
59  }
60  return dest;
61}
62
63void *internal_memset(void* s, int c, uptr n) {
64  // The next line prevents Clang from making a call to memset() instead of the
65  // loop below.
66  // FIXME: building the runtime with -ffreestanding is a better idea. However
67  // there currently are linktime problems due to PR12396.
68  char volatile *t = (char*)s;
69  for (uptr i = 0; i < n; ++i, ++t) {
70    *t = c;
71  }
72  return s;
73}
74
75uptr internal_strcspn(const char *s, const char *reject) {
76  uptr i;
77  for (i = 0; s[i]; i++) {
78    if (internal_strchr(reject, s[i]) != 0)
79      return i;
80  }
81  return i;
82}
83
84char* internal_strdup(const char *s) {
85  uptr len = internal_strlen(s);
86  char *s2 = (char*)InternalAlloc(len + 1);
87  internal_memcpy(s2, s, len);
88  s2[len] = 0;
89  return s2;
90}
91
92int internal_strcmp(const char *s1, const char *s2) {
93  while (true) {
94    unsigned c1 = *s1;
95    unsigned c2 = *s2;
96    if (c1 != c2) return (c1 < c2) ? -1 : 1;
97    if (c1 == 0) break;
98    s1++;
99    s2++;
100  }
101  return 0;
102}
103
104int internal_strncmp(const char *s1, const char *s2, uptr n) {
105  for (uptr i = 0; i < n; i++) {
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
116char* internal_strchr(const char *s, int c) {
117  while (true) {
118    if (*s == (char)c)
119      return (char*)s;
120    if (*s == 0)
121      return 0;
122    s++;
123  }
124}
125
126char *internal_strrchr(const char *s, int c) {
127  const char *res = 0;
128  for (uptr i = 0; s[i]; i++) {
129    if (s[i] == c) res = s + i;
130  }
131  return (char*)res;
132}
133
134uptr internal_strlen(const char *s) {
135  uptr i = 0;
136  while (s[i]) i++;
137  return i;
138}
139
140char *internal_strncat(char *dst, const char *src, uptr n) {
141  uptr len = internal_strlen(dst);
142  uptr i;
143  for (i = 0; i < n && src[i]; i++)
144    dst[len + i] = src[i];
145  dst[len + i] = 0;
146  return dst;
147}
148
149char *internal_strncpy(char *dst, const char *src, uptr n) {
150  uptr i;
151  for (i = 0; i < n && src[i]; i++)
152    dst[i] = src[i];
153  for (; i < n; i++)
154    dst[i] = '\0';
155  return dst;
156}
157
158uptr internal_strnlen(const char *s, uptr maxlen) {
159  uptr i = 0;
160  while (i < maxlen && s[i]) i++;
161  return i;
162}
163
164char *internal_strstr(const char *haystack, const char *needle) {
165  // This is O(N^2), but we are not using it in hot places.
166  uptr len1 = internal_strlen(haystack);
167  uptr len2 = internal_strlen(needle);
168  if (len1 < len2) return 0;
169  for (uptr pos = 0; pos <= len1 - len2; pos++) {
170    if (internal_memcmp(haystack + pos, needle, len2) == 0)
171      return (char*)haystack + pos;
172  }
173  return 0;
174}
175
176s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
177  CHECK_EQ(base, 10);
178  while (IsSpace(*nptr)) nptr++;
179  int sgn = 1;
180  u64 res = 0;
181  bool have_digits = false;
182  char *old_nptr = (char*)nptr;
183  if (*nptr == '+') {
184    sgn = 1;
185    nptr++;
186  } else if (*nptr == '-') {
187    sgn = -1;
188    nptr++;
189  }
190  while (IsDigit(*nptr)) {
191    res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
192    int digit = ((*nptr) - '0');
193    res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
194    have_digits = true;
195    nptr++;
196  }
197  if (endptr != 0) {
198    *endptr = (have_digits) ? (char*)nptr : old_nptr;
199  }
200  if (sgn > 0) {
201    return (s64)(Min((u64)INT64_MAX, res));
202  } else {
203    return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
204  }
205}
206
207}  // namespace __sanitizer
208