1#include "libc.h" 2#include <limits.h> 3#include <stdint.h> 4#include <string.h> 5 6#define ALIGN (sizeof(size_t) - 1) 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* __stpncpy(char* restrict d, const char* restrict s, size_t n) { 12 // This reads past the end of the string, which is usually OK since 13 // it won't cross a page boundary. But under ASan, even one byte 14 // past the actual end is diagnosed. 15 if (!__has_feature(address_sanitizer) && 16 ((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) { 17 for (; ((uintptr_t)s & ALIGN) && n && (*d = *s); n--, s++, d++) 18 ; 19 if (!n || !*s) 20 goto tail; 21 size_t* wd = (void*)d; 22 const size_t* ws = (const void*)s; 23 for (; n >= sizeof(size_t) && !HASZERO(*ws); n -= sizeof(size_t), ws++, wd++) 24 *wd = *ws; 25 d = (void*)wd; 26 s = (const void*)ws; 27 } 28 for (; n && (*d = *s); n--, s++, d++) 29 ; 30tail: 31 memset(d, 0, n); 32 return d; 33} 34 35weak_alias(__stpncpy, stpncpy); 36