summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPierre Gousseau <pierregousseau14@gmail.com>2017-06-01 09:37:22 +0000
committerPierre Gousseau <pierregousseau14@gmail.com>2017-06-01 09:37:22 +0000
commit27c8277872fdff5466439844251c9c52ec37dadb (patch)
tree54db5314d40ec06270abfc355f39fd2696e4985f /lib
parent9b2c60be6745a807592f96e7238c331c2308f615 (diff)
[asan] Add strndup/__strndup interceptors.
Recommit of r302781 with Vitaly Buka's fix for non zero terminated strings. Differential Revision: https://reviews.llvm.org/D31457 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@304399 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/asan/asan_flags.cc4
-rw-r--r--lib/asan/tests/asan_str_test.cc27
-rw-r--r--lib/msan/msan_interceptors.cc36
-rw-r--r--lib/msan/tests/msan_test.cc13
-rw-r--r--lib/sanitizer_common/sanitizer_common_interceptors.inc42
-rw-r--r--lib/sanitizer_common/sanitizer_flags.inc3
-rw-r--r--lib/sanitizer_common/sanitizer_platform_interceptors.h14
-rw-r--r--lib/sanitizer_common/tests/sanitizer_test_utils.h6
8 files changed, 114 insertions, 31 deletions
diff --git a/lib/asan/asan_flags.cc b/lib/asan/asan_flags.cc
index c8ae3faed..6be0d6e94 100644
--- a/lib/asan/asan_flags.cc
+++ b/lib/asan/asan_flags.cc
@@ -194,6 +194,10 @@ void InitializeFlags() {
Report("WARNING: strchr* interceptors are enabled even though "
"replace_str=0. Use intercept_strchr=0 to disable them.");
}
+ if (!f->replace_str && common_flags()->intercept_strndup) {
+ Report("WARNING: strndup* interceptors are enabled even though "
+ "replace_str=0. Use intercept_strndup=0 to disable them.");
+ }
}
} // namespace __asan
diff --git a/lib/asan/tests/asan_str_test.cc b/lib/asan/tests/asan_str_test.cc
index c790088f8..964f6da02 100644
--- a/lib/asan/tests/asan_str_test.cc
+++ b/lib/asan/tests/asan_str_test.cc
@@ -154,6 +154,33 @@ TEST(AddressSanitizer, MAYBE_StrDupOOBTest) {
free(str);
}
+#if SANITIZER_TEST_HAS_STRNDUP
+TEST(AddressSanitizer, MAYBE_StrNDupOOBTest) {
+ size_t size = Ident(42);
+ char *str = MallocAndMemsetString(size);
+ char *new_str;
+ // Normal strndup calls.
+ str[size - 1] = '\0';
+ new_str = strndup(str, size - 13);
+ free(new_str);
+ new_str = strndup(str + size - 1, 13);
+ free(new_str);
+ // Argument points to not allocated memory.
+ EXPECT_DEATH(Ident(strndup(str - 1, 13)), LeftOOBReadMessage(1));
+ EXPECT_DEATH(Ident(strndup(str + size, 13)), RightOOBReadMessage(0));
+ // Overwrite the terminating '\0' and hit unallocated memory.
+ str[size - 1] = 'z';
+ EXPECT_DEATH(Ident(strndup(str, size + 13)), RightOOBReadMessage(0));
+ // Check handling of non 0 terminated strings.
+ Ident(new_str = strndup(str + size - 1, 0));
+ free(new_str);
+ Ident(new_str = strndup(str + size - 1, 1));
+ free(new_str);
+ EXPECT_DEATH(Ident(strndup(str + size - 1, 2)), RightOOBReadMessage(0));
+ free(str);
+}
+#endif // SANITIZER_TEST_HAS_STRNDUP
+
TEST(AddressSanitizer, StrCpyOOBTest) {
size_t to_size = Ident(30);
size_t from_size = Ident(6); // less than to_size
diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc
index ab08744a7..fbc2ea4fe 100644
--- a/lib/msan/msan_interceptors.cc
+++ b/lib/msan/msan_interceptors.cc
@@ -341,33 +341,6 @@ INTERCEPTOR(char *, __strdup, char *src) {
#define MSAN_MAYBE_INTERCEPT___STRDUP
#endif
-INTERCEPTOR(char *, strndup, char *src, SIZE_T n) {
- ENSURE_MSAN_INITED();
- GET_STORE_STACK_TRACE;
- // On FreeBSD strndup() leverages strnlen().
- InterceptorScope interceptor_scope;
- SIZE_T copy_size = REAL(strnlen)(src, n);
- char *res = REAL(strndup)(src, n);
- CopyShadowAndOrigin(res, src, copy_size, &stack);
- __msan_unpoison(res + copy_size, 1); // \0
- return res;
-}
-
-#if !SANITIZER_FREEBSD
-INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) {
- ENSURE_MSAN_INITED();
- GET_STORE_STACK_TRACE;
- SIZE_T copy_size = REAL(strnlen)(src, n);
- char *res = REAL(__strndup)(src, n);
- CopyShadowAndOrigin(res, src, copy_size, &stack);
- __msan_unpoison(res + copy_size, 1); // \0
- return res;
-}
-#define MSAN_MAYBE_INTERCEPT___STRNDUP INTERCEPT_FUNCTION(__strndup)
-#else
-#define MSAN_MAYBE_INTERCEPT___STRNDUP
-#endif
-
INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
ENSURE_MSAN_INITED();
char *res = REAL(gcvt)(number, ndigit, buf);
@@ -1373,6 +1346,13 @@ int OnExit() {
return __msan_memcpy(to, from, size); \
}
+#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
+ do { \
+ GET_STORE_STACK_TRACE; \
+ CopyShadowAndOrigin(to, from, size, &stack); \
+ __msan_unpoison(to + size, 1); \
+ } while (false)
+
#include "sanitizer_common/sanitizer_platform_interceptors.h"
#include "sanitizer_common/sanitizer_common_interceptors.inc"
@@ -1540,8 +1520,6 @@ void InitializeInterceptors() {
INTERCEPT_FUNCTION(stpcpy); // NOLINT
INTERCEPT_FUNCTION(strdup);
MSAN_MAYBE_INTERCEPT___STRDUP;
- INTERCEPT_FUNCTION(strndup);
- MSAN_MAYBE_INTERCEPT___STRNDUP;
INTERCEPT_FUNCTION(strncpy); // NOLINT
INTERCEPT_FUNCTION(gcvt);
INTERCEPT_FUNCTION(strcat); // NOLINT
diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc
index c7c91324a..543a7eb98 100644
--- a/lib/msan/tests/msan_test.cc
+++ b/lib/msan/tests/msan_test.cc
@@ -1581,19 +1581,28 @@ TEST(MemorySanitizer, strdup) {
TEST(MemorySanitizer, strndup) {
char buf[4] = "abc";
__msan_poison(buf + 2, sizeof(*buf));
- char *x = strndup(buf, 3);
+ char *x;
+ EXPECT_UMR(x = strndup(buf, 3));
EXPECT_NOT_POISONED(x[0]);
EXPECT_NOT_POISONED(x[1]);
EXPECT_POISONED(x[2]);
EXPECT_NOT_POISONED(x[3]);
free(x);
+ // Check handling of non 0 terminated strings.
+ buf[3] = 'z';
+ __msan_poison(buf + 3, sizeof(*buf));
+ EXPECT_UMR(x = strndup(buf + 3, 1));
+ EXPECT_POISONED(x[0]);
+ EXPECT_NOT_POISONED(x[1]);
+ free(x);
}
TEST(MemorySanitizer, strndup_short) {
char buf[4] = "abc";
__msan_poison(buf + 1, sizeof(*buf));
__msan_poison(buf + 2, sizeof(*buf));
- char *x = strndup(buf, 2);
+ char *x;
+ EXPECT_UMR(x = strndup(buf, 2));
EXPECT_NOT_POISONED(x[0]);
EXPECT_POISONED(x[1]);
EXPECT_NOT_POISONED(x[2]);
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 53204b48e..c0c08a031 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -34,6 +34,8 @@
// COMMON_INTERCEPTOR_MEMSET_IMPL
// COMMON_INTERCEPTOR_MEMMOVE_IMPL
// COMMON_INTERCEPTOR_MEMCPY_IMPL
+// COMMON_INTERCEPTOR_COPY_STRING
+// COMMON_INTERCEPTOR_STRNDUP_IMPL
//===----------------------------------------------------------------------===//
#include "interception/interception.h"
@@ -217,6 +219,24 @@ bool PlatformHasDifferentMemcpyAndMemmove();
}
#endif
+#ifndef COMMON_INTERCEPTOR_COPY_STRING
+#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
+#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \
+ COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \
+ uptr copy_length = internal_strnlen(s, size); \
+ char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \
+ if (common_flags()->intercept_strndup) { \
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \
+ } \
+ COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
+ internal_memcpy(new_mem, s, copy_length); \
+ new_mem[copy_length] = '\0'; \
+ return new_mem;
+#endif
+
struct FileMetadata {
// For open_memstream().
char **addr;
@@ -300,6 +320,26 @@ INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
#define INIT_STRNLEN
#endif
+#if SANITIZER_INTERCEPT_STRNDUP
+INTERCEPTOR(char*, strndup, const char *s, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
+}
+#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
+#else
+#define INIT_STRNDUP
+#endif // SANITIZER_INTERCEPT_STRNDUP
+
+#if SANITIZER_INTERCEPT___STRNDUP
+INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
+}
+#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
+#else
+#define INIT___STRNDUP
+#endif // SANITIZER_INTERCEPT___STRNDUP
+
#if SANITIZER_INTERCEPT_TEXTDOMAIN
INTERCEPTOR(char*, textdomain, const char *domainname) {
void *ctx;
@@ -6163,6 +6203,8 @@ static void InitializeCommonInterceptors() {
INIT_TEXTDOMAIN;
INIT_STRLEN;
INIT_STRNLEN;
+ INIT_STRNDUP;
+ INIT___STRNDUP;
INIT_STRCMP;
INIT_STRNCMP;
INIT_STRCASECMP;
diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc
index 12c126fa7..f87d8b643 100644
--- a/lib/sanitizer_common/sanitizer_flags.inc
+++ b/lib/sanitizer_common/sanitizer_flags.inc
@@ -197,6 +197,9 @@ COMMON_FLAG(bool, intercept_strpbrk, true,
COMMON_FLAG(bool, intercept_strlen, true,
"If set, uses custom wrappers for strlen and strnlen functions "
"to find more errors.")
+COMMON_FLAG(bool, intercept_strndup, true,
+ "If set, uses custom wrappers for strndup functions "
+ "to find more errors.")
COMMON_FLAG(bool, intercept_strchr, true,
"If set, uses custom wrappers for strchr, strchrnul, and strrchr "
"functions to find more errors.")
diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h
index e5644ef25..a95497467 100644
--- a/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -25,6 +25,12 @@
# define SI_NOT_WINDOWS 0
#endif
+#if SANITIZER_POSIX
+# define SI_POSIX 1
+#else
+# define SI_POSIX 0
+#endif
+
#if SANITIZER_LINUX && !SANITIZER_ANDROID
# define SI_LINUX_NOT_ANDROID 1
#else
@@ -69,6 +75,12 @@
# define SI_UNIX_NOT_MAC 0
#endif
+#if SANITIZER_LINUX && !SANITIZER_FREEBSD
+# define SI_LINUX_NOT_FREEBSD 1
+# else
+# define SI_LINUX_NOT_FREEBSD 0
+#endif
+
#define SANITIZER_INTERCEPT_STRLEN 1
#define SANITIZER_INTERCEPT_STRNLEN SI_NOT_MAC
#define SANITIZER_INTERCEPT_STRCMP 1
@@ -86,6 +98,8 @@
#define SANITIZER_INTERCEPT_MEMMOVE 1
#define SANITIZER_INTERCEPT_MEMCPY 1
#define SANITIZER_INTERCEPT_MEMCMP 1
+#define SANITIZER_INTERCEPT_STRNDUP SI_POSIX
+#define SANITIZER_INTERCEPT___STRNDUP SI_LINUX_NOT_FREEBSD
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070
# define SI_MAC_DEPLOYMENT_BELOW_10_7 1
diff --git a/lib/sanitizer_common/tests/sanitizer_test_utils.h b/lib/sanitizer_common/tests/sanitizer_test_utils.h
index 9c162a66f..b7728d9ea 100644
--- a/lib/sanitizer_common/tests/sanitizer_test_utils.h
+++ b/lib/sanitizer_common/tests/sanitizer_test_utils.h
@@ -124,4 +124,10 @@ static inline uint32_t my_rand() {
# define SANITIZER_TEST_HAS_PRINTF_L 0
#endif
+#if !defined(_MSC_VER)
+# define SANITIZER_TEST_HAS_STRNDUP 1
+#else
+# define SANITIZER_TEST_HAS_STRNDUP 0
+#endif
+
#endif // SANITIZER_TEST_UTILS_H