sanitizer_libc.cc revision 72870db5f2e0e83b2e925eef594dacfae275a8de
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_allocator_internal.h" 14#include "sanitizer_common.h" 15#include "sanitizer_libc.h" 16 17namespace __sanitizer { 18 19s64 internal_atoll(const char *nptr) { 20 return internal_simple_strtoll(nptr, (char**)0, 10); 21} 22 23void *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 31int 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 40void *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 48void *internal_memmove(void *dest, const void *src, uptr n) { 49 char *d = (char*)dest; 50 char *s = (char*)src; 51 sptr i, signed_n = (sptr)n; 52 CHECK_GE(signed_n, 0); 53 if (d < s) { 54 for (i = 0; i < signed_n; ++i) 55 d[i] = s[i]; 56 } else { 57 if (d > s && signed_n > 0) 58 for (i = signed_n - 1; i >= 0 ; --i) { 59 d[i] = s[i]; 60 } 61 } 62 return dest; 63} 64 65void *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 77uptr 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 86char* 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 94int 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 106int 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 118char* 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 128char *internal_strchrnul(const char *s, int c) { 129 char *res = internal_strchr(s, c); 130 if (!res) 131 res = (char*)s + internal_strlen(s); 132 return res; 133} 134 135char *internal_strrchr(const char *s, int c) { 136 const char *res = 0; 137 for (uptr i = 0; s[i]; i++) { 138 if (s[i] == c) res = s + i; 139 } 140 return (char*)res; 141} 142 143uptr internal_strlen(const char *s) { 144 uptr i = 0; 145 while (s[i]) i++; 146 return i; 147} 148 149char *internal_strncat(char *dst, const char *src, uptr n) { 150 uptr len = internal_strlen(dst); 151 uptr i; 152 for (i = 0; i < n && src[i]; i++) 153 dst[len + i] = src[i]; 154 dst[len + i] = 0; 155 return dst; 156} 157 158char *internal_strncpy(char *dst, const char *src, uptr n) { 159 uptr i; 160 for (i = 0; i < n && src[i]; i++) 161 dst[i] = src[i]; 162 internal_memset(dst + i, '\0', n - i); 163 return dst; 164} 165 166uptr internal_strnlen(const char *s, uptr maxlen) { 167 uptr i = 0; 168 while (i < maxlen && s[i]) i++; 169 return i; 170} 171 172char *internal_strstr(const char *haystack, const char *needle) { 173 // This is O(N^2), but we are not using it in hot places. 174 uptr len1 = internal_strlen(haystack); 175 uptr len2 = internal_strlen(needle); 176 if (len1 < len2) return 0; 177 for (uptr pos = 0; pos <= len1 - len2; pos++) { 178 if (internal_memcmp(haystack + pos, needle, len2) == 0) 179 return (char*)haystack + pos; 180 } 181 return 0; 182} 183 184s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) { 185 CHECK_EQ(base, 10); 186 while (IsSpace(*nptr)) nptr++; 187 int sgn = 1; 188 u64 res = 0; 189 bool have_digits = false; 190 char *old_nptr = (char*)nptr; 191 if (*nptr == '+') { 192 sgn = 1; 193 nptr++; 194 } else if (*nptr == '-') { 195 sgn = -1; 196 nptr++; 197 } 198 while (IsDigit(*nptr)) { 199 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX; 200 int digit = ((*nptr) - '0'); 201 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX; 202 have_digits = true; 203 nptr++; 204 } 205 if (endptr != 0) { 206 *endptr = (have_digits) ? (char*)nptr : old_nptr; 207 } 208 if (sgn > 0) { 209 return (s64)(Min((u64)INT64_MAX, res)); 210 } else { 211 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1); 212 } 213} 214 215bool mem_is_zero(const char *beg, uptr size) { 216 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check. 217 const char *end = beg + size; 218 uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr)); 219 uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr)); 220 uptr all = 0; 221 // Prologue. 222 for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++) 223 all |= *mem; 224 // Aligned loop. 225 for (; aligned_beg < aligned_end; aligned_beg++) 226 all |= *aligned_beg; 227 // Epilogue. 228 if ((char*)aligned_end >= beg) 229 for (const char *mem = (char*)aligned_end; mem < end; mem++) 230 all |= *mem; 231 return all == 0; 232} 233 234} // namespace __sanitizer 235