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

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 06:51:01 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Alexandre Ganea (aganea)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/192060.diff


2 Files Affected:

- (modified) compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp (-3) 
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc (+18) 


``````````diff
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;

``````````

</details>


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


More information about the llvm-commits mailing list