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