diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -199,12 +199,15 @@ #endif // Platform-specific options. -#if SANITIZER_APPLE -#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 -#elif SANITIZER_WINDOWS64 -#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 +#if SANITIZER_APPLE || (SANITIZER_WINDOWS && SANITIZER_X64) +# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 +# define PLATFORM_MEMCPY_MEMMOVE_CAN_BE_FOLDED 0 +#elif SANITIZER_WINDOWS && SANITIZER_I386 +# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 +# define PLATFORM_MEMCPY_MEMMOVE_CAN_BE_FOLDED 1 #else #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 +# define PLATFORM_MEMCPY_MEMMOVE_CAN_BE_FOLDED 0 #endif // SANITIZER_APPLE #ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE @@ -871,11 +874,19 @@ // N.B.: If we switch this to internal_ we'll have to use internal_memmove // due to memcpy being an alias of memmove on OS X. void *ctx; -#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE - COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size); -#else - COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); -#endif +# ifndef PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE +# error "Undefined" +# endif + +# ifndef PLATFORM_MEMCPY_MEMMOVE_CAN_BE_FOLDED +# error "Undefined" +# endif +# if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE && \ + !PLATFORM_MEMCPY_MEMMOVE_CAN_BE_FOLDED + COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size); +# else + COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); +# endif } #define INIT_MEMCPY \ diff --git a/compiler-rt/test/asan/TestCases/Windows/memcpy_sanity.cpp b/compiler-rt/test/asan/TestCases/Windows/memcpy_sanity.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/memcpy_sanity.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cl_asan %s -Fe%t.icf.ref /clang:-fno-builtin-memcpy /clang:-fno-builtin-memmove /link /OPT:ICF /OPT:REF +// RUN: %clang_cl_asan %s -Fe%t.noicf.ref /clang:-fno-builtin-memcpy /clang:-fno-builtin-memmove /link /OPT:NOICF /OPT:REF +// RUN: %clang_cl_asan %s -Fe%t.icf.noref /clang:-fno-builtin-memcpy /clang:-fno-builtin-memmove /link /OPT:ICF /OPT:NOREF +// RUN: %clang_cl_asan %s -Fe%t.noicf.noref /clang:-fno-builtin-memcpy /clang:-fno-builtin-memmove /link /OPT:NOICF /OPT:NOREF +// RUN: not %run %t.icf.ref 2>&1 | FileCheck %s +// RUN: not %run %t.noicf.ref 2>&1 | FileCheck %s +// RUN: not %run %t.icf.noref 2>&1 | FileCheck %s +// RUN: not %run %t.noicf.noref 2>&1 | FileCheck %s + +#include + +int main() { + int *buf = new int[4]; + + memmove(buf + 1, buf, 3 * sizeof(int)); + memcpy(buf + 1, buf, 3 * sizeof(int)); + + delete[] buf; + + memcpy(buf + 1, buf, 3 * sizeof(int)); + // CHECK: AddressSanitizer: heap-use-after-free + + return 0; +} diff --git a/compiler-rt/test/asan/TestCases/Windows/memmove_sanity.cpp b/compiler-rt/test/asan/TestCases/Windows/memmove_sanity.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/memmove_sanity.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cl_asan %s -Fe%t.icf.ref /clang:-fno-builtin-memcpy /clang:-fno-builtin-memmove /link /OPT:ICF /OPT:REF +// RUN: %clang_cl_asan %s -Fe%t.noicf.ref /clang:-fno-builtin-memcpy /clang:-fno-builtin-memmove /link /OPT:NOICF /OPT:REF +// RUN: %clang_cl_asan %s -Fe%t.icf.noref /clang:-fno-builtin-memcpy /clang:-fno-builtin-memmove /link /OPT:ICF /OPT:NOREF +// RUN: %clang_cl_asan %s -Fe%t.noicf.noref /clang:-fno-builtin-memcpy /clang:-fno-builtin-memmove /link /OPT:NOICF /OPT:NOREF +// RUN: not %run %t.icf.ref 2>&1 | FileCheck %s +// RUN: not %run %t.noicf.ref 2>&1 | FileCheck %s +// RUN: not %run %t.icf.noref 2>&1 | FileCheck %s +// RUN: not %run %t.noicf.noref 2>&1 | FileCheck %s + +#include + +int main() { + int *buf = new int[4]; + + memmove(buf + 1, buf, 3 * sizeof(int)); + memcpy(buf + 1, buf, 3 * sizeof(int)); + + delete[] buf; + + memmove(buf + 1, buf, 3 * sizeof(int)); + // CHECK: AddressSanitizer: heap-use-after-free + + return 0; +}