[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