libc: add limited FORTIFY_SOURCE support for clang
In 829c089f83
, we disabled all
FORTIFY_SOURCE support when compiling under clang. At the time,
we didn't have proper test cases, and couldn't easily create targeted
clang tests.
This change re-enables FORTIFY_SOURCE support under clang for a
limited set of functions, where we have explicit unittests available.
The functions are:
* memcpy
* memmove
* strcpy
* strncpy
* strcat
* strncat
* memset
* strlen (with modifications)
* strchr (with modifications)
* strrchr (with modifications)
It may be possible, in the future, to enable other functions. However,
I need to write unittests first.
For strlen, strchr, and strrchr, clang unconditionally calls the
fortified version of the relevant function. If it doesn't know the
size of the buffer it's dealing with, it passes in ((size_t) -1),
which is the largest possible size_t.
I added two new clang specific unittest files, primarily copied
from fortify?_test.cpp.
I've also rebuild the entire system with these changes, and didn't
observe any obvious problems.
Change-Id: If12a15089bb0ffe93824b485290d05b14355fcaa
This commit is contained in:
@@ -91,7 +91,7 @@ __errordecl(__memcpy_dest_size_error, "memcpy called with size bigger than desti
|
||||
__errordecl(__memcpy_src_size_error, "memcpy called with size bigger than source");
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
void *memcpy (void* __restrict dest, const void* __restrict src, size_t copy_amount) {
|
||||
void* memcpy(void* __restrict dest, const void* __restrict src, size_t copy_amount) {
|
||||
char *d = (char *) dest;
|
||||
const char *s = (const char *) src;
|
||||
size_t s_len = __builtin_object_size(s, 0);
|
||||
@@ -109,19 +109,19 @@ void *memcpy (void* __restrict dest, const void* __restrict src, size_t copy_amo
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
void *memmove (void *dest, const void *src, size_t len) {
|
||||
void* memmove(void *dest, const void *src, size_t len) {
|
||||
return __builtin___memmove_chk(dest, src, len, __builtin_object_size (dest, 0));
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
char *strcpy(char* __restrict dest, const char* __restrict src) {
|
||||
char* strcpy(char* __restrict dest, const char* __restrict src) {
|
||||
return __builtin___strcpy_chk(dest, src, __bos(dest));
|
||||
}
|
||||
|
||||
__errordecl(__strncpy_error, "strncpy called with size bigger than buffer");
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
char *strncpy(char* __restrict dest, const char* __restrict src, size_t n) {
|
||||
char* strncpy(char* __restrict dest, const char* __restrict src, size_t n) {
|
||||
size_t bos = __bos(dest);
|
||||
if (__builtin_constant_p(n) && (n > bos)) {
|
||||
__strncpy_error();
|
||||
@@ -130,7 +130,7 @@ char *strncpy(char* __restrict dest, const char* __restrict src, size_t n) {
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
char *strcat(char* __restrict dest, const char* __restrict src) {
|
||||
char* strcat(char* __restrict dest, const char* __restrict src) {
|
||||
return __builtin___strcat_chk(dest, src, __bos(dest));
|
||||
}
|
||||
|
||||
@@ -140,10 +140,11 @@ char *strncat(char* __restrict dest, const char* __restrict src, size_t n) {
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
void *memset (void *s, int c, size_t n) {
|
||||
void* memset(void *s, int c, size_t n) {
|
||||
return __builtin___memset_chk(s, c, n, __builtin_object_size (s, 0));
|
||||
}
|
||||
|
||||
#if !defined(__clang__)
|
||||
extern size_t __strlcpy_real(char* __restrict, const char* __restrict, size_t)
|
||||
__asm__(__USER_LABEL_PREFIX__ "strlcpy");
|
||||
__errordecl(__strlcpy_error, "strlcpy called with size bigger than buffer");
|
||||
@@ -172,7 +173,9 @@ size_t strlcpy(char* __restrict dest, const char* __restrict src, size_t size) {
|
||||
|
||||
return __strlcpy_chk(dest, src, size, bos);
|
||||
}
|
||||
#endif /* !defined(__clang__) */
|
||||
|
||||
#if !defined(__clang__)
|
||||
extern size_t __strlcat_real(char* __restrict, const char* __restrict, size_t)
|
||||
__asm__(__USER_LABEL_PREFIX__ "strlcat");
|
||||
__errordecl(__strlcat_error, "strlcat called with size bigger than buffer");
|
||||
@@ -202,11 +205,13 @@ size_t strlcat(char* __restrict dest, const char* __restrict src, size_t size) {
|
||||
|
||||
return __strlcat_chk(dest, src, size, bos);
|
||||
}
|
||||
#endif /* !defined(__clang__) */
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
size_t strlen(const char *s) {
|
||||
size_t bos = __bos(s);
|
||||
|
||||
#if !defined(__clang__)
|
||||
// Compiler doesn't know destination size. Don't call __strlen_chk
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
return __builtin_strlen(s);
|
||||
@@ -216,6 +221,7 @@ size_t strlen(const char *s) {
|
||||
if (__builtin_constant_p(slen)) {
|
||||
return slen;
|
||||
}
|
||||
#endif /* !defined(__clang__) */
|
||||
|
||||
return __strlen_chk(s, bos);
|
||||
}
|
||||
@@ -226,6 +232,7 @@ __BIONIC_FORTIFY_INLINE
|
||||
char* strchr(const char *s, int c) {
|
||||
size_t bos = __bos(s);
|
||||
|
||||
#if !defined(__clang__)
|
||||
// Compiler doesn't know destination size. Don't call __strchr_chk
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
return __builtin_strchr(s, c);
|
||||
@@ -235,6 +242,7 @@ char* strchr(const char *s, int c) {
|
||||
if (__builtin_constant_p(slen) && (slen < bos)) {
|
||||
return __builtin_strchr(s, c);
|
||||
}
|
||||
#endif /* !defined(__clang__) */
|
||||
|
||||
return __strchr_chk(s, c, bos);
|
||||
}
|
||||
@@ -245,6 +253,7 @@ __BIONIC_FORTIFY_INLINE
|
||||
char* strrchr(const char *s, int c) {
|
||||
size_t bos = __bos(s);
|
||||
|
||||
#if !defined(__clang__)
|
||||
// Compiler doesn't know destination size. Don't call __strrchr_chk
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
return __builtin_strrchr(s, c);
|
||||
@@ -254,6 +263,7 @@ char* strrchr(const char *s, int c) {
|
||||
if (__builtin_constant_p(slen) && (slen < bos)) {
|
||||
return __builtin_strrchr(s, c);
|
||||
}
|
||||
#endif /* !defined(__clang__) */
|
||||
|
||||
return __strrchr_chk(s, c, bos);
|
||||
}
|
||||
|
Reference in New Issue
Block a user