13cab2bb3Spatrick //===-- sanitizer_libc.cpp ------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is shared between AddressSanitizer and ThreadSanitizer
103cab2bb3Spatrick // run-time libraries. See sanitizer_libc.h for details.
113cab2bb3Spatrick //===----------------------------------------------------------------------===//
123cab2bb3Spatrick 
133cab2bb3Spatrick #include "sanitizer_allocator_internal.h"
143cab2bb3Spatrick #include "sanitizer_common.h"
153cab2bb3Spatrick #include "sanitizer_libc.h"
163cab2bb3Spatrick 
173cab2bb3Spatrick namespace __sanitizer {
183cab2bb3Spatrick 
internal_atoll(const char * nptr)193cab2bb3Spatrick s64 internal_atoll(const char *nptr) {
203cab2bb3Spatrick   return internal_simple_strtoll(nptr, nullptr, 10);
213cab2bb3Spatrick }
223cab2bb3Spatrick 
internal_memchr(const void * s,int c,uptr n)233cab2bb3Spatrick void *internal_memchr(const void *s, int c, uptr n) {
243cab2bb3Spatrick   const char *t = (const char *)s;
253cab2bb3Spatrick   for (uptr i = 0; i < n; ++i, ++t)
263cab2bb3Spatrick     if (*t == c)
273cab2bb3Spatrick       return reinterpret_cast<void *>(const_cast<char *>(t));
283cab2bb3Spatrick   return nullptr;
293cab2bb3Spatrick }
303cab2bb3Spatrick 
internal_memrchr(const void * s,int c,uptr n)313cab2bb3Spatrick void *internal_memrchr(const void *s, int c, uptr n) {
323cab2bb3Spatrick   const char *t = (const char *)s;
333cab2bb3Spatrick   void *res = nullptr;
343cab2bb3Spatrick   for (uptr i = 0; i < n; ++i, ++t) {
353cab2bb3Spatrick     if (*t == c) res = reinterpret_cast<void *>(const_cast<char *>(t));
363cab2bb3Spatrick   }
373cab2bb3Spatrick   return res;
383cab2bb3Spatrick }
393cab2bb3Spatrick 
internal_memcmp(const void * s1,const void * s2,uptr n)403cab2bb3Spatrick int internal_memcmp(const void* s1, const void* s2, uptr n) {
413cab2bb3Spatrick   const char *t1 = (const char *)s1;
423cab2bb3Spatrick   const char *t2 = (const char *)s2;
433cab2bb3Spatrick   for (uptr i = 0; i < n; ++i, ++t1, ++t2)
443cab2bb3Spatrick     if (*t1 != *t2)
453cab2bb3Spatrick       return *t1 < *t2 ? -1 : 1;
463cab2bb3Spatrick   return 0;
473cab2bb3Spatrick }
483cab2bb3Spatrick 
internal_memcpy(void * dest,const void * src,uptr n)493cab2bb3Spatrick void *internal_memcpy(void *dest, const void *src, uptr n) {
503cab2bb3Spatrick   char *d = (char*)dest;
513cab2bb3Spatrick   const char *s = (const char *)src;
523cab2bb3Spatrick   for (uptr i = 0; i < n; ++i)
533cab2bb3Spatrick     d[i] = s[i];
543cab2bb3Spatrick   return dest;
553cab2bb3Spatrick }
563cab2bb3Spatrick 
internal_memmove(void * dest,const void * src,uptr n)573cab2bb3Spatrick void *internal_memmove(void *dest, const void *src, uptr n) {
583cab2bb3Spatrick   char *d = (char*)dest;
593cab2bb3Spatrick   const char *s = (const char *)src;
603cab2bb3Spatrick   sptr i, signed_n = (sptr)n;
613cab2bb3Spatrick   CHECK_GE(signed_n, 0);
623cab2bb3Spatrick   if (d < s) {
633cab2bb3Spatrick     for (i = 0; i < signed_n; ++i)
643cab2bb3Spatrick       d[i] = s[i];
653cab2bb3Spatrick   } else {
663cab2bb3Spatrick     if (d > s && signed_n > 0) {
673cab2bb3Spatrick       for (i = signed_n - 1; i >= 0; --i) {
683cab2bb3Spatrick         d[i] = s[i];
693cab2bb3Spatrick       }
703cab2bb3Spatrick     }
713cab2bb3Spatrick   }
723cab2bb3Spatrick   return dest;
733cab2bb3Spatrick }
743cab2bb3Spatrick 
internal_memset(void * s,int c,uptr n)753cab2bb3Spatrick void *internal_memset(void* s, int c, uptr n) {
763cab2bb3Spatrick   // Optimize for the most performance-critical case:
773cab2bb3Spatrick   if ((reinterpret_cast<uptr>(s) % 16) == 0 && (n % 16) == 0) {
783cab2bb3Spatrick     u64 *p = reinterpret_cast<u64*>(s);
793cab2bb3Spatrick     u64 *e = p + n / 8;
803cab2bb3Spatrick     u64 v = c;
813cab2bb3Spatrick     v |= v << 8;
823cab2bb3Spatrick     v |= v << 16;
833cab2bb3Spatrick     v |= v << 32;
843cab2bb3Spatrick     for (; p < e; p += 2)
853cab2bb3Spatrick       p[0] = p[1] = v;
863cab2bb3Spatrick     return s;
873cab2bb3Spatrick   }
883cab2bb3Spatrick   // The next line prevents Clang from making a call to memset() instead of the
893cab2bb3Spatrick   // loop below.
903cab2bb3Spatrick   // FIXME: building the runtime with -ffreestanding is a better idea. However
913cab2bb3Spatrick   // there currently are linktime problems due to PR12396.
923cab2bb3Spatrick   char volatile *t = (char*)s;
933cab2bb3Spatrick   for (uptr i = 0; i < n; ++i, ++t) {
943cab2bb3Spatrick     *t = c;
953cab2bb3Spatrick   }
963cab2bb3Spatrick   return s;
973cab2bb3Spatrick }
983cab2bb3Spatrick 
internal_strcspn(const char * s,const char * reject)993cab2bb3Spatrick uptr internal_strcspn(const char *s, const char *reject) {
1003cab2bb3Spatrick   uptr i;
1013cab2bb3Spatrick   for (i = 0; s[i]; i++) {
1023cab2bb3Spatrick     if (internal_strchr(reject, s[i]))
1033cab2bb3Spatrick       return i;
1043cab2bb3Spatrick   }
1053cab2bb3Spatrick   return i;
1063cab2bb3Spatrick }
1073cab2bb3Spatrick 
internal_strdup(const char * s)1083cab2bb3Spatrick char* internal_strdup(const char *s) {
1093cab2bb3Spatrick   uptr len = internal_strlen(s);
1103cab2bb3Spatrick   char *s2 = (char*)InternalAlloc(len + 1);
1113cab2bb3Spatrick   internal_memcpy(s2, s, len);
1123cab2bb3Spatrick   s2[len] = 0;
1133cab2bb3Spatrick   return s2;
1143cab2bb3Spatrick }
1153cab2bb3Spatrick 
internal_strcmp(const char * s1,const char * s2)1163cab2bb3Spatrick int internal_strcmp(const char *s1, const char *s2) {
1173cab2bb3Spatrick   while (true) {
1183cab2bb3Spatrick     unsigned c1 = *s1;
1193cab2bb3Spatrick     unsigned c2 = *s2;
1203cab2bb3Spatrick     if (c1 != c2) return (c1 < c2) ? -1 : 1;
1213cab2bb3Spatrick     if (c1 == 0) break;
1223cab2bb3Spatrick     s1++;
1233cab2bb3Spatrick     s2++;
1243cab2bb3Spatrick   }
1253cab2bb3Spatrick   return 0;
1263cab2bb3Spatrick }
1273cab2bb3Spatrick 
internal_strncmp(const char * s1,const char * s2,uptr n)1283cab2bb3Spatrick int internal_strncmp(const char *s1, const char *s2, uptr n) {
1293cab2bb3Spatrick   for (uptr i = 0; i < n; i++) {
1303cab2bb3Spatrick     unsigned c1 = *s1;
1313cab2bb3Spatrick     unsigned c2 = *s2;
1323cab2bb3Spatrick     if (c1 != c2) return (c1 < c2) ? -1 : 1;
1333cab2bb3Spatrick     if (c1 == 0) break;
1343cab2bb3Spatrick     s1++;
1353cab2bb3Spatrick     s2++;
1363cab2bb3Spatrick   }
1373cab2bb3Spatrick   return 0;
1383cab2bb3Spatrick }
1393cab2bb3Spatrick 
internal_strchr(const char * s,int c)1403cab2bb3Spatrick char* internal_strchr(const char *s, int c) {
1413cab2bb3Spatrick   while (true) {
1423cab2bb3Spatrick     if (*s == (char)c)
1433cab2bb3Spatrick       return const_cast<char *>(s);
1443cab2bb3Spatrick     if (*s == 0)
1453cab2bb3Spatrick       return nullptr;
1463cab2bb3Spatrick     s++;
1473cab2bb3Spatrick   }
1483cab2bb3Spatrick }
1493cab2bb3Spatrick 
internal_strchrnul(const char * s,int c)1503cab2bb3Spatrick char *internal_strchrnul(const char *s, int c) {
1513cab2bb3Spatrick   char *res = internal_strchr(s, c);
1523cab2bb3Spatrick   if (!res)
1533cab2bb3Spatrick     res = const_cast<char *>(s) + internal_strlen(s);
1543cab2bb3Spatrick   return res;
1553cab2bb3Spatrick }
1563cab2bb3Spatrick 
internal_strrchr(const char * s,int c)1573cab2bb3Spatrick char *internal_strrchr(const char *s, int c) {
1583cab2bb3Spatrick   const char *res = nullptr;
1593cab2bb3Spatrick   for (uptr i = 0; s[i]; i++) {
1603cab2bb3Spatrick     if (s[i] == c) res = s + i;
1613cab2bb3Spatrick   }
1623cab2bb3Spatrick   return const_cast<char *>(res);
1633cab2bb3Spatrick }
1643cab2bb3Spatrick 
internal_strlen(const char * s)1653cab2bb3Spatrick uptr internal_strlen(const char *s) {
1663cab2bb3Spatrick   uptr i = 0;
1673cab2bb3Spatrick   while (s[i]) i++;
1683cab2bb3Spatrick   return i;
1693cab2bb3Spatrick }
1703cab2bb3Spatrick 
internal_strlcat(char * dst,const char * src,uptr maxlen)1713cab2bb3Spatrick uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {
1723cab2bb3Spatrick   const uptr srclen = internal_strlen(src);
1733cab2bb3Spatrick   const uptr dstlen = internal_strnlen(dst, maxlen);
1743cab2bb3Spatrick   if (dstlen == maxlen) return maxlen + srclen;
1753cab2bb3Spatrick   if (srclen < maxlen - dstlen) {
1763cab2bb3Spatrick     internal_memmove(dst + dstlen, src, srclen + 1);
1773cab2bb3Spatrick   } else {
1783cab2bb3Spatrick     internal_memmove(dst + dstlen, src, maxlen - dstlen - 1);
1793cab2bb3Spatrick     dst[maxlen - 1] = '\0';
1803cab2bb3Spatrick   }
1813cab2bb3Spatrick   return dstlen + srclen;
1823cab2bb3Spatrick }
1833cab2bb3Spatrick 
internal_strncat(char * dst,const char * src,uptr n)1843cab2bb3Spatrick char *internal_strncat(char *dst, const char *src, uptr n) {
1853cab2bb3Spatrick   uptr len = internal_strlen(dst);
1863cab2bb3Spatrick   uptr i;
1873cab2bb3Spatrick   for (i = 0; i < n && src[i]; i++)
1883cab2bb3Spatrick     dst[len + i] = src[i];
1893cab2bb3Spatrick   dst[len + i] = 0;
1903cab2bb3Spatrick   return dst;
1913cab2bb3Spatrick }
1923cab2bb3Spatrick 
internal_strlcpy(char * dst,const char * src,uptr maxlen)1933cab2bb3Spatrick uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {
1943cab2bb3Spatrick   const uptr srclen = internal_strlen(src);
1953cab2bb3Spatrick   if (srclen < maxlen) {
1963cab2bb3Spatrick     internal_memmove(dst, src, srclen + 1);
1973cab2bb3Spatrick   } else if (maxlen != 0) {
1983cab2bb3Spatrick     internal_memmove(dst, src, maxlen - 1);
1993cab2bb3Spatrick     dst[maxlen - 1] = '\0';
2003cab2bb3Spatrick   }
2013cab2bb3Spatrick   return srclen;
2023cab2bb3Spatrick }
2033cab2bb3Spatrick 
internal_strncpy(char * dst,const char * src,uptr n)2043cab2bb3Spatrick char *internal_strncpy(char *dst, const char *src, uptr n) {
2053cab2bb3Spatrick   uptr i;
2063cab2bb3Spatrick   for (i = 0; i < n && src[i]; i++)
2073cab2bb3Spatrick     dst[i] = src[i];
2083cab2bb3Spatrick   internal_memset(dst + i, '\0', n - i);
2093cab2bb3Spatrick   return dst;
2103cab2bb3Spatrick }
2113cab2bb3Spatrick 
internal_strnlen(const char * s,uptr maxlen)2123cab2bb3Spatrick uptr internal_strnlen(const char *s, uptr maxlen) {
2133cab2bb3Spatrick   uptr i = 0;
2143cab2bb3Spatrick   while (i < maxlen && s[i]) i++;
2153cab2bb3Spatrick   return i;
2163cab2bb3Spatrick }
2173cab2bb3Spatrick 
internal_strstr(const char * haystack,const char * needle)2183cab2bb3Spatrick char *internal_strstr(const char *haystack, const char *needle) {
2193cab2bb3Spatrick   // This is O(N^2), but we are not using it in hot places.
2203cab2bb3Spatrick   uptr len1 = internal_strlen(haystack);
2213cab2bb3Spatrick   uptr len2 = internal_strlen(needle);
2223cab2bb3Spatrick   if (len1 < len2) return nullptr;
2233cab2bb3Spatrick   for (uptr pos = 0; pos <= len1 - len2; pos++) {
2243cab2bb3Spatrick     if (internal_memcmp(haystack + pos, needle, len2) == 0)
2253cab2bb3Spatrick       return const_cast<char *>(haystack) + pos;
2263cab2bb3Spatrick   }
2273cab2bb3Spatrick   return nullptr;
2283cab2bb3Spatrick }
2293cab2bb3Spatrick 
internal_simple_strtoll(const char * nptr,const char ** endptr,int base)2303cab2bb3Spatrick s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) {
2313cab2bb3Spatrick   CHECK_EQ(base, 10);
2323cab2bb3Spatrick   while (IsSpace(*nptr)) nptr++;
2333cab2bb3Spatrick   int sgn = 1;
2343cab2bb3Spatrick   u64 res = 0;
2353cab2bb3Spatrick   bool have_digits = false;
2363cab2bb3Spatrick   char *old_nptr = const_cast<char *>(nptr);
2373cab2bb3Spatrick   if (*nptr == '+') {
2383cab2bb3Spatrick     sgn = 1;
2393cab2bb3Spatrick     nptr++;
2403cab2bb3Spatrick   } else if (*nptr == '-') {
2413cab2bb3Spatrick     sgn = -1;
2423cab2bb3Spatrick     nptr++;
2433cab2bb3Spatrick   }
2443cab2bb3Spatrick   while (IsDigit(*nptr)) {
2453cab2bb3Spatrick     res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
2463cab2bb3Spatrick     int digit = ((*nptr) - '0');
2473cab2bb3Spatrick     res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
2483cab2bb3Spatrick     have_digits = true;
2493cab2bb3Spatrick     nptr++;
2503cab2bb3Spatrick   }
2513cab2bb3Spatrick   if (endptr) {
2523cab2bb3Spatrick     *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr;
2533cab2bb3Spatrick   }
2543cab2bb3Spatrick   if (sgn > 0) {
2553cab2bb3Spatrick     return (s64)(Min((u64)INT64_MAX, res));
2563cab2bb3Spatrick   } else {
2573cab2bb3Spatrick     return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
2583cab2bb3Spatrick   }
2593cab2bb3Spatrick }
2603cab2bb3Spatrick 
internal_wcslen(const wchar_t * s)261*810390e3Srobert uptr internal_wcslen(const wchar_t *s) {
262*810390e3Srobert   uptr i = 0;
263*810390e3Srobert   while (s[i]) i++;
264*810390e3Srobert   return i;
265*810390e3Srobert }
266*810390e3Srobert 
internal_wcsnlen(const wchar_t * s,uptr maxlen)267*810390e3Srobert uptr internal_wcsnlen(const wchar_t *s, uptr maxlen) {
268*810390e3Srobert   uptr i = 0;
269*810390e3Srobert   while (i < maxlen && s[i]) i++;
270*810390e3Srobert   return i;
271*810390e3Srobert }
272*810390e3Srobert 
mem_is_zero(const char * beg,uptr size)2733cab2bb3Spatrick bool mem_is_zero(const char *beg, uptr size) {
2743cab2bb3Spatrick   CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
2753cab2bb3Spatrick   const char *end = beg + size;
2763cab2bb3Spatrick   uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
2773cab2bb3Spatrick   uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
2783cab2bb3Spatrick   uptr all = 0;
2793cab2bb3Spatrick   // Prologue.
2803cab2bb3Spatrick   for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
2813cab2bb3Spatrick     all |= *mem;
2823cab2bb3Spatrick   // Aligned loop.
2833cab2bb3Spatrick   for (; aligned_beg < aligned_end; aligned_beg++)
2843cab2bb3Spatrick     all |= *aligned_beg;
2853cab2bb3Spatrick   // Epilogue.
2863cab2bb3Spatrick   if ((char *)aligned_end >= beg) {
2873cab2bb3Spatrick     for (const char *mem = (char *)aligned_end; mem < end; mem++) all |= *mem;
2883cab2bb3Spatrick   }
2893cab2bb3Spatrick   return all == 0;
2903cab2bb3Spatrick }
2913cab2bb3Spatrick 
2923cab2bb3Spatrick } // namespace __sanitizer
293