[compiler-rt] [ASan][Windows] Fix memmove/memcpy interception on x64 (PR #192060)

Alexandre Ganea via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 06:50:24 PDT 2026


https://github.com/aganea created https://github.com/llvm/llvm-project/pull/192060

On Windows x64, memcpy and memmove used to share an implementation in `vcruntime140.dll`, but newer versions of the CRT may provide them as separate functions. Detect this at runtime and intercept accordingly, rather than unconditionally assuming they alias each other.

Should fix https://github.com/llvm/llvm-project/issues/126077

>From 73ee2978d42c9c7af2a3b6b13ab8e281379c1384 Mon Sep 17 00:00:00 2001
From: Alexandre Ganea <alex_toresh at yahoo.fr>
Date: Tue, 14 Apr 2026 09:48:47 -0400
Subject: [PATCH] [ASan][Windows] Fix memmove/memcpy interception on x64

On Windows x64, memcpy and memmove used to share an implementation in
vcruntime140.dll, but newer versions of the CRT may provide them as
separate functions. Detect this at runtime and intercept accordingly,
rather than unconditionally assuming they alias each other.

Should fix https://github.com/llvm/llvm-project/issues/126077
---
 .../lib/asan/asan_win_static_runtime_thunk.cpp |  3 ---
 ...tizer_common_interceptors_memintrinsics.inc | 18 ++++++++++++++++++
 2 files changed, 18 insertions(+), 3 deletions(-)

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 46e0e90738f24..601b0d2dea11f 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,7 @@ INTERCEPT_LIBRARY_FUNCTION_ASAN(memchr);
 #  endif
 INTERCEPT_LIBRARY_FUNCTION_ASAN(memcmp);
 INTERCEPT_LIBRARY_FUNCTION_ASAN(memcpy);
-#  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 0b6731c89950b..8b50392a45f8d 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc
@@ -237,8 +237,26 @@ namespace __sanitizer {
 // This does not need to be called if InitializeCommonInterceptors() is called.
 void InitializeMemintrinsicInterceptors() {
   INIT_MEMSET;
+#if SANITIZER_WINDOWS64
+  // On Windows x64, memcpy and memmove used to be the same function in the
+  // CRT (vcruntime140.dll), but newer versions of the runtime may provide
+  // them as separate functions.  Detect at runtime before INIT_MEMMOVE
+  // patches the entry point.
+  // Use volatile to prevent the compiler from assuming distinct declarations
+  // imply distinct addresses and folding the comparison to true.
+  volatile uptr memcpy_addr = (uptr)memcpy;
+  volatile uptr memmove_addr = (uptr)memmove;
+  bool memcpy_is_separate = (memcpy_addr != memmove_addr);
+  INIT_MEMMOVE;
+  if (memcpy_is_separate)
+    COMMON_INTERCEPT_FUNCTION(memcpy);
+  else
+    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-commits mailing list