fortify: add diagnostics for str* functions

This CL allows us to diagnose string functions that get an explicit size
passed into them, and string functions that are trivially misused.

Bug: 131861088
Test: mma
Change-Id: I894aec99420a75c6474cfd7d5010f0cf2f10ab21
diff --git a/libc/include/bits/fortify/string.h b/libc/include/bits/fortify/string.h
index 1e12986..0e205d3 100644
--- a/libc/include/bits/fortify/string.h
+++ b/libc/include/bits/fortify/string.h
@@ -94,12 +94,18 @@
 }
 
 __BIONIC_FORTIFY_INLINE
-char* strcat(char* const dst __pass_object_size, const char* src) __overloadable {
+char* strcat(char* const dst __pass_object_size, const char* src)
+        __overloadable
+        __clang_error_if(__bos_unevaluated_le(__bos(dst), __builtin_strlen(src)),
+                         "'strcat' called with string bigger than buffer") {
     return __builtin___strcat_chk(dst, src, __bos(dst));
 }
 
 __BIONIC_FORTIFY_INLINE
-char* strncat(char* const dst __pass_object_size, const char* src, size_t n) __overloadable {
+char* strncat(char* const dst __pass_object_size, const char* src, size_t n)
+        __overloadable
+        __clang_error_if(__bos_unevaluated_lt(__bos(dst), n),
+                         "'strncat' called with size bigger than buffer") {
     return __builtin___strncat_chk(dst, src, n, __bos(dst));
 }
 
@@ -145,7 +151,9 @@
 #if __ANDROID_API__ >= __ANDROID_API_L__
 __BIONIC_FORTIFY_INLINE
 char* stpncpy(char* const dst __pass_object_size, const char* const src __pass_object_size, size_t n)
-        __overloadable {
+        __overloadable
+        __clang_error_if(__bos_unevaluated_lt(__bos(dst), n),
+                         "'stpncpy' called with size bigger than buffer") {
     size_t bos_dst = __bos(dst);
     size_t bos_src = __bos(src);
 
@@ -159,7 +167,9 @@
 
 __BIONIC_FORTIFY_INLINE
 char* strncpy(char* const dst __pass_object_size, const char* const src __pass_object_size, size_t n)
-        __overloadable {
+        __overloadable
+        __clang_error_if(__bos_unevaluated_lt(__bos(dst), n),
+                         "'strncpy' called with size bigger than buffer") {
     size_t bos_dst = __bos(dst);
     size_t bos_src = __bos(src);
 
@@ -174,7 +184,10 @@
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
 __BIONIC_FORTIFY_INLINE
-size_t strlcpy(char* const dst __pass_object_size, const char* src, size_t size) __overloadable {
+size_t strlcpy(char* const dst __pass_object_size, const char* src, size_t size)
+        __overloadable
+        __clang_error_if(__bos_unevaluated_lt(__bos(dst), size),
+                         "'strlcpy' called with size bigger than buffer") {
     size_t bos = __bos(dst);
 
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -185,7 +198,10 @@
 }
 
 __BIONIC_FORTIFY_INLINE
-size_t strlcat(char* const dst __pass_object_size, const char* src, size_t size) __overloadable {
+size_t strlcat(char* const dst __pass_object_size, const char* src, size_t size)
+        __overloadable
+        __clang_error_if(__bos_unevaluated_lt(__bos(dst), size),
+                         "'strlcat' called with size bigger than buffer") {
     size_t bos = __bos(dst);
 
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {