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 11char* __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 33weak_alias(__strchrnul, strchrnul); 34