sanitizer_libc.cc revision 2d1fdb26e458c4ddc04155c1d421bced3ba90cd0
1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- sanitizer_libc.cc -------------------------------------------------===//
2b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany//
3b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany//                     The LLVM Compiler Infrastructure
4b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany//
5b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany// This file is distributed under the University of Illinois Open Source
6b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany// License. See LICENSE.TXT for details.
7b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany//
8b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany//===----------------------------------------------------------------------===//
9b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany//
10b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany// This file is shared between AddressSanitizer and ThreadSanitizer
1116e0075746b21ed866ec3be21ef0d1e46f0efed5Kostya Serebryany// run-time libraries. See sanitizer_libc.h for details.
12b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany//===----------------------------------------------------------------------===//
131f3c2fee395abc36230c445e9ebdba55c4729d35Alexey Samsonov#include "sanitizer_allocator_internal.h"
14f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov#include "sanitizer_common.h"
1516e0075746b21ed866ec3be21ef0d1e46f0efed5Kostya Serebryany#include "sanitizer_libc.h"
16b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany
17b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryanynamespace __sanitizer {
18b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Make the compiler think that something is going on there.
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic inline void break_optimization(void *arg) {
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if _MSC_VER
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // FIXME: make sure this is actually enough.
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm;
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm__ __volatile__("" : : "r" (arg) : "memory");
262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
29c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovs64 internal_atoll(const char *nptr) {
30c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return internal_simple_strtoll(nptr, (char**)0, 10);
31b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany}
32b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany
331f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovvoid *internal_memchr(const void *s, int c, uptr n) {
341f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov  const char* t = (char*)s;
351f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov  for (uptr i = 0; i < n; ++i, ++t)
361f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov    if (*t == c)
371f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov      return (void*)t;
381f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov  return 0;
391f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
401f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
41327c1c17d9557ed8b197f732c8a070fd6ba821b5Alexey Samsonovint internal_memcmp(const void* s1, const void* s2, uptr n) {
42327c1c17d9557ed8b197f732c8a070fd6ba821b5Alexey Samsonov  const char* t1 = (char*)s1;
43327c1c17d9557ed8b197f732c8a070fd6ba821b5Alexey Samsonov  const char* t2 = (char*)s2;
44327c1c17d9557ed8b197f732c8a070fd6ba821b5Alexey Samsonov  for (uptr i = 0; i < n; ++i, ++t1, ++t2)
45327c1c17d9557ed8b197f732c8a070fd6ba821b5Alexey Samsonov    if (*t1 != *t2)
46327c1c17d9557ed8b197f732c8a070fd6ba821b5Alexey Samsonov      return *t1 < *t2 ? -1 : 1;
47327c1c17d9557ed8b197f732c8a070fd6ba821b5Alexey Samsonov  return 0;
48327c1c17d9557ed8b197f732c8a070fd6ba821b5Alexey Samsonov}
49327c1c17d9557ed8b197f732c8a070fd6ba821b5Alexey Samsonov
50f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonovvoid *internal_memcpy(void *dest, const void *src, uptr n) {
51f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  char *d = (char*)dest;
52f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  char *s = (char*)src;
53f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  for (uptr i = 0; i < n; ++i)
54f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov    d[i] = s[i];
55f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  return dest;
56f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov}
57f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov
58f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenkovoid *internal_memmove(void *dest, const void *src, uptr n) {
59f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  char *d = (char*)dest;
60f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  char *s = (char*)src;
6171a8273b3729ffaef40d178739f48dc38417d86aAlexander Potapenko  sptr i, signed_n = (sptr)n;
6271a8273b3729ffaef40d178739f48dc38417d86aAlexander Potapenko  CHECK_GE(signed_n, 0);
63f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  if (d < s) {
6471a8273b3729ffaef40d178739f48dc38417d86aAlexander Potapenko    for (i = 0; i < signed_n; ++i)
65f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko      d[i] = s[i];
66f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  } else {
6771a8273b3729ffaef40d178739f48dc38417d86aAlexander Potapenko    if (d > s && signed_n > 0)
6871a8273b3729ffaef40d178739f48dc38417d86aAlexander Potapenko      for (i = signed_n - 1; i >= 0 ; --i) {
695759d92e99e2b7adcc46a8729f16023208dd8f37Kostya Serebryany        d[i] = s[i];
70f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko      }
71f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  }
72f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko  return dest;
73f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko}
74f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko
752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Semi-fast bzero for 16-aligned data. Still far from peak performance.
762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_bzero_aligned16(void *s, uptr n) {
772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  struct S16 { u64 a, b; } ALIGNED(16);
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK_EQ((reinterpret_cast<uptr>(s) | n) & 15, 0);
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (S16 *p = reinterpret_cast<S16*>(s), *end = p + n / 16; p < end; p++) {
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    p->a = p->b = 0;
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    break_optimization(0);  // Make sure this does not become memset.
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
854fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonovvoid *internal_memset(void* s, int c, uptr n) {
864fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  // The next line prevents Clang from making a call to memset() instead of the
874fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  // loop below.
884fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  // FIXME: building the runtime with -ffreestanding is a better idea. However
894fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  // there currently are linktime problems due to PR12396.
904fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  char volatile *t = (char*)s;
914fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  for (uptr i = 0; i < n; ++i, ++t) {
924fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov    *t = c;
934fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  }
944fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  return s;
954fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov}
964fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov
97251134734f71a7e21a7bd17bc7b5821f07c803b2Alexey Samsonovuptr internal_strcspn(const char *s, const char *reject) {
98251134734f71a7e21a7bd17bc7b5821f07c803b2Alexey Samsonov  uptr i;
99251134734f71a7e21a7bd17bc7b5821f07c803b2Alexey Samsonov  for (i = 0; s[i]; i++) {
100251134734f71a7e21a7bd17bc7b5821f07c803b2Alexey Samsonov    if (internal_strchr(reject, s[i]) != 0)
101251134734f71a7e21a7bd17bc7b5821f07c803b2Alexey Samsonov      return i;
102251134734f71a7e21a7bd17bc7b5821f07c803b2Alexey Samsonov  }
103251134734f71a7e21a7bd17bc7b5821f07c803b2Alexey Samsonov  return i;
104251134734f71a7e21a7bd17bc7b5821f07c803b2Alexey Samsonov}
105251134734f71a7e21a7bd17bc7b5821f07c803b2Alexey Samsonov
106f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonovchar* internal_strdup(const char *s) {
107f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  uptr len = internal_strlen(s);
108f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  char *s2 = (char*)InternalAlloc(len + 1);
109f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  internal_memcpy(s2, s, len);
110f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  s2[len] = 0;
111f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  return s2;
112f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov}
113f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov
114c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonovint internal_strcmp(const char *s1, const char *s2) {
115c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov  while (true) {
116c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov    unsigned c1 = *s1;
117c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov    unsigned c2 = *s2;
118c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov    if (c1 != c2) return (c1 < c2) ? -1 : 1;
119c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov    if (c1 == 0) break;
120c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov    s1++;
121c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov    s2++;
122c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov  }
123c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov  return 0;
124c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov}
125c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov
1268cd0df78c317106be477c5496f481af0563a5208Alexey Samsonovint internal_strncmp(const char *s1, const char *s2, uptr n) {
1278cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov  for (uptr i = 0; i < n; i++) {
1288cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov    unsigned c1 = *s1;
1298cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov    unsigned c2 = *s2;
1308cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov    if (c1 != c2) return (c1 < c2) ? -1 : 1;
1318cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov    if (c1 == 0) break;
1328cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov    s1++;
1338cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov    s2++;
1348cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov  }
1358cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov  return 0;
1368cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov}
1378cd0df78c317106be477c5496f481af0563a5208Alexey Samsonov
13888207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonovchar* internal_strchr(const char *s, int c) {
13988207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov  while (true) {
14088207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov    if (*s == (char)c)
14188207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov      return (char*)s;
14288207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov    if (*s == 0)
14388207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov      return 0;
14488207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov    s++;
14588207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov  }
14688207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov}
14788207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov
14872870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonovchar *internal_strchrnul(const char *s, int c) {
14972870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov  char *res = internal_strchr(s, c);
15072870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov  if (!res)
15172870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov    res = (char*)s + internal_strlen(s);
15272870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov  return res;
15372870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov}
15472870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov
1554fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonovchar *internal_strrchr(const char *s, int c) {
1564fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  const char *res = 0;
1574fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  for (uptr i = 0; s[i]; i++) {
1584fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov    if (s[i] == c) res = s + i;
1594fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  }
1604fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov  return (char*)res;
1614fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov}
1624fac1482179c6bfd84fa129560caa43f341c7336Alexey Samsonov
163230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonovuptr internal_strlen(const char *s) {
164230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  uptr i = 0;
165230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  while (s[i]) i++;
166230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov  return i;
167230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov}
168230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov
169c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovchar *internal_strncat(char *dst, const char *src, uptr n) {
170c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  uptr len = internal_strlen(dst);
171c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  uptr i;
172c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  for (i = 0; i < n && src[i]; i++)
173c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    dst[len + i] = src[i];
174c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  dst[len + i] = 0;
175c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return dst;
176c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov}
177c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
1783836ff2733d40e1182e301ef7de3eff9469777aeAlexey Samsonovchar *internal_strncpy(char *dst, const char *src, uptr n) {
1793836ff2733d40e1182e301ef7de3eff9469777aeAlexey Samsonov  uptr i;
1803836ff2733d40e1182e301ef7de3eff9469777aeAlexey Samsonov  for (i = 0; i < n && src[i]; i++)
1813836ff2733d40e1182e301ef7de3eff9469777aeAlexey Samsonov    dst[i] = src[i];
18298432980845d10da7ea1aa8fc4d330a763d193edWill Dietz  internal_memset(dst + i, '\0', n - i);
1833836ff2733d40e1182e301ef7de3eff9469777aeAlexey Samsonov  return dst;
1843836ff2733d40e1182e301ef7de3eff9469777aeAlexey Samsonov}
1853836ff2733d40e1182e301ef7de3eff9469777aeAlexey Samsonov
186c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovuptr internal_strnlen(const char *s, uptr maxlen) {
187c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  uptr i = 0;
188c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  while (i < maxlen && s[i]) i++;
189c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return i;
190c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov}
191c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
192c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovchar *internal_strstr(const char *haystack, const char *needle) {
193c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  // This is O(N^2), but we are not using it in hot places.
194c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  uptr len1 = internal_strlen(haystack);
195c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  uptr len2 = internal_strlen(needle);
196c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  if (len1 < len2) return 0;
197c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  for (uptr pos = 0; pos <= len1 - len2; pos++) {
198c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    if (internal_memcmp(haystack + pos, needle, len2) == 0)
199c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov      return (char*)haystack + pos;
200c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  }
201c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  return 0;
202c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov}
203c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
204c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovs64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
2056985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany  CHECK_EQ(base, 10);
206c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  while (IsSpace(*nptr)) nptr++;
207c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  int sgn = 1;
208c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  u64 res = 0;
209c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  bool have_digits = false;
210c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  char *old_nptr = (char*)nptr;
211c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  if (*nptr == '+') {
212c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    sgn = 1;
213c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    nptr++;
214c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  } else if (*nptr == '-') {
215c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    sgn = -1;
216c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    nptr++;
217c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  }
218c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  while (IsDigit(*nptr)) {
219c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
220c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    int digit = ((*nptr) - '0');
221c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
222c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    have_digits = true;
223c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    nptr++;
224c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  }
225c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  if (endptr != 0) {
226c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    *endptr = (have_digits) ? (char*)nptr : old_nptr;
227c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  }
228c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  if (sgn > 0) {
229c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    return (s64)(Min((u64)INT64_MAX, res));
230c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  } else {
231c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov    return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
232c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov  }
233c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov}
234c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
235eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryanybool mem_is_zero(const char *beg, uptr size) {
2368ceeec4f343768b199e7c891865029360b7225dcDmitry Vyukov  CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40));  // Sanity check.
237eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  const char *end = beg + size;
238eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
239eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
240eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  uptr all = 0;
241eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  // Prologue.
242eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
243eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany    all |= *mem;
244eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  // Aligned loop.
245eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  for (; aligned_beg < aligned_end; aligned_beg++)
246eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany    all |= *aligned_beg;
247eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  // Epilogue.
248eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  if ((char*)aligned_end >= beg)
249eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany    for (const char *mem = (char*)aligned_end; mem < end; mem++)
250eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany      all |= *mem;
251eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  return all == 0;
252eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany}
253eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany
254b3cedf98a3c8545da2234c2d35cb5d687984035fKostya Serebryany}  // namespace __sanitizer
255