blob: 62b9bf7aef06ac295858712a549c098689fb63ee [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 Samsonovf7667cc2012-06-07 11:54:08 +000013#include "sanitizer_common.h"
Kostya Serebryany16e00752012-05-31 13:42:53 +000014#include "sanitizer_libc.h"
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +000015
16namespace __sanitizer {
17
Alexey Samsonovc9256972012-06-15 13:09:52 +000018s64 internal_atoll(const char *nptr) {
19 return internal_simple_strtoll(nptr, (char**)0, 10);
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +000020}
21
Alexey Samsonov1f11d312012-06-05 09:49:25 +000022void *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
Alexey Samsonov327c1c12012-06-14 14:04:54 +000030int 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
Alexey Samsonovf7667cc2012-06-07 11:54:08 +000039void *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
Alexey Samsonov4fac1482012-06-08 14:11:12 +000047void *internal_memset(void* s, int c, uptr n) {
48 // The next line prevents Clang from making a call to memset() instead of the
49 // loop below.
50 // FIXME: building the runtime with -ffreestanding is a better idea. However
51 // there currently are linktime problems due to PR12396.
52 char volatile *t = (char*)s;
53 for (uptr i = 0; i < n; ++i, ++t) {
54 *t = c;
55 }
56 return s;
57}
58
Alexey Samsonovf7667cc2012-06-07 11:54:08 +000059char* internal_strdup(const char *s) {
60 uptr len = internal_strlen(s);
61 char *s2 = (char*)InternalAlloc(len + 1);
62 internal_memcpy(s2, s, len);
63 s2[len] = 0;
64 return s2;
65}
66
Alexey Samsonovc0d78c12012-06-04 13:27:49 +000067int internal_strcmp(const char *s1, const char *s2) {
68 while (true) {
69 unsigned c1 = *s1;
70 unsigned c2 = *s2;
71 if (c1 != c2) return (c1 < c2) ? -1 : 1;
72 if (c1 == 0) break;
73 s1++;
74 s2++;
75 }
76 return 0;
77}
78
Alexey Samsonov88207ab2012-06-15 12:24:07 +000079char* internal_strchr(const char *s, int c) {
80 while (true) {
81 if (*s == (char)c)
82 return (char*)s;
83 if (*s == 0)
84 return 0;
85 s++;
86 }
87}
88
Alexey Samsonov4fac1482012-06-08 14:11:12 +000089char *internal_strrchr(const char *s, int c) {
90 const char *res = 0;
91 for (uptr i = 0; s[i]; i++) {
92 if (s[i] == c) res = s + i;
93 }
94 return (char*)res;
95}
96
Alexey Samsonov230c3be2012-06-06 09:26:25 +000097uptr internal_strlen(const char *s) {
98 uptr i = 0;
99 while (s[i]) i++;
100 return i;
101}
102
Alexey Samsonovc9256972012-06-15 13:09:52 +0000103char *internal_strncat(char *dst, const char *src, uptr n) {
104 uptr len = internal_strlen(dst);
105 uptr i;
106 for (i = 0; i < n && src[i]; i++)
107 dst[len + i] = src[i];
108 dst[len + i] = 0;
109 return dst;
110}
111
Alexey Samsonov3836ff22012-06-04 10:30:16 +0000112char *internal_strncpy(char *dst, const char *src, uptr n) {
113 uptr i;
114 for (i = 0; i < n && src[i]; i++)
115 dst[i] = src[i];
116 for (; i < n; i++)
117 dst[i] = '\0';
118 return dst;
119}
120
Alexey Samsonovc9256972012-06-15 13:09:52 +0000121uptr internal_strnlen(const char *s, uptr maxlen) {
122 uptr i = 0;
123 while (i < maxlen && s[i]) i++;
124 return i;
125}
126
127char *internal_strstr(const char *haystack, const char *needle) {
128 // This is O(N^2), but we are not using it in hot places.
129 uptr len1 = internal_strlen(haystack);
130 uptr len2 = internal_strlen(needle);
131 if (len1 < len2) return 0;
132 for (uptr pos = 0; pos <= len1 - len2; pos++) {
133 if (internal_memcmp(haystack + pos, needle, len2) == 0)
134 return (char*)haystack + pos;
135 }
136 return 0;
137}
138
139s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
140 CHECK(base == 10);
141 while (IsSpace(*nptr)) nptr++;
142 int sgn = 1;
143 u64 res = 0;
144 bool have_digits = false;
145 char *old_nptr = (char*)nptr;
146 if (*nptr == '+') {
147 sgn = 1;
148 nptr++;
149 } else if (*nptr == '-') {
150 sgn = -1;
151 nptr++;
152 }
153 while (IsDigit(*nptr)) {
154 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
155 int digit = ((*nptr) - '0');
156 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
157 have_digits = true;
158 nptr++;
159 }
160 if (endptr != 0) {
161 *endptr = (have_digits) ? (char*)nptr : old_nptr;
162 }
163 if (sgn > 0) {
164 return (s64)(Min((u64)INT64_MAX, res));
165 } else {
166 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
167 }
168}
169
Kostya Serebryanyb3cedf92012-05-29 12:18:18 +0000170} // namespace __sanitizer