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 16 namespace __sanitizer { 17 18 s64 internal_atoll(const char *nptr) { 19 return internal_simple_strtoll(nptr, (char**)0, 10); 20 } 21 22 void *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 30 int 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 39 void *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 47 void *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 64 void *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 76 uptr 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 85 char* 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 93 int 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 105 int 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 117 char* 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 127 char *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 135 uptr internal_strlen(const char *s) { 136 uptr i = 0; 137 while (s[i]) i++; 138 return i; 139 } 140 141 char *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 150 char *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 159 uptr internal_strnlen(const char *s, uptr maxlen) { 160 uptr i = 0; 161 while (i < maxlen && s[i]) i++; 162 return i; 163 } 164 165 char *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 177 s64 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 208 bool mem_is_zero(const char *beg, uptr size) { 209 CHECK_LE(size, 1ULL << 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