diff options
author | Alexander Potapenko <glider@google.com> | 2013-09-20 10:56:34 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2013-09-20 10:56:34 +0000 |
commit | d4d7040ee026ab04502c42327ed5081f704a8e3c (patch) | |
tree | b88d29acf8d7c6a3442bef2428b3df0ace872408 | |
parent | 81b0fe0ae241ca12882f653dcf6b13eaa5ca284d (diff) | |
download | compiler-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.cc | 46 | ||||
-rw-r--r-- | lib/asan/tests/asan_str_test.cc | 2 |
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; |