1 #include "libc.h"
2 #include <limits.h>
3 #include <stdint.h>
4 #include <string.h>
5 
6 #define ALIGN (sizeof(size_t))
7 #define ONES ((size_t)-1 / UCHAR_MAX)
8 #define HIGHS (ONES * (UCHAR_MAX / 2 + 1))
9 #define HASZERO(x) (((x)-ONES) & ~(x)&HIGHS)
10 
__strchrnul(const char * s,int c)11 char* __strchrnul(const char* s, int c) {
12     c = (unsigned char)c;
13     if (!c)
14         return (char*)s + strlen(s);
15 
16     for (; (uintptr_t)s % ALIGN; s++)
17         if (!*s || *(unsigned char*)s == c)
18             return (char*)s;
19     const size_t* w = (const void*)s;
20 #if !__has_feature(address_sanitizer)
21     // This reads past the end of the string, which is usually OK since it
22     // won't cross a page boundary.  But under ASan, even one byte past the
23     // actual end is diagnosed.
24     size_t k = ONES * c;
25     while (!HASZERO(*w) && !HASZERO(*w ^ k))
26         ++w;
27 #endif
28     for (s = (const void*)w; *s && *(unsigned char*)s != c; s++)
29         ;
30     return (char*)s;
31 }
32 
33 weak_alias(__strchrnul, strchrnul);
34