sanitizer_libc.cc revision 71a8273b3729ffaef40d178739f48dc38417d86a
15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//===-- sanitizer_libc.cc -------------------------------------------------===// 25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// 35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// The LLVM Compiler Infrastructure 45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// This file is distributed under the University of Illinois Open Source 65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// License. See LICENSE.TXT for details. 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//===----------------------------------------------------------------------===// 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// This file is shared between AddressSanitizer and ThreadSanitizer 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// run-time libraries. See sanitizer_libc.h for details. 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//===----------------------------------------------------------------------===// 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "sanitizer_common.h" 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "sanitizer_libc.h" 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace __sanitizer { 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Lius64 internal_atoll(const char *nptr) { 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return internal_simple_strtoll(nptr, (char**)0, 10); 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid *internal_memchr(const void *s, int c, uptr n) { 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const char* t = (char*)s; 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (uptr i = 0; i < n; ++i, ++t) 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (*t == c) 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return (void*)t; 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return 0; 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuint internal_memcmp(const void* s1, const void* s2, uptr n) { 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const char* t1 = (char*)s1; 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char* t2 = (char*)s2; 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (uptr i = 0; i < n; ++i, ++t1, ++t2) 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (*t1 != *t2) 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return *t1 < *t2 ? -1 : 1; 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return 0; 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid *internal_memcpy(void *dest, const void *src, uptr n) { 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu char *d = (char*)dest; 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu char *s = (char*)src; 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (uptr i = 0; i < n; ++i) 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu d[i] = s[i]; 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return dest; 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid *internal_memmove(void *dest, const void *src, uptr n) { 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu char *d = (char*)dest; 49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) char *s = (char*)src; 50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sptr i, signed_n = (sptr)n; 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHECK_GE(signed_n, 0); 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (d < s) { 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (i = 0; i < signed_n; ++i) 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu d[i] = s[i]; 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (d > s && signed_n > 0) 575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (i = signed_n - 1; i >= 0 ; --i) { 585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu d[i] = s[i]; 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return dest; 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid *internal_memset(void* s, int c, uptr n) { 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The next line prevents Clang from making a call to memset() instead of the 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // loop below. 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // FIXME: building the runtime with -ffreestanding is a better idea. However 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // there currently are linktime problems due to PR12396. 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu char volatile *t = (char*)s; 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (uptr i = 0; i < n; ++i, ++t) { 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *t = c; 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return s; 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)uptr internal_strcspn(const char *s, const char *reject) { 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uptr i; 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (i = 0; s[i]; i++) { 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (internal_strchr(reject, s[i]) != 0) 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return i; 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return i; 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)char* internal_strdup(const char *s) { 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uptr len = internal_strlen(s); 87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) char *s2 = (char*)InternalAlloc(len + 1); 88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) internal_memcpy(s2, s, len); 89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) s2[len] = 0; 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return s2; 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int internal_strcmp(const char *s1, const char *s2) { 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) while (true) { 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) unsigned c1 = *s1; 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unsigned c2 = *s2; 975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (c1 != c2) return (c1 < c2) ? -1 : 1; 985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (c1 == 0) break; 995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu s1++; 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu s2++; 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return 0; 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int internal_strncmp(const char *s1, const char *s2, uptr n) { 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (uptr i = 0; i < n; i++) { 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) unsigned c1 = *s1; 108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) unsigned c2 = *s2; 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (c1 != c2) return (c1 < c2) ? -1 : 1; 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (c1 == 0) break; 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) s1++; 112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) s2++; 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return 0; 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuchar* internal_strchr(const char *s, int c) { 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu while (true) { 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (*s == (char)c) 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (char*)s; 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (*s == 0) 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 0; 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) s++; 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)char *internal_strrchr(const char *s, int c) { 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char *res = 0; 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (uptr i = 0; s[i]; i++) { 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (s[i] == c) res = s + i; 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (char*)res; 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)uptr internal_strlen(const char *s) { 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uptr i = 0; 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) while (s[i]) i++; 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return i; 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)char *internal_strncat(char *dst, const char *src, uptr n) { 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uptr len = internal_strlen(dst); 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uptr i; 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (i = 0; i < n && src[i]; i++) 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) dst[len + i] = src[i]; 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dst[len + i] = 0; 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return dst; 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)char *internal_strncpy(char *dst, const char *src, uptr n) { 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uptr i; 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (i = 0; i < n && src[i]; i++) 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) dst[i] = src[i]; 154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (; i < n; i++) 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) dst[i] = '\0'; 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return dst; 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)uptr internal_strnlen(const char *s, uptr maxlen) { 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uptr i = 0; 161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) while (i < maxlen && s[i]) i++; 162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return i; 163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)char *internal_strstr(const char *haystack, const char *needle) { 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // This is O(N^2), but we are not using it in hot places. 167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uptr len1 = internal_strlen(haystack); 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uptr len2 = internal_strlen(needle); 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (len1 < len2) return 0; 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (uptr pos = 0; pos <= len1 - len2; pos++) { 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (internal_memcmp(haystack + pos, needle, len2) == 0) 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return (char*)haystack + pos; 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return 0; 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) { 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK_EQ(base, 10); 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (IsSpace(*nptr)) nptr++; 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int sgn = 1; 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) u64 res = 0; 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool have_digits = false; 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) char *old_nptr = (char*)nptr; 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (*nptr == '+') { 185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sgn = 1; 186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) nptr++; 187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } else if (*nptr == '-') { 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sgn = -1; 189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) nptr++; 190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) while (IsDigit(*nptr)) { 192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX; 193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int digit = ((*nptr) - '0'); 194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX; 195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) have_digits = true; 1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu nptr++; 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (endptr != 0) { 199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *endptr = (have_digits) ? (char*)nptr : old_nptr; 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (sgn > 0) { 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (s64)(Min((u64)INT64_MAX, res)); 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1); 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace __sanitizer 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)