diff options
author | Nick Kralevich <nnk@google.com> | 2013-01-17 15:41:33 -0800 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2013-02-15 10:02:23 -0800 |
commit | 1e8faf0d73d7f4cf8da8a141d4749dc35b166756 (patch) | |
tree | 68af56614d306feac93ea3c553a00ead1f13aa48 | |
parent | 48b524b247a3f4719896adc61ea5bd51a51c33c3 (diff) | |
download | bionic-1e8faf0d73d7f4cf8da8a141d4749dc35b166756.zip bionic-1e8faf0d73d7f4cf8da8a141d4749dc35b166756.tar.gz bionic-1e8faf0d73d7f4cf8da8a141d4749dc35b166756.tar.bz2 |
FORTIFY_SOURCE: optimize
Don't do the fortify_source checks if we can determine, at
compile time, that the provided operation is safe.
This avoids silliness like calling fortify source on things like:
size_t len = strlen("asdf");
printf("%d\n", len);
and allows the compiler to optimize this code to:
printf("%d\n", 4);
Defer to gcc's builtin functions instead of pointing our code
to the libc implementation.
Change-Id: I5e1dcb61946461c4afaaaa983e39f07c7a0df0ae
-rw-r--r-- | libc/include/string.h | 27 | ||||
-rw-r--r-- | tests/string_test.cpp | 21 |
2 files changed, 39 insertions, 9 deletions
diff --git a/libc/include/string.h b/libc/include/string.h index 6643d28..70e0042 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -201,8 +201,6 @@ size_t strlcat(char *dest, const char *src, size_t size) { return __strlcat_chk(dest, src, size, bos); } -__purefunc extern size_t __strlen_real(const char *) - __asm__(__USER_LABEL_PREFIX__ "strlen"); extern size_t __strlen_chk(const char *, size_t); __BIONIC_FORTIFY_INLINE @@ -211,14 +209,17 @@ size_t strlen(const char *s) { // Compiler doesn't know destination size. Don't call __strlen_chk if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { - return __strlen_real(s); + return __builtin_strlen(s); + } + + size_t slen = __builtin_strlen(s); + if (__builtin_constant_p(slen)) { + return slen; } return __strlen_chk(s, bos); } -__purefunc extern char* __strchr_real(const char *, int) - __asm__(__USER_LABEL_PREFIX__ "strchr"); extern char* __strchr_chk(const char *, int, size_t); __BIONIC_FORTIFY_INLINE @@ -227,14 +228,17 @@ char* strchr(const char *s, int c) { // Compiler doesn't know destination size. Don't call __strchr_chk if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { - return __strchr_real(s, c); + 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); } -__purefunc extern char* __strrchr_real(const char *, int) - __asm__(__USER_LABEL_PREFIX__ "strrchr"); extern char* __strrchr_chk(const char *, int, size_t); __BIONIC_FORTIFY_INLINE @@ -243,7 +247,12 @@ char* strrchr(const char *s, int c) { // Compiler doesn't know destination size. Don't call __strrchr_chk if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { - return __strrchr_real(s, c); + 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); diff --git a/tests/string_test.cpp b/tests/string_test.cpp index b200144..01a9c51 100644 --- a/tests/string_test.cpp +++ b/tests/string_test.cpp @@ -314,6 +314,27 @@ TEST(string_DeathTest, strcpy_fortified) { ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGSEGV), ""); free(orig); } + +TEST(string_DeathTest, strlen_fortified) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + char buf[10]; + memcpy(buf, "0123456789", sizeof(buf)); + ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGSEGV), ""); +} + +TEST(string_DeathTest, strchr_fortified) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + char buf[10]; + memcpy(buf, "0123456789", sizeof(buf)); + ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGSEGV), ""); +} + +TEST(string_DeathTest, strrchr_fortified) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + char buf[10]; + memcpy(buf, "0123456789", sizeof(buf)); + ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGSEGV), ""); +} #endif #if __BIONIC__ |