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_memmove_sanity.cpp b/compiler-rt/test/asan/TestCases/Windows/memcpy_memmove_sanity.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/memcpy_memmove_sanity.cpp @@ -0,0 +1,36 @@ +// 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 memcpy 2>&1 | FileCheck %s +// RUN: not %run %t.noicf.ref memcpy 2>&1 | FileCheck %s +// RUN: not %run %t.icf.noref memcpy 2>&1 | FileCheck %s +// RUN: not %run %t.noicf.noref memcpy 2>&1 | FileCheck %s +// RUN: not %run %t.icf.ref memmove 2>&1 | FileCheck %s +// RUN: not %run %t.noicf.ref memmove 2>&1 | FileCheck %s +// RUN: not %run %t.icf.noref memmove 2>&1 | FileCheck %s +// RUN: not %run %t.noicf.noref memmove 2>&1 | FileCheck %s +// UNSUPPORTED: target={{.*-windows-gnu}} + +#include +#include + +int main(int argc, char **argv) { + int *buf = new int[4]; + + memmove(buf + 1, buf, 3 * sizeof(int)); + memcpy(buf + 1, buf, 3 * sizeof(int)); + + delete[] buf; + if (argc != 2) { + abort(); + } + if (strcmp(argv[1], "memcpy") == 0) { + memcpy(buf + 1, buf, 3 * sizeof(int)); + } else if (strcmp(argv[1], "memmove") == 0) { + memmove(buf + 1, buf, 3 * sizeof(int)); + } + // CHECK: AddressSanitizer: heap-use-after-free + + return 0; +}