[llvm-branch-commits] [compiler-rt] a6ca3f4 - Revert "[ASan][Windows] Fix memmove/memcpy interception on x64 (#192060)"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Apr 22 08:49:45 PDT 2026
Author: Alexandre Ganea
Date: 2026-04-22T11:49:41-04:00
New Revision: a6ca3f457dad19a2f957abbf00daaed69eb87a7c
URL: https://github.com/llvm/llvm-project/commit/a6ca3f457dad19a2f957abbf00daaed69eb87a7c
DIFF: https://github.com/llvm/llvm-project/commit/a6ca3f457dad19a2f957abbf00daaed69eb87a7c.diff
LOG: Revert "[ASan][Windows] Fix memmove/memcpy interception on x64 (#192060)"
This reverts commit 62ae7e4786d9b5653435861fd5f6b89baaa084e0.
Added:
Modified:
compiler-rt/lib/asan/asan_allocator.cpp
compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc
Removed:
################################################################################
diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index f9d3c5d01e0e3..46ba7e16da9b2 100644
--- a/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/compiler-rt/lib/asan/asan_allocator.cpp
@@ -34,14 +34,6 @@
#include "sanitizer_common/sanitizer_quarantine.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
-#if SANITIZER_WINDOWS64
-namespace __sanitizer {
-// Set by InitializeMemintrinsicInterceptors(). True when the CRT exposes
-// memcpy and memmove as separate functions (newer vcruntime140.dll).
-extern bool win64_memcpy_memmove_are_disjoint;
-} // namespace __sanitizer
-#endif
-
namespace __asan {
// Valid redzone sizes are 16, 32, 64, ... 2048, so we encode them in 3 bits.
@@ -815,27 +807,7 @@ struct Allocator {
uptr memcpy_size = Min(new_size, m->UsedSize());
// If realloc() races with free(), we may start copying freed memory.
// However, we will report racy double-free later anyway.
-#if SANITIZER_WINDOWS64
- // On Win64, REAL(memcpy) only points at a distinct non-interceptor
- // function when memcpy and memmove are separate CRT entry points. When
- // they are aliased we keep REAL(memcpy) == REAL(memmove), and both may
- // dispatch back through the intercepted libc routine, which performs
- // shadow-checked reads. That is a problem for chunks upgraded from
- // malloc(0) / HeapReAlloc(..., 0): the single live byte is still
- // shadow-poisoned (from_zero_alloc / asan_mark_zero_allocation), so a
- // shadow-checked copy of Min(new_size, UsedSize()) bytes reports a
- // spurious heap-buffer-overflow (see ReallocTest,
- // heaprealloc_alloc_zero). Fall back to internal_memcpy (which bypasses
- // the interceptor) for the poisoned or aliased cases, and only use
- // REAL(memcpy) on the fast path.
- if (memcpy_size && __sanitizer::win64_memcpy_memmove_are_disjoint &&
- !m->from_zero_alloc)
- REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
- else
- internal_memcpy(new_ptr, old_ptr, memcpy_size);
-#else
REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
-#endif
Deallocate(old_ptr, 0, 0, stack, FROM_MALLOC);
}
return new_ptr;
diff --git a/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp b/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp
index 17f98d51fd8e6..46e0e90738f24 100644
--- a/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp
@@ -42,10 +42,10 @@ INTERCEPT_LIBRARY_FUNCTION_ASAN(memchr);
# endif
INTERCEPT_LIBRARY_FUNCTION_ASAN(memcmp);
INTERCEPT_LIBRARY_FUNCTION_ASAN(memcpy);
-// Older Win64 CRTs aliased memmove and memcpy, so hooking memcpy was enough.
-// Newer vcruntime140.dll ships them as distinct functions, so we always have
-// to intercept memmove explicitly.
+# ifndef _WIN64
+// memmove and memcpy share an implementation on amd64
INTERCEPT_LIBRARY_FUNCTION_ASAN(memmove);
+# endif
INTERCEPT_LIBRARY_FUNCTION_ASAN(memset);
INTERCEPT_LIBRARY_FUNCTION_ASAN(strcat);
INTERCEPT_LIBRARY_FUNCTION_ASAN(strchr);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc
index eaf1d869ca62d..0b6731c89950b 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc
@@ -234,38 +234,11 @@ INTERCEPTOR(void *, bzero, void *block, usize size) {
#endif // SANITIZER_INTERCEPT_BZERO
namespace __sanitizer {
-
-#if SANITIZER_WINDOWS64
-// On Windows x64, memcpy and memmove used to share a single implementation in
-// the CRT (vcruntime140.dll), but newer CRTs ship them as distinct functions.
-// Detect this at interceptor init time so the rest of the runtime can pick the
-// right code path (e.g. asan_allocator's Reallocate). See
-// InitializeMemintrinsicInterceptors below.
-bool win64_memcpy_memmove_are_disjoint;
-#endif
-
// This does not need to be called if InitializeCommonInterceptors() is called.
void InitializeMemintrinsicInterceptors() {
INIT_MEMSET;
-#if SANITIZER_WINDOWS64
- // Use volatile to keep the compiler from folding &memcpy != &memmove at
- // compile time (the two declarations are distinct symbols even if the
- // runtime resolves them to the same address).
- volatile uptr memcpy_addr = (uptr)&memcpy;
- volatile uptr memmove_addr = (uptr)&memmove;
- win64_memcpy_memmove_are_disjoint = (memcpy_addr != memmove_addr);
- INIT_MEMMOVE;
- if (win64_memcpy_memmove_are_disjoint) {
- COMMON_INTERCEPT_FUNCTION(memcpy);
- } else {
- // Legacy CRT: memcpy and memmove are the same function; just share REAL.
- ASSIGN_REAL(memcpy, memmove);
- }
- CHECK(REAL(memcpy));
-#else
INIT_MEMMOVE;
INIT_MEMCPY;
-#endif
INIT_AEABI_MEM;
INIT___BZERO;
INIT_BZERO;
More information about the llvm-branch-commits
mailing list