summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2013-09-20 10:56:34 +0000
committerAlexander Potapenko <glider@google.com>2013-09-20 10:56:34 +0000
commitd4d7040ee026ab04502c42327ed5081f704a8e3c (patch)
treeb88d29acf8d7c6a3442bef2428b3df0ace872408
parent81b0fe0ae241ca12882f653dcf6b13eaa5ca284d (diff)
downloadcompiler-rt-d4d7040ee026ab04502c42327ed5081f704a8e3c.tar.gz
compiler-rt-d4d7040ee026ab04502c42327ed5081f704a8e3c.tar.bz2
compiler-rt-d4d7040ee026ab04502c42327ed5081f704a8e3c.tar.xz
[ASan] Enforce the memmove semantics for both memcpy() and memmove() interceptors on Darwin.
Due to bugs in the interposition of resolver functions on 10.7 and 10.8 both memcpy() and memmove() were previously intercepted by INTERCEPTOR(memcpy), which led to false positives and crashes (see http://llvm.org/bugs/show_bug.cgi?id=16362) We choose to use a memmove-like function in both cases. This effectively disables the overlap checks in memcpy(), but the overlaps aren't possible in practice, because memcpy() and memmove() are the same function on Darwin. Once the interposition is fixed in 10.9, we'll need to revisit this issue, see https://code.google.com/p/address-sanitizer/issues/detail?id=226 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@191081 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/asan/asan_interceptors.cc46
-rw-r--r--lib/asan/tests/asan_str_test.cc2
2 files changed, 32 insertions, 16 deletions
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc
index c996b661..e2ed6d5d 100644
--- a/lib/asan/asan_interceptors.cc
+++ b/lib/asan/asan_interceptors.cc
@@ -315,7 +315,26 @@ INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
return REAL(memcmp(a1, a2, size));
}
+#define MEMMOVE_BODY { \
+ if (!asan_inited) return internal_memmove(to, from, size); \
+ if (asan_init_is_running) { \
+ return REAL(memmove)(to, from, size); \
+ } \
+ ENSURE_ASAN_INITED(); \
+ if (flags()->replace_intrin) { \
+ ASAN_READ_RANGE(from, size); \
+ ASAN_WRITE_RANGE(to, size); \
+ } \
+ /* Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. \
+ See also \
+ http://code.google.com/p/address-sanitizer/issues/detail?id=116. */ \
+ return internal_memmove(to, from, size); \
+}
+
+INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) MEMMOVE_BODY
+
INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
+#if !SANITIZER_MAC
if (!asan_inited) return internal_memcpy(to, from, size);
// memcpy is called during __asan_init() from the internals
// of printf(...).
@@ -332,24 +351,19 @@ INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
ASAN_READ_RANGE(from, size);
ASAN_WRITE_RANGE(to, size);
}
- // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
+ // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8, so
+ // calling REAL(memcpy) here leads to infinite recursion.
// See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
return internal_memcpy(to, from, size);
-}
-
-INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
- if (!asan_inited) return internal_memmove(to, from, size);
- if (asan_init_is_running) {
- return REAL(memmove)(to, from, size);
- }
- ENSURE_ASAN_INITED();
- if (flags()->replace_intrin) {
- ASAN_READ_RANGE(from, size);
- ASAN_WRITE_RANGE(to, size);
- }
- // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
- // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
- return internal_memmove(to, from, size);
+#else
+ // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
+ // with WRAP(memcpy). As a result, false positives are reported for memmove()
+ // calls. If we just disable error reporting with
+ // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
+ // internal_memcpy(), which may lead to crashes, see
+ // http://llvm.org/bugs/show_bug.cgi?id=16362.
+ MEMMOVE_BODY
+#endif // !SANITIZER_MAC
}
INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
diff --git a/lib/asan/tests/asan_str_test.cc b/lib/asan/tests/asan_str_test.cc
index 78101129..5a6fef38 100644
--- a/lib/asan/tests/asan_str_test.cc
+++ b/lib/asan/tests/asan_str_test.cc
@@ -12,6 +12,8 @@
//===----------------------------------------------------------------------===//
#include "asan_test_utils.h"
+#include <AvailabilityMacros.h>
+
// Used for string functions tests
static char global_string[] = "global";
static size_t global_string_length = 6;