diff options
Diffstat (limited to 'libc/include/bits/fortify/string.h')
-rw-r--r-- | libc/include/bits/fortify/string.h | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/libc/include/bits/fortify/string.h b/libc/include/bits/fortify/string.h index 14bb1335b..f994e3e40 100644 --- a/libc/include/bits/fortify/string.h +++ b/libc/include/bits/fortify/string.h @@ -40,6 +40,8 @@ size_t __strlcat_chk(char*, const char*, size_t, size_t) __INTRODUCED_IN(17); #if defined(__BIONIC_FORTIFY) extern void* __memrchr_real(const void*, int, size_t) __RENAME(memrchr); +// These can share their implementation between gcc and clang with minimal +// trickery... #if __ANDROID_API__ >= __ANDROID_API_J_MR1__ __BIONIC_FORTIFY_INLINE void* memcpy(void* const dst __pass_object_size0, const void* src, size_t copy_amount) @@ -100,6 +102,9 @@ void* memset(void* const s __pass_object_size0, int c, size_t n) } #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */ + +#if defined(__clang__) + #if __ANDROID_API__ >= __ANDROID_API_M__ __BIONIC_FORTIFY_INLINE void* memchr(const void* const s __pass_object_size, int c, size_t n) __overloadable { @@ -226,6 +231,192 @@ char* strrchr(const char* const s __pass_object_size, int c) __overloadable { } #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR2__ */ +#else // defined(__clang__) +extern char* __strncpy_real(char*, const char*, size_t) __RENAME(strncpy); +extern size_t __strlcpy_real(char*, const char*, size_t) + __RENAME(strlcpy); +extern size_t __strlcat_real(char*, const char*, size_t) + __RENAME(strlcat); + +__errordecl(__memchr_buf_size_error, "memchr called with size bigger than buffer"); +__errordecl(__memrchr_buf_size_error, "memrchr called with size bigger than buffer"); + +#if __ANDROID_API__ >= __ANDROID_API_M__ +__BIONIC_FORTIFY_INLINE +void* memchr(const void* s __pass_object_size, int c, size_t n) { + size_t bos = __bos(s); + + if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __builtin_memchr(s, c, n); + } + + if (__builtin_constant_p(n) && (n > bos)) { + __memchr_buf_size_error(); + } + + if (__builtin_constant_p(n) && (n <= bos)) { + return __builtin_memchr(s, c, n); + } + + return __memchr_chk(s, c, n, bos); +} + +__BIONIC_FORTIFY_INLINE +void* __memrchr_fortify(const void* s, int c, size_t n) { + size_t bos = __bos(s); + + if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __memrchr_real(s, c, n); + } + + if (__builtin_constant_p(n) && (n > bos)) { + __memrchr_buf_size_error(); + } + + if (__builtin_constant_p(n) && (n <= bos)) { + return __memrchr_real(s, c, n); + } + + return __memrchr_chk(s, c, n, bos); +} +#endif /* __ANDROID_API__ >= __ANDROID_API_M__ */ + +#if __ANDROID_API__ >= __ANDROID_API_L__ +__BIONIC_FORTIFY_INLINE +char* stpncpy(char* dst, const char* src, size_t n) { + size_t bos_dst = __bos(dst); + size_t bos_src = __bos(src); + + if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __builtin___stpncpy_chk(dst, src, n, bos_dst); + } + + if (__builtin_constant_p(n) && (n <= bos_src)) { + return __builtin___stpncpy_chk(dst, src, n, bos_dst); + } + + size_t slen = __builtin_strlen(src); + if (__builtin_constant_p(slen)) { + return __builtin___stpncpy_chk(dst, src, n, bos_dst); + } + + return __stpncpy_chk2(dst, src, n, bos_dst, bos_src); +} + +__BIONIC_FORTIFY_INLINE +char* strncpy(char* dst, const char* src, size_t n) { + size_t bos_dst = __bos(dst); + size_t bos_src = __bos(src); + + if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __strncpy_real(dst, src, n); + } + + if (__builtin_constant_p(n) && (n <= bos_src)) { + return __builtin___strncpy_chk(dst, src, n, bos_dst); + } + + size_t slen = __builtin_strlen(src); + if (__builtin_constant_p(slen)) { + return __builtin___strncpy_chk(dst, src, n, bos_dst); + } + + return __strncpy_chk2(dst, src, n, bos_dst, bos_src); +} +#endif /* __ANDROID_API__ >= __ANDROID_API_L__ */ + +#if __ANDROID_API__ >= __ANDROID_API_J_MR1__ +__BIONIC_FORTIFY_INLINE +size_t strlcpy(char* dst __pass_object_size, const char* src, size_t size) { + size_t bos = __bos(dst); + + // Compiler doesn't know destination size. Don't call __strlcpy_chk + if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __strlcpy_real(dst, src, size); + } + + // Compiler can prove, at compile time, that the passed in size + // is always <= the actual object size. Don't call __strlcpy_chk + if (__builtin_constant_p(size) && (size <= bos)) { + return __strlcpy_real(dst, src, size); + } + + return __strlcpy_chk(dst, src, size, bos); +} + +__BIONIC_FORTIFY_INLINE +size_t strlcat(char* dst, const char* src, size_t size) { + size_t bos = __bos(dst); + + // Compiler doesn't know destination size. Don't call __strlcat_chk + if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __strlcat_real(dst, src, size); + } + + // Compiler can prove, at compile time, that the passed in size + // is always <= the actual object size. Don't call __strlcat_chk + if (__builtin_constant_p(size) && (size <= bos)) { + return __strlcat_real(dst, src, size); + } + + return __strlcat_chk(dst, src, size, bos); +} + +__BIONIC_FORTIFY_INLINE +size_t strlen(const char* s) __overloadable { + size_t bos = __bos(s); + + // Compiler doesn't know destination size. Don't call __strlen_chk + if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __builtin_strlen(s); + } + + size_t slen = __builtin_strlen(s); + if (__builtin_constant_p(slen)) { + return slen; + } + + return __strlen_chk(s, bos); +} +#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */ + +#if __ANDROID_API__ >= __ANDROID_API_J_MR2__ +__BIONIC_FORTIFY_INLINE +char* strchr(const char* s, int c) { + size_t bos = __bos(s); + + // Compiler doesn't know destination size. Don't call __strchr_chk + if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __builtin_strchr(s, c); + } + + size_t slen = __builtin_strlen(s); + if (__builtin_constant_p(slen) && (slen < bos)) { + return __builtin_strchr(s, c); + } + + return __strchr_chk(s, c, bos); +} + +__BIONIC_FORTIFY_INLINE +char* strrchr(const char* s, int c) { + size_t bos = __bos(s); + + // Compiler doesn't know destination size. Don't call __strrchr_chk + if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __builtin_strrchr(s, c); + } + + size_t slen = __builtin_strlen(s); + if (__builtin_constant_p(slen) && (slen < bos)) { + return __builtin_strrchr(s, c); + } + + return __strrchr_chk(s, c, bos); +} +#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR2__ */ +#endif /* defined(__clang__) */ + #if __ANDROID_API__ >= __ANDROID_API_M__ #if defined(__cplusplus) extern "C++" { |