OSDN Git Service

FORTIFY_SOURCE: optimize
authorNick Kralevich <nnk@google.com>
Thu, 17 Jan 2013 23:41:33 +0000 (15:41 -0800)
committerNick Kralevich <nnk@google.com>
Thu, 17 Jan 2013 23:41:33 +0000 (15:41 -0800)
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

libc/include/string.h
tests/string_test.cpp

index 6643d28..70e0042 100644 (file)
@@ -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);
index 08c73a1..1720058 100644 (file)
@@ -316,6 +316,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__