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