[compiler-rt] [asan][win][msvc] override new and delete and seperate TUs (PR #68754)

Charlie Barto via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 16 10:14:09 PST 2023


https://github.com/barcharcraz updated https://github.com/llvm/llvm-project/pull/68754

>From f7576fc3bc174ebebf4ac15ee6624003301ff427 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Tue, 11 Jul 2023 17:26:14 -0700
Subject: [PATCH 01/19] win_new_delete_override1

---
 compiler-rt/lib/asan/CMakeLists.txt           |  53 ++-
 ...n_win_delete_array_align_nothrow_thunk.cpp |  40 ++
 .../asan_win_delete_array_align_thunk.cpp     |  48 +++
 .../asan_win_delete_array_nothrow_thunk.cpp   |  39 ++
 ...asan_win_delete_array_size_align_thunk.cpp |  49 +++
 .../asan/asan_win_delete_array_size_thunk.cpp |  47 ++
 .../lib/asan/asan_win_delete_array_thunk.cpp  |  48 +++
 ..._win_delete_scalar_align_nothrow_thunk.cpp |  40 ++
 .../asan_win_delete_scalar_align_thunk.cpp    |  44 ++
 .../asan_win_delete_scalar_nothrow_thunk.cpp  |  39 ++
 ...san_win_delete_scalar_size_align_thunk.cpp |  47 ++
 .../asan_win_delete_scalar_size_thunk.cpp     |  46 ++
 .../lib/asan/asan_win_delete_scalar_thunk.cpp |  44 ++
 ...asan_win_new_array_align_nothrow_thunk.cpp |  50 +++
 .../asan/asan_win_new_array_align_thunk.cpp   |  46 ++
 .../asan/asan_win_new_array_nothrow_thunk.cpp |  49 +++
 .../lib/asan/asan_win_new_array_thunk.cpp     |  45 ++
 compiler-rt/lib/asan/asan_win_new_delete.cpp  | 160 +++++++
 .../asan/asan_win_new_delete_thunk_common.h   |  99 +++++
 ...san_win_new_scalar_align_nothrow_thunk.cpp |  49 +++
 .../asan/asan_win_new_scalar_align_thunk.cpp  |  42 ++
 .../asan_win_new_scalar_nothrow_thunk.cpp     |  48 +++
 .../lib/asan/asan_win_new_scalar_thunk.cpp    |  42 ++
 compiler-rt/lib/asan/asan_win_thunk_common.h  |  64 +++
 .../new_delete_mfc_already_defined.cpp        |  25 ++
 .../new_delete_mfc_already_defined_dbg.cpp    |  25 ++
 .../operator_array_new_with_dtor_left_oob.cpp |   4 +
 .../operator_delete_replacement_array.cpp     |  41 ++
 .../operator_delete_replacement_scalar.cpp    |  47 ++
 .../operator_new_delete_replacement_all.cpp   |  35 ++
 .../operator_new_delete_replacement_common.h  | 403 ++++++++++++++++++
 .../operator_new_delete_replacement_macros.h  |  29 ++
 .../operator_new_replacement_array.cpp        |  39 ++
 .../operator_new_replacement_scalar.cpp       |  43 ++
 .../TestCases/Windows/operator_new_uaf.cpp    |   2 +
 35 files changed, 1968 insertions(+), 3 deletions(-)
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_array_align_nothrow_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_array_nothrow_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_array_size_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_array_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_scalar_align_nothrow_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_scalar_align_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_scalar_nothrow_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_scalar_size_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_new_array_nothrow_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_new_array_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_new_delete.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
 create mode 100644 compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp
 create mode 100644 compiler-rt/lib/asan/asan_win_thunk_common.h
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_array.cpp
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_scalar.cpp
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_all.cpp
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_common.h
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_macros.h
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_array.cpp
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_scalar.cpp

diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index 48d0e91052d73bb..6f286e2386b0b26 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -38,9 +38,40 @@ if (NOT WIN32 AND NOT APPLE)
     )
 endif()
 
-set(ASAN_CXX_SOURCES
-  asan_new_delete.cpp
-  )
+if (WIN32)
+  set(ASAN_CXX_SOURCES asan_win_new_delete.cpp)
+else()
+  set(ASAN_CXX_SOURCES asan_new_delete.cpp)
+endif()
+
+if (APPLE)
+  set(ASAN_SOURCES ASAN_CXX_SOURCES)
+endif()
+
+if (WIN32)
+  set(ASAN_STATIC_IMPLIB_SOURCES
+    asan_win_delete_array_thunk.cpp
+    asan_win_delete_array_align_thunk.cpp
+    asan_win_delete_array_align_nothrow_thunk.cpp
+    asan_win_delete_array_nothrow_thunk.cpp
+    asan_win_delete_array_size_thunk.cpp
+    asan_win_delete_array_size_align_thunk.cpp
+    asan_win_delete_scalar_thunk.cpp
+    asan_win_delete_scalar_align_thunk.cpp
+    asan_win_delete_scalar_align_nothrow_thunk.cpp
+    asan_win_delete_scalar_nothrow_thunk.cpp
+    asan_win_delete_scalar_size_thunk.cpp
+    asan_win_delete_scalar_size_align_thunk.cpp
+    asan_win_new_array_thunk.cpp
+    asan_win_new_array_align_thunk.cpp
+    asan_win_new_array_align_nothrow_thunk.cpp
+    asan_win_new_array_nothrow_thunk.cpp
+    asan_win_new_scalar_thunk.cpp
+    asan_win_new_scalar_align_thunk.cpp
+    asan_win_new_scalar_align_nothrow_thunk.cpp
+    asan_win_new_scalar_nothrow_thunk.cpp
+    )
+endif()
 
 set(ASAN_STATIC_SOURCES
   asan_rtl_static.cpp
@@ -83,6 +114,13 @@ SET(ASAN_HEADERS
   asan_thread.h
   )
 
+if (WIN32)
+  list(APPEND ASAN_HEADERS
+    asan_win_new_delete_thunk_common.h
+    asan_win_thunk_common.h
+    )
+endif()
+
 include_directories(..)
 
 set(ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
@@ -139,6 +177,15 @@ add_compiler_rt_object_libraries(RTAsan_dynamic
   CFLAGS ${ASAN_DYNAMIC_CFLAGS}
   DEFS ${ASAN_DYNAMIC_DEFINITIONS})
 
+if (WIN32)
+  add_compiler_rt_object_libraries(RTAsan_static_implib
+    ARCHS ${ASAN_SUPPORTED_ARCH}
+    SOURCES ${ASAN_STATIC_IMPLIB_SOURCES}
+    ADDITIONAL_HEADERS ${ASAN_HEADERS}
+    CFLAGS ${ASAN_CFLAGS} ${NO_DEFAULT_LIBS_OPTION}
+    DEFS ${ASAN_COMMON_DEFINITIONS})
+endif()
+
 if(NOT APPLE)
   add_compiler_rt_object_libraries(RTAsan
     ARCHS ${ASAN_SUPPORTED_ARCH}
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_align_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_align_nothrow_thunk.cpp
new file mode 100644
index 000000000000000..dbc258749446b98
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_array_align_nothrow_thunk.cpp
@@ -0,0 +1,40 @@
+//===-- asan_win_delete_array_align_nothrow_thunk.cc ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+//////////////////////////////////////////////////////////////////////////////////
+// clang-format off
+// Aligned delete() Fallback Ordering
+//
+// +-------------------+
+// |delete_scalar_align<----+---------------------------+
+// +--^----------------+    |                           |
+//    |                     |                           |
+// +--+---------------+  +--+---------------------+  +--+------------------------+
+// |delete_array_align|  |delete_scalar_size_align|  |delete_scalar_align_nothrow|
+// +--^-----^---------+  +------------------------+  +---------------------------+
+//    |     |
+//    |     +------------------------+
+//    |                              |
+// +--+--------------------+  +------+-------------------+
+// |delete_array_size_align|  |DELETE_ARRAY_ALIGN_NOTHROW|
+// +-----------------------+  +--------------------------+
+// clang-format on
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete[](void* ptr, std::align_val_t align,
+                       std::nothrow_t const&) noexcept {
+  // nothrow version is identical to throwing version
+  operator delete[](ptr, align);
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp
new file mode 100644
index 000000000000000..eb7351a3e9d5f50
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp
@@ -0,0 +1,48 @@
+//===-- asan_win_delete_array_align_thunk.cc ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+//////////////////////////////////////////////////////////////////////////////////
+// clang-format off
+// Aligned delete() Fallback Ordering
+//
+// +-------------------+
+// |delete_scalar_align<----+---------------------------+
+// +--^----------------+    |                           |
+//    |                     |                           |
+// +--+---------------+  +--+---------------------+  +--+------------------------+
+// |DELETE_ARRAY_ALIGN|  |delete_scalar_size_align|  |delete_scalar_align_nothrow|
+// +--^-----^---------+  +------------------------+  +---------------------------+
+//    |     |
+//    |     +------------------------+
+//    |                              |
+// +--+--------------------+  +------+-------------------+
+// |delete_array_size_align|  |delete_array_align_nothrow|
+// +-----------------------+  +--------------------------+
+// clang-format on
+
+__asan_InitDefine<op_delete_array_align> init_delete_array_align;
+
+extern "C" void __cdecl __asan_delete_array_align(
+    __asan_win_new_delete_data* data, void* ptr, std::align_val_t align);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete[](void* ptr, std::align_val_t align) noexcept {
+  if (__asan_InitDefine<op_delete_scalar_align>::defined) {
+    __asan_win_new_delete_data data{};
+    __asan_delete_array_align(&data, ptr, align);
+  } else {
+    operator delete(ptr, align);
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_nothrow_thunk.cpp
new file mode 100644
index 000000000000000..2e44eaf4cc4eade
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_array_nothrow_thunk.cpp
@@ -0,0 +1,39 @@
+//===-- asan_win_delete_array_nothrow_thunk.cc ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////////////////////
+// clang-format off
+// delete() Fallback Ordering
+//
+// +-------------+
+// |delete_scalar<----+-----------------------+
+// +--^----------+    |                       |
+//    |               |                       |
+// +--+---------+  +--+---------------+  +----+----------------+
+// |delete_array|  |delete_scalar_size|  |delete_scalar_nothrow|
+// +--^----^----+  +------------------+  +---------------------+
+//    |    |
+//    |    +-------------------+
+//    |                        |
+// +--+--------------+  +------+-------------+
+// |delete_array_size|  |DELETE_ARRAY_NOTHROW|
+// +-----------------+  +--------------------+
+// clang-format on
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete[](void* ptr, std::nothrow_t const&) noexcept {
+  // nothrow version is identical to throwing version
+  operator delete[](ptr);
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp
new file mode 100644
index 000000000000000..d27e2ebb83fd37d
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp
@@ -0,0 +1,49 @@
+//===-- asan_win_delete_array_size_align_thunk.cc -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+//////////////////////////////////////////////////////////////////////////////////
+// clang-format off
+// Aligned delete() Fallback Ordering
+//
+// +-------------------+
+// |delete_scalar_align<----+---------------------------+
+// +--^----------------+    |                           |
+//    |                     |                           |
+// +--+---------------+  +--+---------------------+  +--+------------------------+
+// |delete_array_align|  |delete_scalar_size_align|  |delete_scalar_align_nothrow|
+// +--^-----^---------+  +------------------------+  +---------------------------+
+//    |     |
+//    |     +------------------------+
+//    |                              |
+// +--+--------------------+  +------+-------------------+
+// |DELETE_ARRAY_SIZE_ALIGN|  |delete_array_align_nothrow|
+// +-----------------------+  +--------------------------+
+// clang-format on
+
+extern "C" void __cdecl __asan_delete_array_size_align(
+    __asan_win_new_delete_data* data, void* ptr, size_t size,
+    std::align_val_t align);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete[](void* ptr, size_t size,
+                       std::align_val_t align) noexcept {
+  if (__asan_InitDefine<op_delete_scalar_align>::defined &&
+      __asan_InitDefine<op_delete_array_align>::defined) {
+    __asan_win_new_delete_data data{};
+    __asan_delete_array_size_align(&data, ptr, size, align);
+  } else {
+    operator delete[](ptr, align);
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_size_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_size_thunk.cpp
new file mode 100644
index 000000000000000..0720b6337bc7a67
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_array_size_thunk.cpp
@@ -0,0 +1,47 @@
+//===-- asan_win_delete_array_size_thunk.cc -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////////////////////
+// clang-format off
+// delete() Fallback Ordering
+//
+// +-------------+
+// |delete_scalar<----+-----------------------+
+// +--^----------+    |                       |
+//    |               |                       |
+// +--+---------+  +--+---------------+  +----+----------------+
+// |delete_array|  |delete_scalar_size|  |delete_scalar_nothrow|
+// +--^----^----+  +------------------+  +---------------------+
+//    |    |
+//    |    +-------------------+
+//    |                        |
+// +--+--------------+  +------+-------------+
+// |DELETE_ARRAY_SIZE|  |delete_array_nothrow|
+// +-----------------+  +--------------------+
+// clang-format on
+
+extern "C" void __cdecl __asan_delete_array_size(
+    __asan_win_new_delete_data* data, void* ptr, size_t size);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete[](void* ptr, size_t size) noexcept {
+  if (__asan_InitDefine<op_delete_scalar>::defined &&
+      __asan_InitDefine<op_delete_array>::defined) {
+    __asan_win_new_delete_data data{};
+    __asan_delete_array_size(&data, ptr, size);
+  } else {
+    operator delete[](ptr);
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_thunk.cpp
new file mode 100644
index 000000000000000..02e8b7a5af80b64
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_array_thunk.cpp
@@ -0,0 +1,48 @@
+//===-- asan_win_delete_array_thunk.cc ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////////////////////
+// clang-format off
+// delete() Fallback Ordering
+//
+// +-------------+
+// |delete_scalar<----+-----------------------+
+// +--^----------+    |                       |
+//    |               |                       |
+// +--+---------+  +--+---------------+  +----+----------------+
+// |DELETE_ARRAY|  |delete_scalar_size|  |delete_scalar_nothrow|
+// +--^----^----+  +------------------+  +---------------------+
+//    |    |
+//    |    +-------------------+
+//    |                        |
+// +--+--------------+  +------+-------------+
+// |delete_array_size|  |delete_array_nothrow|
+// +-----------------+  +--------------------+
+// clang-format on
+
+__asan_InitDefine<op_delete_array> init_delete_array;
+
+extern "C" void __cdecl __asan_delete_array(__asan_win_new_delete_data* data,
+                                            void* ptr);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete[](void* ptr) noexcept {
+  if (__asan_InitDefine<op_delete_scalar>::defined) {
+    __asan_win_new_delete_data data{};
+    __asan_delete_array(&data, ptr);
+  } else {
+    operator delete(ptr);
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_align_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_align_nothrow_thunk.cpp
new file mode 100644
index 000000000000000..12f4f55f761fe9b
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_align_nothrow_thunk.cpp
@@ -0,0 +1,40 @@
+//===-- asan_win_delete_scalar_align_nothrow_thunk.cc ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+//////////////////////////////////////////////////////////////////////////////////
+// clang-format off
+// Aligned delete() Fallback Ordering
+//
+// +-------------------+
+// |delete_scalar_align<----+---------------------------+
+// +--^----------------+    |                           |
+//    |                     |                           |
+// +--+---------------+  +--+---------------------+  +--+------------------------+
+// |delete_array_align|  |delete_scalar_size_align|  |DELETE_SCALAR_ALIGN_NOTHROW|
+// +--^-----^---------+  +------------------------+  +---------------------------+
+//    |     |
+//    |     +------------------------+
+//    |                              |
+// +--+--------------------+  +------+-------------------+
+// |delete_array_size_align|  |delete_array_align_nothrow|
+// +-----------------------+  +--------------------------+
+// clang-format on
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete(void* ptr, std::align_val_t align,
+                     std::nothrow_t const&) noexcept {
+  // nothrow version is identical to throwing version
+  operator delete(ptr, align);
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_align_thunk.cpp
new file mode 100644
index 000000000000000..b9a53963fc6d711
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_align_thunk.cpp
@@ -0,0 +1,44 @@
+//===-- asan_win_delete_scalar_align_thunk.cc -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+//////////////////////////////////////////////////////////////////////////////////
+// clang-format off
+// Aligned delete() Fallback Ordering
+//
+// +-------------------+
+// |DELETE_SCALAR_ALIGN<----+---------------------------+
+// +--^----------------+    |                           |
+//    |                     |                           |
+// +--+---------------+  +--+---------------------+  +--+------------------------+
+// |delete_array_align|  |delete_scalar_size_align|  |delete_scalar_align_nothrow|
+// +--^-----^---------+  +------------------------+  +---------------------------+
+//    |     |
+//    |     +------------------------+
+//    |                              |
+// +--+--------------------+  +------+-------------------+
+// |delete_array_size_align|  |delete_array_align_nothrow|
+// +-----------------------+  +--------------------------+
+// clang-format on
+
+__asan_InitDefine<op_delete_scalar_align> init_delete_scalar_align;
+
+extern "C" void __cdecl __asan_delete_align(__asan_win_new_delete_data* data,
+                                            void* ptr, std::align_val_t align);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete(void* ptr, std::align_val_t align) noexcept {
+  __asan_win_new_delete_data data{};
+  __asan_delete_align(&data, ptr, align);
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_nothrow_thunk.cpp
new file mode 100644
index 000000000000000..44a96a2f5b2cfac
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_nothrow_thunk.cpp
@@ -0,0 +1,39 @@
+//===-- asan_win_delete_scalar_nothrow_thunk.cc ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////////////////////
+// clang-format off
+// delete() Fallback Ordering
+//
+// +-------------+
+// |delete_scalar<----+-----------------------+
+// +--^----------+    |                       |
+//    |               |                       |
+// +--+---------+  +--+---------------+  +----+----------------+
+// |delete_array|  |delete_scalar_size|  |DELETE_SCALAR_NOTHROW|
+// +--^----^----+  +------------------+  +---------------------+
+//    |    |
+//    |    +-------------------+
+//    |                        |
+// +--+--------------+  +------+-------------+
+// |delete_array_size|  |delete_array_nothrow|
+// +-----------------+  +--------------------+
+// clang-format on
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete(void* ptr, std::nothrow_t const&) noexcept {
+  // nothrow version is identical to throwing version
+  operator delete(ptr);
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp
new file mode 100644
index 000000000000000..6bcc00f4f12a5da
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp
@@ -0,0 +1,47 @@
+//===-- asan_win_delete_scalar_size_align_thunk.cc ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+//////////////////////////////////////////////////////////////////////////////////
+// clang-format off
+// Aligned delete() Fallback Ordering
+//
+// +-------------------+
+// |delete_scalar_align<----+---------------------------+
+// +--^----------------+    |                           |
+//    |                     |                           |
+// +--+---------------+  +--+---------------------+  +--+------------------------+
+// |delete_array_align|  |DELETE_SCALAR_SIZE_ALIGN|  |delete_scalar_align_nothrow|
+// +--^-----^---------+  +------------------------+  +---------------------------+
+//    |     |
+//    |     +------------------------+
+//    |                              |
+// +--+--------------------+  +------+-------------------+
+// |delete_array_size_align|  |delete_array_align_nothrow|
+// +-----------------------+  +--------------------------+
+// clang-format on
+
+extern "C" void __cdecl __asan_delete_size_align(
+    __asan_win_new_delete_data* data, void* ptr, size_t size,
+    std::align_val_t align) noexcept;
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete(void* ptr, size_t size, std::align_val_t align) noexcept {
+  if (__asan_InitDefine<op_delete_scalar_align>::defined) {
+    __asan_win_new_delete_data data{};
+    __asan_delete_size_align(&data, ptr, size, align);
+  } else {
+    operator delete(ptr, align);
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_size_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_size_thunk.cpp
new file mode 100644
index 000000000000000..31e2846995e6321
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_size_thunk.cpp
@@ -0,0 +1,46 @@
+//===-- asan_win_delete_scalar_size_thunk.cc ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////////////////////
+// clang-format off
+// delete() Fallback Ordering
+//
+// +-------------+
+// |delete_scalar<----+-----------------------+
+// +--^----------+    |                       |
+//    |               |                       |
+// +--+---------+  +--+---------------+  +----+----------------+
+// |delete_array|  |DELETE_SCALAR_SIZE|  |delete_scalar_nothrow|
+// +--^----^----+  +------------------+  +---------------------+
+//    |    |
+//    |    +-------------------+
+//    |                        |
+// +--+--------------+  +------+-------------+
+// |delete_array_size|  |delete_array_nothrow|
+// +-----------------+  +--------------------+
+// clang-format on
+
+extern "C" void __cdecl __asan_delete_size(__asan_win_new_delete_data* data,
+                                           void* ptr, size_t size);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete(void* ptr, size_t size) noexcept {
+  if (__asan_InitDefine<op_delete_scalar>::defined) {
+    __asan_win_new_delete_data data{};
+    __asan_delete_size(&data, ptr, size);
+  } else {
+    operator delete(ptr);
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp
new file mode 100644
index 000000000000000..38d3899816b0486
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp
@@ -0,0 +1,44 @@
+//===-- asan_win_delete_scalar_thunk.cc -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////////////////////
+// clang-format off
+// delete() Fallback Ordering
+//
+// +-------------+
+// |DELETE_SCALAR<----+-----------------------+
+// +--^----------+    |                       |
+//    |               |                       |
+// +--+---------+  +--+---------------+  +----+----------------+
+// |delete_array|  |delete_scalar_size|  |delete_scalar_nothrow|
+// +--^----^----+  +------------------+  +---------------------+
+//    |    |
+//    |    +-------------------+
+//    |                        |
+// +--+--------------+  +------+-------------+
+// |delete_array_size|  |delete_array_nothrow|
+// +-----------------+  +--------------------+
+// clang-format on
+
+__asan_InitDefine<op_delete_scalar> init_delete_scalar;
+
+extern "C" void __cdecl __asan_delete(__asan_win_new_delete_data* data,
+                                      void* ptr);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void operator delete(void* ptr) noexcept {
+  __asan_win_new_delete_data data{};
+  __asan_delete(&data, ptr);
+}
diff --git a/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp
new file mode 100644
index 000000000000000..bf8bc78ec4206a3
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp
@@ -0,0 +1,50 @@
+//===-- asan_win_new_array_align_nothrow_thunk.cc -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////
+// clang-format off
+// Aligned new() Fallback Ordering
+//
+// +----------------+
+// |new_scalar_align<--------------+
+// +----^-----------+              |
+//      |                          |
+// +----+-------------------+  +---+-----------+
+// |new_scalar_align_nothrow|  |new_array_align|
+// +------------------------+  +---^-----------+
+//                                 |
+//                     +-----------+-----------+
+//                     |NEW_ARRAY_ALIGN_NOTHROW|
+//                     +-----------------------+
+// clang-format on
+
+extern "C" void* __cdecl __asan_new_array_align_nothrow(
+    __asan_win_new_delete_data* data, size_t size, std::align_val_t align);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void* operator new[](size_t size, std::align_val_t align,
+                     std::nothrow_t const&) noexcept {
+  if (__asan_InitDefine<op_new_scalar_align>::defined &&
+      __asan_InitDefine<op_new_array_align>::defined) {
+    __asan_win_new_delete_data data{};
+    return __asan_new_array_align_nothrow(&data, size, align);
+  }
+
+  try {
+    return operator new[](size, align);
+  } catch (...) {
+    return nullptr;
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp
new file mode 100644
index 000000000000000..faa39b2a008b0d7
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp
@@ -0,0 +1,46 @@
+//===-- asan_win_new_array_align_thunk.cc ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////
+// clang-format off
+// Aligned new() Fallback Ordering
+//
+// +----------------+
+// |new_scalar_align<--------------+
+// +----^-----------+              |
+//      |                          |
+// +----+-------------------+  +---+-----------+
+// |new_scalar_align_nothrow|  |NEW_ARRAY_ALIGN|
+// +------------------------+  +---^-----------+
+//                                 |
+//                     +-----------+-----------+
+//                     |new_array_align_nothrow|
+//                     +-----------------------+
+// clang-format on
+
+__asan_InitDefine<op_new_array_align> init_new_array_align;
+
+extern "C" void* __cdecl __asan_new_array_align(
+    __asan_win_new_delete_data* data, size_t size, std::align_val_t align);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void* operator new[](size_t size, std::align_val_t align) {
+  if (__asan_InitDefine<op_new_scalar_align>::defined) {
+    __asan_win_new_delete_data data{};
+    return __asan_new_array_align(&data, size, align);
+  }
+
+  return operator new(size, align);
+}
diff --git a/compiler-rt/lib/asan/asan_win_new_array_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_nothrow_thunk.cpp
new file mode 100644
index 000000000000000..526e9abf54d1e0d
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_array_nothrow_thunk.cpp
@@ -0,0 +1,49 @@
+//===-- asan_win_new_array_nothrow_thunk.cc -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////
+// clang-format off
+// new() Fallback Ordering
+//
+// +----------+
+// |new_scalar<---------------+
+// +----^-----+               |
+//      |                     |
+// +----+-------------+  +----+----+
+// |new_scalar_nothrow|  |new_array|
+// +------------------+  +----^----+
+//                            |
+//               +------------+----+
+//               |NEW_ARRAY_NOTHROW|
+//               +-----------------+
+// clang-format on
+
+extern "C" void* __cdecl __asan_new_array_nothrow(
+    __asan_win_new_delete_data* data, size_t size);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void* operator new[](size_t size, std::nothrow_t const&) noexcept {
+  if (__asan_InitDefine<op_new_scalar>::defined &&
+      __asan_InitDefine<op_new_array>::defined) {
+    __asan_win_new_delete_data data{};
+    return __asan_new_array_nothrow(&data, size);
+  }
+
+  try {
+    return operator new[](size);
+  } catch (...) {
+    return nullptr;
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp
new file mode 100644
index 000000000000000..b848e343f81b845
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp
@@ -0,0 +1,45 @@
+//===-- asan_win_new_array_thunk.cc ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////
+// clang-format off
+// new() Fallback Ordering
+//
+// +----------+
+// |new_scalar<---------------+
+// +----^-----+               |
+//      |                     |
+// +----+-------------+  +----+----+
+// |new_scalar_nothrow|  |NEW_ARRAY|
+// +------------------+  +----^----+
+//                            |
+//               +------------+----+
+//               |new_array_nothrow|
+//               +-----------------+
+// clang-format on
+
+__asan_InitDefine<op_new_array> init_new_array;
+
+extern "C" void* __cdecl __asan_new_array(__asan_win_new_delete_data* data,
+                                          size_t size);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void* operator new[](size_t size) {
+  if (__asan_InitDefine<op_new_scalar>::defined) {
+    __asan_win_new_delete_data data{};
+    return __asan_new_array(&data, size);
+  }
+  return operator new(size);
+}
diff --git a/compiler-rt/lib/asan/asan_win_new_delete.cpp b/compiler-rt/lib/asan/asan_win_new_delete.cpp
new file mode 100644
index 000000000000000..c4de9159d5b0cbc
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_delete.cpp
@@ -0,0 +1,160 @@
+//===-- asan_win_new_delete.cc --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include <stddef.h>
+
+#include "asan_allocator.h"
+#include "asan_internal.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+
+// Fake std::align_val_t to avoid including <new>.
+namespace std {
+enum class align_val_t : size_t {};
+}
+
+using namespace __asan;
+
+struct __asan_win_new_delete_data {
+  size_t size;        // Size of this struct (it travels over the DLL boundary).
+  int extra_context;  // Number of extra frames we need to collect in the
+                      // backtrace.
+  __sanitizer::uptr pc;
+  __sanitizer::uptr bp;
+  __sanitizer::uptr caller_pc;
+};
+
+#define OPERATOR_NEW_BODY(type, nothrow)                          \
+  GET_STACK_TRACE_MALLOC_WIN(data->pc, data->bp, data->caller_pc, \
+                             data->extra_context);                \
+  void *res = asan_memalign(0, size, &stack, type);               \
+  if (!nothrow && UNLIKELY(!res))                                 \
+    ReportOutOfMemory(size, &stack);                              \
+  return res;
+
+#define OPERATOR_NEW_BODY_ALIGN(type, nothrow)                    \
+  GET_STACK_TRACE_MALLOC_WIN(data->pc, data->bp, data->caller_pc, \
+                             data->extra_context);                \
+  void *res = asan_memalign((uptr)align, size, &stack, type);     \
+  if (!nothrow && UNLIKELY(!res))                                 \
+    ReportOutOfMemory(size, &stack);                              \
+  return res;
+
+#define OPERATOR_DELETE_BODY(type)                              \
+  GET_STACK_TRACE_FREE_WIN(data->pc, data->bp, data->caller_pc, \
+                           data->extra_context);                \
+  asan_delete(ptr, 0, 0, &stack, type);
+
+#define OPERATOR_DELETE_BODY_SIZE(type)                         \
+  GET_STACK_TRACE_FREE_WIN(data->pc, data->bp, data->caller_pc, \
+                           data->extra_context);                \
+  asan_delete(ptr, size, 0, &stack, type);
+
+#define OPERATOR_DELETE_BODY_ALIGN(type)                        \
+  GET_STACK_TRACE_FREE_WIN(data->pc, data->bp, data->caller_pc, \
+                           data->extra_context);                \
+  asan_delete(ptr, 0, static_cast<uptr>(align), &stack, type);
+
+#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type)                   \
+  GET_STACK_TRACE_FREE_WIN(data->pc, data->bp, data->caller_pc, \
+                           data->extra_context);                \
+  asan_delete(ptr, size, static_cast<uptr>(align), &stack, type);
+
+extern "C" {
+__declspec(dllexport) void *__cdecl __asan_new(
+    __asan_win_new_delete_data *const data, size_t const size) {
+  OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
+}
+
+__declspec(dllexport) void *__cdecl __asan_new_array(
+    __asan_win_new_delete_data *const data, size_t const size) {
+  OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
+}
+
+__declspec(dllexport) void *__cdecl __asan_new_nothrow(
+    __asan_win_new_delete_data *const data, size_t const size) {
+  OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
+}
+
+__declspec(dllexport) void *__cdecl __asan_new_array_nothrow(
+    __asan_win_new_delete_data *const data, size_t const size) {
+  OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
+}
+
+__declspec(dllexport) void *__cdecl __asan_new_align(
+    __asan_win_new_delete_data *const data, size_t const size,
+    std::align_val_t const align) {
+  OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/);
+}
+
+__declspec(dllexport) void *__cdecl __asan_new_array_align(
+    __asan_win_new_delete_data *const data, size_t const size,
+    std::align_val_t const align) {
+  OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/);
+}
+
+__declspec(dllexport) void *__cdecl __asan_new_align_nothrow(
+    __asan_win_new_delete_data *const data, size_t const size,
+    std::align_val_t const align) {
+  OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/);
+}
+
+__declspec(dllexport) void *__cdecl __asan_new_array_align_nothrow(
+    __asan_win_new_delete_data *const data, size_t const size,
+    std::align_val_t const align) {
+  OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/);
+}
+
+__declspec(dllexport) void __cdecl __asan_delete(
+    __asan_win_new_delete_data *const data, void *ptr) {
+  OPERATOR_DELETE_BODY(FROM_NEW);
+}
+
+__declspec(dllexport) void __cdecl __asan_delete_array(
+    __asan_win_new_delete_data *const data, void *ptr) {
+  OPERATOR_DELETE_BODY(FROM_NEW_BR);
+}
+
+__declspec(dllexport) void __cdecl __asan_delete_size(
+    __asan_win_new_delete_data *const data, void *ptr, size_t const size) {
+  OPERATOR_DELETE_BODY_SIZE(FROM_NEW);
+}
+
+__declspec(dllexport) void __cdecl __asan_delete_array_size(
+    __asan_win_new_delete_data *const data, void *ptr, size_t const size) {
+  OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR);
+}
+
+__declspec(dllexport) void __cdecl __asan_delete_align(
+    __asan_win_new_delete_data *const data, void *ptr,
+    std::align_val_t const align) {
+  OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
+}
+
+__declspec(dllexport) void __cdecl __asan_delete_array_align(
+    __asan_win_new_delete_data *const data, void *ptr,
+    std::align_val_t const align) {
+  OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
+}
+
+__declspec(dllexport) void __cdecl __asan_delete_size_align(
+    __asan_win_new_delete_data *const data, void *ptr, size_t const size,
+    std::align_val_t const align) {
+  OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW);
+}
+
+__declspec(dllexport) void __cdecl __asan_delete_array_size_align(
+    __asan_win_new_delete_data *const data, void *ptr, size_t const size,
+    std::align_val_t const align) {
+  OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR);
+}
+}  // extern "C"
diff --git a/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
new file mode 100644
index 000000000000000..1502c04b611df38
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
@@ -0,0 +1,99 @@
+//===-- asan_win_new_delete_thunk_common.h ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//
+// In order to provide correct fallback behavior for operator new and delete, we
+// need to honor partially hooked new and delete operators. For example, if
+// plain operator new is provided by the user, then array operator new should
+// fallback to use that operator new. This is slighly complicated in that ASAN
+// must know which operator new/delete was used to correctly track allocations.
+// The solution here is to only pass the allocation/deallocation request
+// directly to ASAN with full metadata when we know all fallbacks for the given
+// overload are provided by ASAN. This requires us to detect which overloads are
+// provided by ASAN. We can accomplish this by seperating the definitions into
+// multiple TUs so each can be selected individually, and adding a dynamic
+// initializer to those TUs to mark whether that overload is included.
+//===----------------------------------------------------------------------===//
+
+#include "asan_win_thunk_common.h"
+// Fake std::nothrow_t and std::align_val_t to avoid including <new>.
+namespace std {
+struct nothrow_t {};
+enum class align_val_t : size_t {};
+}  // namespace std
+
+void* operator new(size_t, std::align_val_t);
+void* operator new[](size_t, std::align_val_t);
+void operator delete(void* ptr, std::align_val_t align);
+void operator delete[](void* ptr, std::align_val_t align);
+
+using __asan_win_new_delete_data = __asan_win_stack_data;
+
+////////////////////////////////////
+// clang-format off
+// Fallback Ordering for new/delete
+//
+// +----------+                                                     +----------------+
+// |new_scalar<---------------+                                     |new_scalar_align<--------------+
+// +----^-----+               |                                     +----^-----------+              |
+//      |                     |                                          |                          |
+// +----+-------------+  +----+----+                                +----+-------------------+  +---+-----------+
+// |new_scalar_nothrow|  |new_array|                                |new_scalar_align_nothrow|  |new_array_align|
+// +------------------+  +----^----+                                +------------------------+  +---^-----------+
+//                            |                                                                     |
+//               +------------+----+                                                    +-----------+-----------+
+//               |new_array_nothrow|                                                    |new_array_align_nothrow|
+//               +-----------------+                                                    +-----------------------+
+//
+// +-------------+                                                  +-------------------+
+// |delete_scalar<----+-----------------------+                     |delete_scalar_align<----+---------------------------+
+// +--^----------+    |                       |                     +--^----------------+    |                           |
+//    |               |                       |                        |                     |                           |
+// +--+---------+  +--+---------------+  +----+----------------+    +--+---------------+  +--+---------------------+  +--+------------------------+
+// |delete_array|  |delete_scalar_size|  |delete_scalar_nothrow|    |delete_array_align|  |delete_scalar_size_align|  |delete_scalar_align_nothrow|
+// +--^----^----+  +------------------+  +---------------------+    +--^-----^---------+  +------------------------+  +---------------------------+
+//    |    |                                                           |     |
+//    |    +-------------------+                                       |     +------------------------+
+//    |                        |                                       |                              |
+// +--+--------------+  +------+-------------+                      +--+--------------------+  +------+-------------------+
+// |delete_array_size|  |delete_array_nothrow|                      |delete_array_size_align|  |delete_array_align_nothrow|
+// +-----------------+  +--------------------+                      +-----------------------+  +--------------------------+
+// clang-format on
+
+// Only need definition detection for overloads with children.
+enum defined_ops {
+  op_new_scalar,
+  op_new_array,
+
+  op_new_scalar_align,
+  op_new_array_align,
+
+  op_delete_scalar,
+  op_delete_array,
+
+  op_delete_scalar_align,
+  op_delete_array_align
+};
+
+// Define a global of this type in each overload's translation unit
+// so that the dynamic initializer will set defined to 1 when
+// that TU is included.
+// We can then use __asan_InitDefine<op>::defined to check whether that TU is
+// included.
+template <defined_ops Id>
+struct __asan_InitDefine {
+  __asan_InitDefine() { defined = 1; }
+
+  static int defined;
+};
+
+template <defined_ops Id>
+int __asan_InitDefine<Id>::defined = 0;
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
new file mode 100644
index 000000000000000..a6ae7c6890667f4
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
@@ -0,0 +1,49 @@
+//===-- asan_win_new_scalar_align_nothrow_thunk.cc ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////
+// clang-format off
+// Aligned new() Fallback Ordering
+//
+// +----------------+
+// |new_scalar_align<--------------+
+// +----^-----------+              |
+//      |                          |
+// +----+-------------------+  +---+-----------+
+// |NEW_SCALAR_ALIGN_NOTHROW|  |new_array_align|
+// +------------------------+  +---^-----------+
+//                                 |
+//                     +-----------+-----------+
+//                     |new_array_align_nothrow|
+//                     +-----------------------+
+// clang-format on
+
+extern "C" void* __cdecl __asan_new_align_nothrow(
+    __asan_win_new_delete_data* data, size_t size, std::align_val_t align);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void* operator new(size_t size, std::align_val_t align,
+                   std::nothrow_t const&) noexcept {
+  if (__asan_InitDefine<op_new_scalar_align>::defined) {
+    __asan_win_new_delete_data data{};
+    return __asan_new_align_nothrow(&data, size, align);
+  }
+
+  try {
+    return operator new(size, align);
+  } catch (...) {
+    return nullptr;
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp
new file mode 100644
index 000000000000000..dfffb956657c69e
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp
@@ -0,0 +1,42 @@
+//===-- asan_win_new_scalar_align_thunk.cc --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////////////////
+// clang-format off
+// Aligned new() Fallback Ordering
+//
+// +----------------+
+// |NEW_SCALAR_ALIGN<--------------+
+// +----^-----------+              |
+//      |                          |
+// +----+-------------------+  +---+-----------+
+// |new_scalar_align_nothrow|  |new_array_align|
+// +------------------------+  +---^-----------+
+//                                 |
+//                     +-----------+-----------+
+//                     |new_array_align_nothrow|
+//                     +-----------------------+
+// clang-format on
+
+__asan_InitDefine<op_new_scalar_align> init_new_scalar_align;
+
+extern "C" void* __cdecl __asan_new_align(__asan_win_new_delete_data* data,
+                                          size_t size, std::align_val_t align);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void* operator new(size_t size, std::align_val_t align) {
+  __asan_win_new_delete_data data{};
+  return __asan_new_align(&data, size, align);
+}
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp
new file mode 100644
index 000000000000000..53306d435a75ac3
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp
@@ -0,0 +1,48 @@
+//===-- asan_win_new_scalar_nothrow_thunk.cc ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////
+// clang-format off
+// new() Fallback Ordering
+//
+// +----------+
+// |new_scalar<---------------+
+// +----^-----+               |
+//      |                     |
+// +----+-------------+  +----+----+
+// |NEW_SCALAR_NOTHROW|  |new_array|
+// +------------------+  +----^----+
+//                            |
+//               +------------+----+
+//               |new_array_nothrow|
+//               +-----------------+
+// clang-format on
+
+extern "C" void* __cdecl __asan_new_nothrow(__asan_win_new_delete_data* data,
+                                            size_t size);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void* operator new(size_t size, std::nothrow_t const&) noexcept {
+  if (__asan_InitDefine<op_new_scalar>::defined) {
+    __asan_win_new_delete_data data{};
+    return __asan_new_nothrow(&data, size);
+  }
+
+  try {
+    return operator new(size);
+  } catch (...) {
+    return nullptr;
+  }
+}
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp
new file mode 100644
index 000000000000000..47d9fa84ce55124
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp
@@ -0,0 +1,42 @@
+//===-- asan_win_new_scalar_thunk.cc --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific user-provided new/delete operator detection and fallback.
+//===----------------------------------------------------------------------===//
+#include "asan_win_new_delete_thunk_common.h"
+
+////////////////////////////////////
+// clang-format off
+// new() Fallback Ordering
+//
+// +----------+
+// |NEW_SCALAR|<---------------+
+// +----^-----+               |
+//      |                     |
+// +----+-------------+  +----+----+
+// |new_scalar_nothrow|  |new_array|
+// +------------------+  +----^----+
+//                            |
+//               +------------+----+
+//               |new_array_nothrow|
+//               +-----------------+
+// clang-format on
+
+__asan_InitDefine<op_new_scalar> init_new_scalar;
+
+extern "C" void* __cdecl __asan_new(__asan_win_new_delete_data* data,
+                                    size_t size);
+
+// Avoid tailcall optimization to preserve stack frame.
+#pragma optimize("", off)
+void* operator new(size_t size) {
+  __asan_win_new_delete_data data{};
+  return __asan_new(&data, size);
+}
diff --git a/compiler-rt/lib/asan/asan_win_thunk_common.h b/compiler-rt/lib/asan/asan_win_thunk_common.h
new file mode 100644
index 000000000000000..49d17a74e367865
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_win_thunk_common.h
@@ -0,0 +1,64 @@
+//===-- asan_win_thunk_common.h  --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific common utilities to communicate between static and DLL
+// portions of the ASAN runtime.
+//
+// This file must not include any core components of the ASAN runtime as it must
+// be able to be included in the portions statically linked with the user
+// program.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+namespace __sanitizer {
+#if defined(_WIN64)
+typedef unsigned long long uptr;
+#else
+typedef unsigned long uptr;
+#endif
+}  // namespace __sanitizer
+
+extern "C" void* _ReturnAddress(void);
+extern "C" void* _AddressOfReturnAddress(void);
+#pragma intrinsic(_ReturnAddress)
+#pragma intrinsic(_AddressOfReturnAddress)
+
+#define GET_CALLER_PC() (__sanitizer::uptr) _ReturnAddress()
+#define GET_CURRENT_FRAME() \
+  (((__sanitizer::uptr)_AddressOfReturnAddress()) + sizeof(__sanitizer::uptr))
+
+__declspec(noinline) inline __sanitizer::uptr __asan_GetCurrentPc() {
+  return GET_CALLER_PC();
+}
+
+struct __asan_win_stack_data {
+  // Put calls to get pc, bp, and caller_pc in ctor arguments so they occur in
+  // the calling frame and don't rely on inlining to get correct stack
+  // information.
+  __forceinline explicit __asan_win_stack_data(
+      __sanitizer::uptr pc_arg = __asan_GetCurrentPc(),
+      __sanitizer::uptr bp_arg = GET_CURRENT_FRAME(),
+      __sanitizer::uptr caller_pc_arg = GET_CALLER_PC())
+      : size(sizeof(__asan_win_stack_data)),
+        extra_context(2),  // TODO: Should only need one - investigate why we
+                           // need an extra frame.
+        pc(pc_arg),
+        bp(bp_arg),
+        caller_pc(caller_pc_arg) {}
+
+  size_t size;        // Size of this struct (it travels over the DLL boundary).
+  int extra_context;  // Number of extra frames we need to collect in the
+                      // backtrace.
+  __sanitizer::uptr pc;
+  __sanitizer::uptr bp;
+  __sanitizer::uptr caller_pc;
+};
diff --git a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp
new file mode 100644
index 000000000000000..dbb789cc075861c
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cl_asan -Od %s -Fe%t
+// RUN: %run %t
+
+// test fixing new/delete already defined
+// as long as it finishes linking, it should be good
+
+// before fix:
+// nafxcw.lib(afxmem.obj) : warning LNK4006: "void * __cdecl operator new(unsigned int)" (??2 at YAPAXI@Z) already defined in clang_rt.asan_cxx-i386.lib(asan_win_new_scalar_thunk.cpp.obj); second definition ignored
+// nafxcw.lib(afxmem.obj) : warning LNK4006: "void __cdecl operator delete(void *)" (??3 at YAXPAX@Z) already defined in clang_rt.asan_cxx-i386.lib(asan_win_delete_scalar_thunk.cpp.obj); second definition ignored
+
+#ifdef _DLL
+#define _AFXDLL
+#endif
+
+#include "afxglobals.h"
+
+int AFX_CDECL AfxCriticalNewHandler(size_t nSize);
+
+int main(int argc, char* argv) {
+    AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
+    _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
+    AfxSetNewHandler(pnhOldHandler);
+    puts("Pass");
+    return 0;
+}
\ No newline at end of file
diff --git a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp
new file mode 100644
index 000000000000000..b3b5fffc999ae16
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cl_asan -Od %s -Fe%t /link /WX
+// RUN: %env_asan_opts=alloc_dealloc_mismatch=true %run %t
+
+// test fixing new already defined and mismatch between allocation and deallocation APis
+
+// before fix:
+// nafxcwd.lib(afx_new_scalar.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2 at YAPAXI@Z) already defined in clang_rt.asan_cxx_dbg-i386.lib(asan_win_new_scalar_thunk.cpp.obj)
+// Address Sanitizer error: mismatch between allocation and deallocation APis
+
+#ifdef _DLL
+#define _AFXDLL
+#endif
+
+#include <SDKDDKVer.h>
+#include <afxglobals.h>
+
+int main() {
+    int * normal = new int;
+    int * debug = DEBUG_NEW int;
+
+    delete normal;
+    delete debug;
+
+    return 0;
+}
\ No newline at end of file
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cpp
index cad28ae8ace213a..06a8939b3a2a04f 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cpp
@@ -6,7 +6,11 @@ struct C {
   ~C() {}
 };
 
+#ifdef _MSC_VER
+__declspec(noinline) int hide(int x) { return x; }
+#else
 int __attribute__((noinline, optnone)) hide(int x) { return x; }
+#endif
 
 int main() {
   C *buffer = new C[42];
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_array.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_array.cpp
new file mode 100644
index 000000000000000..211b24c680b65df
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_array.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cl_asan /EHsc /Od /std:c++17 %s -Fe%t
+// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %clang_cl_asan /EHsc /Od %p/dll_host.cpp -Fe%t
+// RUN: %clang_cl_asan /EHsc /LD /Od /std:c++17 /DTEST_DLL %s -Fe%t.dll
+// RUN: %run %t %t.dll 2>&1 | FileCheck %s
+
+#include "operator_new_delete_replacement_macros.h"
+#define DEFINED_REPLACEMENTS (ALL_NEW | ALL_ALIGNED_NEW | SCALAR_DELETE | ARRAY_DELETE | SCALAR_ALIGNED_DELETE | ARRAY_ALIGNED_DELETE)
+#include "operator_new_delete_replacement_common.h"
+
+// Covers:
+// 12. sized array (asan)              -> array (custom)
+// 14. array nothrow (asan)            -> array (custom)
+// 19. aligned sized array (asan)      -> aligned array (custom)
+// 21. aligned array nothrow (asan)    -> aligned array (custom)
+
+// CHECK: new_scalar
+// CHECK: new_array
+// CHECK: new_scalar_nothrow
+// CHECK: new_array_nothrow
+// CHECK: delete_scalar
+// CHECK: delete_array
+// CHECK: delete_scalar
+// CHECK: delete_array
+// CHECK: new_scalar
+// CHECK: new_array
+// CHECK: delete_scalar
+// CHECK: delete_array
+
+// CHECK: new_scalar_align
+// CHECK: new_array_align
+// CHECK: new_scalar_align_nothrow
+// CHECK: new_array_align_nothrow
+// CHECK: delete_scalar_align
+// CHECK: delete_array_align
+// CHECK: delete_scalar_align
+// CHECK: delete_array_align
+// CHECK: new_scalar_align
+// CHECK: new_array_align
+// CHECK: delete_scalar_align
+// CHECK: delete_array_align
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_scalar.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_scalar.cpp
new file mode 100644
index 000000000000000..355d0030499c988
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_scalar.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cl_asan  /EHsc /Od /std:c++17 %s -Fe%t
+// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %clang_cl_asan /EHsc /Od %p/dll_host.cpp -Fe%t
+// RUN: %clang_cl_asan /EHsc /LD /Od /std:c++17 /DTEST_DLL %s -Fe%t.dll
+// RUN: %run %t %t.dll 2>&1 | FileCheck %s
+
+#include "operator_new_delete_replacement_macros.h"
+#define DEFINED_REPLACEMENTS (ALL_NEW | ALL_ALIGNED_NEW | SCALAR_DELETE | SCALAR_ALIGNED_DELETE)
+#include "operator_new_delete_replacement_common.h"
+
+// Covers:
+// 9.  array (asan)                    -> scalar (custom)
+// 10. nothrow (asan)                  -> scalar (custom)
+// 11. sized (asan)                    -> scalar (custom) ** original bug report scenario **
+// 13. sized array (asan)              -> array (asan)            -> scalar (custom)
+// 15. array nothrow (asan)            -> array (asan)            -> scalar (custom)
+// 16. aligned array (asan)            -> aligned scalar (custom)
+// 17. aligned nothrow (asan)          -> aligned scalar (custom)
+// 18. aligned sized (asan)            -> aligned scalar (custom)
+// 20. aligned sized array (asan)      -> aligned array (asan)    -> aligned scalar (custom)
+// 22. aligned array nothrow (asan)    -> aligned array (asan)    -> aligned scalar (custom)
+
+// CHECK: new_scalar
+// CHECK: new_array
+// CHECK: new_scalar_nothrow
+// CHECK: new_array_nothrow
+// CHECK: delete_scalar
+// CHECK: delete_scalar
+// CHECK: delete_scalar
+// CHECK: delete_scalar
+// CHECK: new_scalar
+// CHECK: new_array
+// CHECK: delete_scalar
+// CHECK: delete_scalar
+
+// CHECK: new_scalar_align
+// CHECK: new_array_align
+// CHECK: new_scalar_align_nothrow
+// CHECK: new_array_align_nothrow
+// CHECK: delete_scalar_align
+// CHECK: delete_scalar_align
+// CHECK: delete_scalar_align
+// CHECK: delete_scalar_align
+// CHECK: new_scalar_align
+// CHECK: new_array_align
+// CHECK: delete_scalar_align
+// CHECK: delete_scalar_align
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_all.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_all.cpp
new file mode 100644
index 000000000000000..9c343e55cdd1865
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_all.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cl_asan /EHsc /Od /std:c++17 %s -Fe%t
+// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %clang_cl_asan /EHsc /Od %p/dll_host.cpp -Fe%t
+// RUN: %clang_cl_asan /EHsc /LD /Od /std:c++17 /DTEST_DLL %s -Fe%t.dll
+// RUN: %run %t %t.dll 2>&1 | FileCheck %s
+
+#include "operator_new_delete_replacement_macros.h"
+#define DEFINED_REPLACEMENTS ALL_OPERATORS
+#include "operator_new_delete_replacement_common.h"
+
+// CHECK: new_scalar
+// CHECK: new_array
+// CHECK: new_scalar_nothrow
+// CHECK: new_array_nothrow
+// CHECK: delete_scalar
+// CHECK: delete_array
+// CHECK: delete_scalar_nothrow
+// CHECK: delete_array_nothrow
+// CHECK: new_scalar
+// CHECK: new_array
+// CHECK: delete_scalar_size
+// CHECK: delete_array_size
+
+// CHECK: new_scalar_align
+// CHECK: new_array_align
+// CHECK: new_scalar_align_nothrow
+// CHECK: new_array_align_nothrow
+// CHECK: delete_scalar_align
+// CHECK: delete_array_align
+// CHECK: delete_scalar_align_nothrow
+// CHECK: delete_array_align_nothrow
+// CHECK: new_scalar_align
+// CHECK: new_array_align
+// CHECK: delete_scalar_size_align
+// CHECK: delete_array_size_align
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_common.h b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_common.h
new file mode 100644
index 000000000000000..07493747a04b28b
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_common.h
@@ -0,0 +1,403 @@
+#include <new>
+#include <stdio.h>
+
+// If users provide fallback, all parents must be replaced as well.
+// That is, you can't sanely provide a non-forwarding array op new without also replacing scalar op new.
+
+// With that in mind, we need to cover the following scenarios for operator new:
+// 1. array (asan)                    -> scalar (custom)
+// 2. nothrow (asan)                  -> scalar (custom)
+// 3. array nothrow (asan)            -> array  (custom)
+// 4. array nothrow (asan)            -> array  (asan)           -> scalar (custom)
+// 5. aligned array (asan)            -> aligned scalar (custom)
+// 6. aligned nothrow (asan)          -> aligned scalar (custom)
+// 7. aligned array nothrow (asan)    -> aligned array  (custom)
+// 8. aligned array nothrow (asan)    -> aligned array  (asan)   -> aligned scalar (custom)
+
+// And the following for operator delete:
+// 9.  array (asan)                    -> scalar (custom)
+// 10. nothrow (asan)                  -> scalar (custom)
+// 11. sized (asan)                    -> scalar (custom) ** original bug report scenario **
+// 12. sized array (asan)              -> array (custom)
+// 13. sized array (asan)              -> array (asan)            -> scalar (custom)
+// 14. array nothrow (asan)            -> array (custom)
+// 15. array nothrow (asan)            -> array (asan)            -> scalar (custom)
+// 16. aligned array (asan)            -> aligned scalar (custom)
+// 17. aligned nothrow (asan)          -> aligned scalar (custom)
+// 18. aligned sized (asan)            -> aligned scalar (custom)
+// 19. aligned sized array (asan)      -> aligned array (custom)
+// 20. aligned sized array (asan)      -> aligned array (asan)    -> aligned scalar (custom)
+// 21. aligned array nothrow (asan)    -> aligned array (custom)
+// 22. aligned array nothrow (asan)    -> aligned array (asan)    -> aligned scalar (custom)
+
+#ifdef VERBOSE
+#define PRINTF(...) printf(__VA_ARGS__)
+#else
+#define PRINTF(...)
+#endif
+
+template <size_t N>
+class arena {
+public:
+  void *alloc(const size_t size, const std::align_val_t al) {
+    return alloc(size, static_cast<size_t>(al));
+  }
+
+  void *alloc(const size_t size, const size_t requested_alignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+    if (requested_alignment == 0 || (requested_alignment & (requested_alignment - 1))) {
+      // Alignment must be non-zero and power of two.
+      PRINTF("Allocation of size '%zu' alignment '%zu' failed due to bad arguments.\n", size, requested_alignment);
+      throw std::bad_alloc{};
+    }
+
+    const size_t alignment = (requested_alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) ? __STDCPP_DEFAULT_NEW_ALIGNMENT__ : requested_alignment;
+
+    // Adjust for alignment
+    const size_t alignment_mask = alignment - 1;
+    m_cur = reinterpret_cast<char *>(reinterpret_cast<unsigned __int64>(m_cur + alignment_mask) & ~alignment_mask);
+    const size_t memory_block_size = (size + alignment_mask) & ~alignment_mask;
+
+    if (m_cur + memory_block_size > m_buffer + N) {
+      PRINTF("Allocation of size '%zu' alignment '%zu' failed due to out of memory.\n", size, requested_alignment);
+      throw std::bad_alloc{};
+    }
+
+    char *const returned_memory_block = m_cur;
+    m_cur += memory_block_size;
+
+    PRINTF("Allocated '0x%p' of size '%zu' (requested '%zu') with alignment '%zu' (requested '%zu')\n",
+           returned_memory_block, memory_block_size, size, alignment, requested_alignment);
+
+    return returned_memory_block;
+  }
+
+  void free(const void *ptr) {
+    PRINTF("Deallocated '0x%p'\n", ptr);
+  }
+
+private:
+  char m_buffer[N];
+  char *m_cur = m_buffer;
+};
+
+arena<100000> mem;
+
+////////////////////////////////////
+// clang-format off
+// new() Fallback Ordering
+//
+// +----------+
+// |new_scalar<---------------+
+// +----^-----+               |
+//      |                     |
+// +----+-------------+  +----+----+
+// |new_scalar_nothrow|  |new_array|
+// +------------------+  +----^----+
+//                            |
+//               +------------+----+
+//               |new_array_nothrow|
+//               +-----------------+
+// clang-format on
+
+#if (DEFINED_REPLACEMENTS & SCALAR_NEW)
+void *operator new(const size_t sz) {
+  puts("new_scalar");
+  return mem.alloc(sz);
+}
+#endif // MISSING_SCALAR_NEW
+
+#if (DEFINED_REPLACEMENTS & SCALAR_NEW_NOTHROW)
+void *operator new(const size_t sz, const std::nothrow_t &) noexcept {
+  puts("new_scalar_nothrow");
+  try {
+    return mem.alloc(sz);
+  } catch (...) {
+    return nullptr;
+  }
+}
+#endif // MISSING_SCALAR_NEW_NOTHROW
+
+#if (DEFINED_REPLACEMENTS & ARRAY_NEW)
+void *operator new[](const size_t sz) {
+  puts("new_array");
+  return mem.alloc(sz);
+}
+#endif // MISSING_ARRAY_NEW
+
+#if (DEFINED_REPLACEMENTS & ARRAY_NEW_NOTHROW)
+void *operator new[](const size_t sz, const std::nothrow_t &) noexcept {
+  puts("new_array_nothrow");
+  try {
+    return mem.alloc(sz);
+  } catch (...) {
+    return nullptr;
+  }
+}
+#endif // MISSING_ARRAY_NEW_NOTHROW
+
+////////////////////////////////////////////////
+// clang-format off
+// Aligned new() Fallback Ordering
+//
+// +----------------+
+// |new_scalar_align<--------------+
+// +----^-----------+              |
+//      |                          |
+// +----+-------------------+  +---+-----------+
+// |new_scalar_align_nothrow|  |new_array_align|
+// +------------------------+  +---^-----------+
+//                                 |
+//                     +-----------+-----------+
+//                     |new_array_align_nothrow|
+//                     +-----------------------+
+// clang-format on
+
+#if (DEFINED_REPLACEMENTS & SCALAR_ALIGNED_NEW)
+void *operator new(const size_t sz, const std::align_val_t al) {
+  puts("new_scalar_align");
+  return mem.alloc(sz, al);
+}
+#endif // MISSING_SCALAR_ALIGNED_NEW
+
+#if (DEFINED_REPLACEMENTS & SCALAR_ALIGNED_NEW_NOTHROW)
+void *operator new(const size_t sz, const std::align_val_t al, const std::nothrow_t &) noexcept {
+  puts("new_scalar_align_nothrow");
+  try {
+    return mem.alloc(sz, al);
+  } catch (...) {
+    return nullptr;
+  }
+}
+#endif // MISSING_SCALAR_NEW_ALIGNED_NOTHROW
+
+#if (DEFINED_REPLACEMENTS & ARRAY_ALIGNED_NEW)
+void *operator new[](const size_t sz, const std::align_val_t al) {
+  puts("new_array_align");
+  return mem.alloc(sz, al);
+}
+#endif // MISSING_ARRAY_ALIGNED_NEW
+
+#if (DEFINED_REPLACEMENTS & ARRAY_ALIGNED_NEW_NOTHROW)
+void *operator new[](const size_t sz, const std::align_val_t al, const std::nothrow_t &) noexcept {
+  puts("new_array_align_nothrow");
+  try {
+    return mem.alloc(sz, al);
+  } catch (...) {
+    return nullptr;
+  }
+}
+#endif // MISSING_ARRAY_ALIGNED_NEW_NOTHROW
+
+////////////////////////////////////////////////////////////////
+// clang-format off
+// delete() Fallback Ordering
+//
+// +-------------+
+// |delete_scalar<----+-----------------------+
+// +--^----------+    |                       |
+//    |               |                       |
+// +--+---------+  +--+---------------+  +----+----------------+
+// |delete_array|  |delete_scalar_size|  |delete_scalar_nothrow|
+// +--^----^----+  +------------------+  +---------------------+
+//    |    |
+//    |    +-------------------+
+//    |                        |
+// +--+--------------+  +------+-------------+
+// |delete_array_size|  |delete_array_nothrow|
+// +-----------------+  +--------------------+
+// clang-format on
+
+#if (DEFINED_REPLACEMENTS & SCALAR_DELETE)
+void operator delete(void *const ptr) noexcept {
+  puts("delete_scalar");
+  mem.free(ptr);
+}
+#endif // MISSING_SCALAR_DELETE
+
+#if (DEFINED_REPLACEMENTS & ARRAY_DELETE)
+void operator delete[](void *const ptr) noexcept {
+  puts("delete_array");
+  mem.free(ptr);
+}
+#endif // MISSING_ARRAY_DELETE
+
+#if (DEFINED_REPLACEMENTS & ARRAY_SIZED_DELETE)
+void operator delete[](void *const ptr, const size_t sz) noexcept {
+  puts("delete_array_size");
+  mem.free(ptr);
+}
+#endif // MISSING_ARRAY_SIZED_DELETE
+
+#if (DEFINED_REPLACEMENTS & ARRAY_DELETE_NOTHROW)
+void operator delete[](void *const ptr, const std::nothrow_t &) noexcept {
+  puts("delete_array_nothrow");
+  mem.free(ptr);
+}
+#endif // MISSING_ARRAY_DELETE_NOTHROW
+
+#if (DEFINED_REPLACEMENTS & SCALAR_SIZED_DELETE)
+void operator delete(void *const ptr, const size_t sz) noexcept {
+  puts("delete_scalar_size");
+  mem.free(ptr);
+}
+#endif // MISSING_SCALAR_SIZED_DELETE
+
+#if (DEFINED_REPLACEMENTS & SCALAR_DELETE_NOTHROW)
+void operator delete(void *const ptr, const std::nothrow_t &) noexcept {
+  puts("delete_scalar_nothrow");
+  mem.free(ptr);
+}
+#endif // MISSING_SCALAR_DELETE_NOTHROW
+
+//////////////////////////////////////////////////////////////////////////////////
+// clang-format off
+// Aligned delete() Fallback Ordering
+//
+// +-------------------+
+// |delete_scalar_align<----+---------------------------+
+// +--^----------------+    |                           |
+//    |                     |                           |
+// +--+---------------+  +--+---------------------+  +--+------------------------+
+// |delete_array_align|  |delete_scalar_size_align|  |delete_scalar_align_nothrow|
+// +--^-----^---------+  +------------------------+  +---------------------------+
+//    |     |
+//    |     +------------------------+
+//    |                              |
+// +--+--------------------+  +------+-------------------+
+// |delete_array_size_align|  |delete_array_align_nothrow|
+// +-----------------------+  +--------------------------+
+// clang-format on
+
+#if (DEFINED_REPLACEMENTS & SCALAR_ALIGNED_DELETE)
+void operator delete(void *const ptr, const std::align_val_t) noexcept {
+  puts("delete_scalar_align");
+  mem.free(ptr);
+}
+#endif // MISSING_SCALAR_DELETE
+
+#if (DEFINED_REPLACEMENTS & ARRAY_ALIGNED_DELETE)
+void operator delete[](void *const ptr, const std::align_val_t) noexcept {
+  puts("delete_array_align");
+  mem.free(ptr);
+}
+#endif // MISSING_ARRAY_DELETE
+
+#if (DEFINED_REPLACEMENTS & ARRAY_SIZED_ALIGNED_DELETE)
+void operator delete[](void *const ptr, const size_t sz, const std::align_val_t) noexcept {
+  puts("delete_array_size_align");
+  mem.free(ptr);
+}
+#endif // MISSING_ARRAY_SIZED_DELETE
+
+#if (DEFINED_REPLACEMENTS & ARRAY_ALIGNED_DELETE_NOTHROW)
+void operator delete[](void *const ptr, const std::align_val_t, const std::nothrow_t &) noexcept {
+  puts("delete_array_align_nothrow");
+  mem.free(ptr);
+}
+#endif // MISSING_ARRAY_DELETE_NOTHROW
+
+#if (DEFINED_REPLACEMENTS & SCALAR_SIZED_ALIGNED_DELETE)
+void operator delete(void *const ptr, const size_t sz, const std::align_val_t) noexcept {
+  puts("delete_scalar_size_align");
+  mem.free(ptr);
+}
+#endif // MISSING_SCALAR_SIZED_DELETE
+
+#if (DEFINED_REPLACEMENTS & SCALAR_ALIGNED_DELETE_NOTHROW)
+void operator delete(void *const ptr, const std::align_val_t, const std::nothrow_t &) noexcept {
+  puts("delete_scalar_align_nothrow");
+  mem.free(ptr);
+}
+#endif // MISSING_SCALAR_DELETE_NOTHROW
+
+// Explicitly call delete so we can explicitly choose sized vs non-sized versions of each.
+// Also provide explicit nothrow version, since that can't be implicitly invoked.
+template <typename T>
+void op_delete_scalar(T *ptr) {
+  if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+    operator delete (ptr, std::align_val_t{alignof(T)});
+  } else {
+    operator delete(ptr);
+  }
+}
+
+template <typename T>
+void op_delete_array(T *ptr) {
+  if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+    operator delete[](ptr, std::align_val_t{alignof(T)});
+  } else {
+    operator delete[](ptr);
+  }
+}
+
+template <typename T>
+void op_delete_scalar_nothrow(T *ptr) {
+  if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+    operator delete (ptr, std::align_val_t{alignof(T)}, std::nothrow_t{});
+  } else {
+    operator delete (ptr, std::nothrow_t{});
+  }
+}
+
+template <typename T>
+void op_delete_array_nothrow(T *ptr) {
+  if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+    operator delete[](ptr, std::align_val_t{alignof(T)}, std::nothrow_t{});
+  } else {
+    operator delete[](ptr, std::nothrow_t{});
+  }
+}
+
+template <typename T>
+void op_delete_scalar_size(T *ptr) {
+  if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+    operator delete (ptr, sizeof(T), std::align_val_t{alignof(T)});
+  } else {
+    operator delete(ptr, sizeof(T));
+  }
+}
+
+template <size_t N, typename T>
+void op_delete_array_size(T *ptr) {
+  if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+    operator delete[](ptr, sizeof(T) * N, std::align_val_t{alignof(T)});
+  } else {
+    operator delete[](ptr, sizeof(T) * N);
+  }
+}
+
+template <typename T>
+void test_allocations() {
+  T *scalar = new T();
+  T *array = new T[5];
+
+  T *scalar_nothrow = new (std::nothrow) T();
+  T *array_nothrow = new (std::nothrow) T[5];
+
+  op_delete_scalar(scalar);
+  op_delete_array(array);
+
+  op_delete_scalar_nothrow(scalar_nothrow);
+  op_delete_array_nothrow(array_nothrow);
+
+  T *scalar_size = new T();
+  T *array_size = new T[5];
+
+  op_delete_scalar_size(scalar_size);
+  op_delete_array_size<5>(array_size);
+}
+
+struct alignas(32) overaligned {
+  double a;
+};
+
+#ifdef TEST_DLL
+extern "C" __declspec(dllexport) int test_function()
+#else
+int main()
+#endif
+{
+  test_allocations<int>();
+  test_allocations<overaligned>();
+  return 0;
+}
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_macros.h b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_macros.h
new file mode 100644
index 000000000000000..87e3afdfeea0692
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_macros.h
@@ -0,0 +1,29 @@
+#define SCALAR_NEW                    0x000001
+#define SCALAR_NEW_NOTHROW            0x000002
+#define ARRAY_NEW                     0x000004
+#define ARRAY_NEW_NOTHROW             0x000008
+#define ALL_NEW                       0x00000f
+
+#define SCALAR_ALIGNED_NEW            0x000010
+#define SCALAR_ALIGNED_NEW_NOTHROW    0x000020
+#define ARRAY_ALIGNED_NEW             0x000040
+#define ARRAY_ALIGNED_NEW_NOTHROW     0x000080
+#define ALL_ALIGNED_NEW               0x0000f0
+
+#define SCALAR_DELETE                 0x000100
+#define ARRAY_DELETE                  0x000200
+#define ARRAY_SIZED_DELETE            0x000400
+#define ARRAY_DELETE_NOTHROW          0x000800
+#define SCALAR_SIZED_DELETE           0x001000
+#define SCALAR_DELETE_NOTHROW         0x002000
+#define ALL_DELETE                    0x003f00
+
+#define SCALAR_ALIGNED_DELETE         0x010000
+#define ARRAY_ALIGNED_DELETE          0x020000
+#define ARRAY_SIZED_ALIGNED_DELETE    0x040000
+#define ARRAY_ALIGNED_DELETE_NOTHROW  0x080000
+#define SCALAR_SIZED_ALIGNED_DELETE   0x100000
+#define SCALAR_ALIGNED_DELETE_NOTHROW 0x200000
+#define ALL_ALIGNED_DELETE            0x3f0000
+
+#define ALL_OPERATORS (ALL_NEW | ALL_ALIGNED_NEW | ALL_DELETE | ALL_ALIGNED_DELETE)
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_array.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_array.cpp
new file mode 100644
index 000000000000000..8e5757dc204064c
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_array.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cl_asan /EHsc /Od /std:c++17 %s -Fe%t
+// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %clang_cl_asan /EHsc /Od %p/dll_host.cpp -Fe%t
+// RUN: %clang_cl_asan /EHsc /LD /Od /std:c++17 /DTEST_DLL %s -Fe%t.dll
+// RUN: %run %t %t.dll 2>&1 | FileCheck %s
+
+#include "operator_new_delete_replacement_macros.h"
+#define DEFINED_REPLACEMENTS (SCALAR_NEW | ARRAY_NEW | SCALAR_ALIGNED_NEW | ARRAY_ALIGNED_NEW | ALL_DELETE | ALL_ALIGNED_DELETE)
+#include "operator_new_delete_replacement_common.h"
+
+// Covers:
+// 3. array nothrow (asan)            -> array  (custom)
+// 7. aligned array nothrow (asan)    -> aligned array  (custom)
+
+// CHECK: new_scalar
+// CHECK: new_array
+// CHECK: new_scalar
+// CHECK: new_array
+// CHECK: delete_scalar
+// CHECK: delete_array
+// CHECK: delete_scalar_nothrow
+// CHECK: delete_array_nothrow
+// CHECK: new_scalar
+// CHECK: new_array
+// CHECK: delete_scalar_size
+// CHECK: delete_array_size
+
+// CHECK: new_scalar_align
+// CHECK: new_array_align
+// CHECK: new_scalar_align
+// CHECK: new_array_align
+// CHECK: delete_scalar_align
+// CHECK: delete_array_align
+// CHECK: delete_scalar_align_nothrow
+// CHECK: delete_array_align_nothrow
+// CHECK: new_scalar_align
+// CHECK: new_array_align
+// CHECK: delete_scalar_size_align
+// CHECK: delete_array_size_align
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_scalar.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_scalar.cpp
new file mode 100644
index 000000000000000..0900e8d9b43950f
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_scalar.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cl_asan /EHsc /Od /std:c++17 %s -Fe%t
+// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %clang_cl_asan /EHsc /Od %p/dll_host.cpp -Fe%t
+// RUN: %clang_cl_asan /EHsc /LD /Od /std:c++17 /DTEST_DLL %s -Fe%t.dll
+// RUN: %run %t %t.dll 2>&1 | FileCheck %s
+
+#include "operator_new_delete_replacement_macros.h"
+#define DEFINED_REPLACEMENTS (SCALAR_NEW | SCALAR_ALIGNED_NEW | ALL_DELETE | ALL_ALIGNED_DELETE)
+#include "operator_new_delete_replacement_common.h"
+
+// Covers:
+// 1. array (asan)                    -> scalar (custom)
+// 2. nothrow (asan)                  -> scalar (custom)
+// 4. array nothrow (asan)            -> array  (asan)           -> scalar (custom)
+// 5. aligned array (asan)            -> aligned scalar (custom)
+// 6. aligned nothrow (asan)          -> aligned scalar (custom)
+// 8. aligned array nothrow (asan)    -> aligned array  (asan)   -> aligned scalar (custom)
+
+// CHECK: new_scalar
+// CHECK: new_scalar
+// CHECK: new_scalar
+// CHECK: new_scalar
+// CHECK: delete_scalar
+// CHECK: delete_array
+// CHECK: delete_scalar_nothrow
+// CHECK: delete_array_nothrow
+// CHECK: new_scalar
+// CHECK: new_scalar
+// CHECK: delete_scalar_size
+// CHECK: delete_array_size
+
+// CHECK: new_scalar_align
+// CHECK: new_scalar_align
+// CHECK: new_scalar_align
+// CHECK: new_scalar_align
+// CHECK: delete_scalar_align
+// CHECK: delete_array_align
+// CHECK: delete_scalar_align_nothrow
+// CHECK: delete_array_align_nothrow
+// CHECK: new_scalar_align
+// CHECK: new_scalar_align
+// CHECK: delete_scalar_size_align
+// CHECK: delete_array_size_align
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp
index f9c3753f7f8bfaa..457e83a19f055eb 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_cl_asan %Od %s %Fe%t
 // RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: %clang_cl_asan -Od %s -Fe%t_dbg /link /INFERASANLIBS:DEBUG
+// RUN: not %run %t_dbg 2>&1 | FileCheck %s
 
 #include <windows.h>
 

>From 58ebaf492d0b0dbd4ff5e87c77487f84b117d663 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Tue, 11 Jul 2023 18:19:13 -0700
Subject: [PATCH 02/19] add GET_STACK_TRACE_EXPLICIT for windows

---
 compiler-rt/lib/asan/asan_stack.h | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/compiler-rt/lib/asan/asan_stack.h b/compiler-rt/lib/asan/asan_stack.h
index 02a76af847ae6e4..ff2094534981e8b 100644
--- a/compiler-rt/lib/asan/asan_stack.h
+++ b/compiler-rt/lib/asan/asan_stack.h
@@ -47,6 +47,21 @@ u32 GetMallocContextSize();
                  fast, max_size);                                          \
   }
 
+#define GET_STACK_TRACE_EXPLICIT(max_size, fast, pc, bp, caller_pc, \
+                                 extra_context)                     \
+  UNINITIALIZED __sanitizer::BufferedStackTrace stack;                            \
+  if (max_size <= 2) {                                              \
+    stack.size = max_size;                                          \
+    if (max_size > 0) {                                             \
+      stack.top_frame_bp = bp;                                      \
+      stack.trace_buffer[0] = pc;                                   \
+      if (max_size > 1)                                             \
+        stack.trace_buffer[1] = caller_pc;                          \
+    }                                                               \
+  } else {                                                          \
+    stack.Unwind(pc, bp, nullptr, fast, max_size + extra_context);  \
+  }
+
 #define GET_STACK_TRACE_FATAL(pc, bp)     \
   UNINITIALIZED BufferedStackTrace stack; \
   stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal)
@@ -60,8 +75,16 @@ u32 GetMallocContextSize();
 #define GET_STACK_TRACE_MALLOC                                                 \
   GET_STACK_TRACE(GetMallocContextSize(), common_flags()->fast_unwind_on_malloc)
 
+#define GET_STACK_TRACE_MALLOC_WIN(pc, bp, caller_pc, extra_context)      \
+  GET_STACK_TRACE_EXPLICIT(__asan::GetMallocContextSize(),                \
+                           common_flags()->fast_unwind_on_malloc, pc, bp, \
+                           caller_pc, extra_context)
+
 #define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC
 
+#define GET_STACK_TRACE_FREE_WIN(pc, bp, caller_pc, extra_context) \
+  GET_STACK_TRACE_MALLOC_WIN(pc, bp, caller_pc, extra_context)
+
 #define PRINT_CURRENT_STACK()   \
   {                             \
     GET_STACK_TRACE_FATAL_HERE; \

>From 84c8d79cec46c467cfa3d5066a1cc22de0e08ce2 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Tue, 18 Jul 2023 16:39:17 -0700
Subject: [PATCH 03/19] add static implib to asan static runtime

---
 compiler-rt/lib/asan/CMakeLists.txt | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index 6f286e2386b0b26..c93df93c88617f8 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -290,6 +290,7 @@ else()
     STATIC
     ARCHS ${ASAN_SUPPORTED_ARCH}
     OBJECT_LIBS RTAsan_static
+      $<$<PLATFORM_ID:Windows>:RTAsan_static_implib>
     CFLAGS ${ASAN_CFLAGS}
     DEFS ${ASAN_COMMON_DEFINITIONS}
     PARENT_TARGET asan)
@@ -358,6 +359,24 @@ else()
       DEFS ${ASAN_DYNAMIC_DEFINITIONS}
       PARENT_TARGET asan)
 
+    set_target_properties(clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch}
+      PROPERTIES ARCHIVE_OUTPUT_NAME clang_rt.asan_dynamic-${arch}_implib
+                 ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+    add_library(clang_rt.asan-${arch}_implib STATIC)
+    target_link_libraries(clang_rt.asan-${arch}_implib RTAsan_static_implib.${arch})
+    add_dependencies(clang_rt.asan-${arch}_implib clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch})
+    get_compiler_rt_output_dir(${arch} IMPLIB_OUTPUT_DIR)
+    set_target_properties(clang_rt.asan-${arch}_implib
+      PROPERTIES ARCHIVE_OUTPUT_NAME clang_rt.asan${MSVC_DBG_SUFFIX}_dynamic-${arch}
+                  ARCHIVE_OUTPUT_DIRECTORY ${IMPLIB_OUTPUT_DIR}
+                  STATIC_LIBRARY_OPTIONS "$<TARGET_LINKER_FILE:clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch}>")
+    get_compiler_rt_install_dir(${arch} IMPLIB_INSTALL_DIR)
+    install(TARGETS clang_rt.asan-${arch}_implib
+      ARCHIVE DESTINATION ${IMPLIB_INSTALL_DIR}
+      LIBRARY DESTINATION ${IMPLIB_INSTALL_DIR}
+      RUNTIME DESTINATION ${IMPLIB_INSTALL_DIR})
+
     if (SANITIZER_USE_SYMBOLS AND NOT ${arch} STREQUAL "i386")
       add_sanitizer_rt_symbols(clang_rt.asan_cxx
         ARCHS ${arch})

>From 16efb89455507d2ea7fcd819488595d5dde0c076 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Wed, 19 Jul 2023 16:05:16 -0700
Subject: [PATCH 04/19] char* -> char**

---
 .../asan/TestCases/Windows/new_delete_mfc_already_defined.cpp   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp
index dbb789cc075861c..8c5ec3f4a26372b 100644
--- a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp
@@ -16,7 +16,7 @@
 
 int AFX_CDECL AfxCriticalNewHandler(size_t nSize);
 
-int main(int argc, char* argv) {
+int main(int argc, char** argv) {
     AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
     _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
     AfxSetNewHandler(pnhOldHandler);

>From 6b8daf3729c98bc93ae6fb1812c586c124f46362 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Wed, 19 Jul 2023 17:07:08 -0700
Subject: [PATCH 05/19] Summary: [asan][win][msvc] override new and delete and
 seperate TUs

Currently asan simply exports each overridden new/delete function from the DLL, this works fine normally, but fails if the user is overriding some, but not all, of those functions. In this case the ones they aren't overriding will pull in all the functions from the dll, and you'll get multiple definition errors. In particular this happened with MFC, since MFC contains an op new overload in the same TU as a bunch of other stuff.

This fixes that issue and adds tests. I verified that all the tests that were passing before in the dynamic asan build still pass, the dll_heap_allocation test still fails, likely because it's trying to link with the static asan runtime which, as mentioned below, doesn't really work.

Additionally this messes around with the build system to add the new/delete overrides to the import library of the DLL, not the dll itself. This is a bit messy in cmake but it does work. The new functions are also added to the static library, but the static library currently doesn't work well on windows, in the branch of asan that we (Microsoft) use i Visual Studio we've actually completely removed support for the static asan runtime, concluding that because of the windows dynamic linkage model it's basically unworkable without really horrible to maintain hacks.

add GET_STACK_TRACE_EXPLICIT for windows

add static implib to asan static runtime

char* -> char**

clang-format

Differential Revision: https://reviews.llvm.org/D155879
---
 compiler-rt/lib/asan/asan_stack.h             |  2 +-
 .../new_delete_mfc_already_defined.cpp        | 14 +--
 .../new_delete_mfc_already_defined_dbg.cpp    | 12 +--
 .../operator_delete_replacement_array.cpp     |  4 +-
 .../operator_delete_replacement_scalar.cpp    |  3 +-
 .../operator_new_delete_replacement_common.h  | 88 +++++++++++--------
 .../operator_new_delete_replacement_macros.h  | 49 ++++++-----
 .../operator_new_replacement_array.cpp        |  4 +-
 .../operator_new_replacement_scalar.cpp       |  3 +-
 9 files changed, 98 insertions(+), 81 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_stack.h b/compiler-rt/lib/asan/asan_stack.h
index ff2094534981e8b..bc1b676e3d45ba6 100644
--- a/compiler-rt/lib/asan/asan_stack.h
+++ b/compiler-rt/lib/asan/asan_stack.h
@@ -49,7 +49,7 @@ u32 GetMallocContextSize();
 
 #define GET_STACK_TRACE_EXPLICIT(max_size, fast, pc, bp, caller_pc, \
                                  extra_context)                     \
-  UNINITIALIZED __sanitizer::BufferedStackTrace stack;                            \
+  UNINITIALIZED __sanitizer::BufferedStackTrace stack;              \
   if (max_size <= 2) {                                              \
     stack.size = max_size;                                          \
     if (max_size > 0) {                                             \
diff --git a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp
index 8c5ec3f4a26372b..952b095446e96fd 100644
--- a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined.cpp
@@ -9,17 +9,17 @@
 // nafxcw.lib(afxmem.obj) : warning LNK4006: "void __cdecl operator delete(void *)" (??3 at YAXPAX@Z) already defined in clang_rt.asan_cxx-i386.lib(asan_win_delete_scalar_thunk.cpp.obj); second definition ignored
 
 #ifdef _DLL
-#define _AFXDLL
+#  define _AFXDLL
 #endif
 
 #include "afxglobals.h"
 
 int AFX_CDECL AfxCriticalNewHandler(size_t nSize);
 
-int main(int argc, char** argv) {
-    AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
-    _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
-    AfxSetNewHandler(pnhOldHandler);
-    puts("Pass");
-    return 0;
+int main(int argc, char **argv) {
+  AFX_MODULE_THREAD_STATE *pState = AfxGetModuleThreadState();
+  _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
+  AfxSetNewHandler(pnhOldHandler);
+  puts("Pass");
+  return 0;
 }
\ No newline at end of file
diff --git a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp
index b3b5fffc999ae16..b7554ca288056ac 100644
--- a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp
@@ -8,18 +8,18 @@
 // Address Sanitizer error: mismatch between allocation and deallocation APis
 
 #ifdef _DLL
-#define _AFXDLL
+#  define _AFXDLL
 #endif
 
 #include <SDKDDKVer.h>
 #include <afxglobals.h>
 
 int main() {
-    int * normal = new int;
-    int * debug = DEBUG_NEW int;
+  int *normal = new int;
+  int *debug = DEBUG_NEW int;
 
-    delete normal;
-    delete debug;
+  delete normal;
+  delete debug;
 
-    return 0;
+  return 0;
 }
\ No newline at end of file
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_array.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_array.cpp
index 211b24c680b65df..b65595cafc9f0a5 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_array.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_array.cpp
@@ -5,7 +5,9 @@
 // RUN: %run %t %t.dll 2>&1 | FileCheck %s
 
 #include "operator_new_delete_replacement_macros.h"
-#define DEFINED_REPLACEMENTS (ALL_NEW | ALL_ALIGNED_NEW | SCALAR_DELETE | ARRAY_DELETE | SCALAR_ALIGNED_DELETE | ARRAY_ALIGNED_DELETE)
+#define DEFINED_REPLACEMENTS                                                   \
+  (ALL_NEW | ALL_ALIGNED_NEW | SCALAR_DELETE | ARRAY_DELETE |                  \
+   SCALAR_ALIGNED_DELETE | ARRAY_ALIGNED_DELETE)
 #include "operator_new_delete_replacement_common.h"
 
 // Covers:
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_scalar.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_scalar.cpp
index 355d0030499c988..b796b41f0affd84 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_scalar.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_delete_replacement_scalar.cpp
@@ -5,7 +5,8 @@
 // RUN: %run %t %t.dll 2>&1 | FileCheck %s
 
 #include "operator_new_delete_replacement_macros.h"
-#define DEFINED_REPLACEMENTS (ALL_NEW | ALL_ALIGNED_NEW | SCALAR_DELETE | SCALAR_ALIGNED_DELETE)
+#define DEFINED_REPLACEMENTS                                                   \
+  (ALL_NEW | ALL_ALIGNED_NEW | SCALAR_DELETE | SCALAR_ALIGNED_DELETE)
 #include "operator_new_delete_replacement_common.h"
 
 // Covers:
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_common.h b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_common.h
index 07493747a04b28b..07e3d29f3264d82 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_common.h
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_common.h
@@ -31,49 +31,60 @@
 // 22. aligned array nothrow (asan)    -> aligned array (asan)    -> aligned scalar (custom)
 
 #ifdef VERBOSE
-#define PRINTF(...) printf(__VA_ARGS__)
+#  define PRINTF(...) printf(__VA_ARGS__)
 #else
-#define PRINTF(...)
+#  define PRINTF(...)
 #endif
 
-template <size_t N>
-class arena {
+template <size_t N> class arena {
 public:
   void *alloc(const size_t size, const std::align_val_t al) {
     return alloc(size, static_cast<size_t>(al));
   }
 
-  void *alloc(const size_t size, const size_t requested_alignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
-    if (requested_alignment == 0 || (requested_alignment & (requested_alignment - 1))) {
+  void *
+  alloc(const size_t size,
+        const size_t requested_alignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+    if (requested_alignment == 0 ||
+        (requested_alignment & (requested_alignment - 1))) {
       // Alignment must be non-zero and power of two.
-      PRINTF("Allocation of size '%zu' alignment '%zu' failed due to bad arguments.\n", size, requested_alignment);
+      PRINTF("Allocation of size '%zu' alignment '%zu' failed due to bad "
+             "arguments.\n",
+             size, requested_alignment);
       throw std::bad_alloc{};
     }
 
-    const size_t alignment = (requested_alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) ? __STDCPP_DEFAULT_NEW_ALIGNMENT__ : requested_alignment;
+    const size_t alignment =
+        (requested_alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+            ? __STDCPP_DEFAULT_NEW_ALIGNMENT__
+            : requested_alignment;
 
     // Adjust for alignment
     const size_t alignment_mask = alignment - 1;
-    m_cur = reinterpret_cast<char *>(reinterpret_cast<unsigned __int64>(m_cur + alignment_mask) & ~alignment_mask);
+    m_cur = reinterpret_cast<char *>(
+        reinterpret_cast<unsigned __int64>(m_cur + alignment_mask) &
+        ~alignment_mask);
     const size_t memory_block_size = (size + alignment_mask) & ~alignment_mask;
 
     if (m_cur + memory_block_size > m_buffer + N) {
-      PRINTF("Allocation of size '%zu' alignment '%zu' failed due to out of memory.\n", size, requested_alignment);
+      PRINTF("Allocation of size '%zu' alignment '%zu' failed due to out of "
+             "memory.\n",
+             size, requested_alignment);
       throw std::bad_alloc{};
     }
 
     char *const returned_memory_block = m_cur;
     m_cur += memory_block_size;
 
-    PRINTF("Allocated '0x%p' of size '%zu' (requested '%zu') with alignment '%zu' (requested '%zu')\n",
-           returned_memory_block, memory_block_size, size, alignment, requested_alignment);
+    PRINTF("Allocated '0x%p' of size '%zu' (requested '%zu') with alignment "
+           "'%zu' (requested '%zu')\n",
+           returned_memory_block, memory_block_size, size, alignment,
+           requested_alignment);
 
     return returned_memory_block;
   }
 
-  void free(const void *ptr) {
-    PRINTF("Deallocated '0x%p'\n", ptr);
-  }
+  void free(const void *ptr) { PRINTF("Deallocated '0x%p'\n", ptr); }
 
 private:
   char m_buffer[N];
@@ -160,7 +171,8 @@ void *operator new(const size_t sz, const std::align_val_t al) {
 #endif // MISSING_SCALAR_ALIGNED_NEW
 
 #if (DEFINED_REPLACEMENTS & SCALAR_ALIGNED_NEW_NOTHROW)
-void *operator new(const size_t sz, const std::align_val_t al, const std::nothrow_t &) noexcept {
+void *operator new(const size_t sz, const std::align_val_t al,
+                   const std::nothrow_t &) noexcept {
   puts("new_scalar_align_nothrow");
   try {
     return mem.alloc(sz, al);
@@ -178,7 +190,8 @@ void *operator new[](const size_t sz, const std::align_val_t al) {
 #endif // MISSING_ARRAY_ALIGNED_NEW
 
 #if (DEFINED_REPLACEMENTS & ARRAY_ALIGNED_NEW_NOTHROW)
-void *operator new[](const size_t sz, const std::align_val_t al, const std::nothrow_t &) noexcept {
+void *operator new[](const size_t sz, const std::align_val_t al,
+                     const std::nothrow_t &) noexcept {
   puts("new_array_align_nothrow");
   try {
     return mem.alloc(sz, al);
@@ -283,28 +296,32 @@ void operator delete[](void *const ptr, const std::align_val_t) noexcept {
 #endif // MISSING_ARRAY_DELETE
 
 #if (DEFINED_REPLACEMENTS & ARRAY_SIZED_ALIGNED_DELETE)
-void operator delete[](void *const ptr, const size_t sz, const std::align_val_t) noexcept {
+void operator delete[](void *const ptr, const size_t sz,
+                       const std::align_val_t) noexcept {
   puts("delete_array_size_align");
   mem.free(ptr);
 }
 #endif // MISSING_ARRAY_SIZED_DELETE
 
 #if (DEFINED_REPLACEMENTS & ARRAY_ALIGNED_DELETE_NOTHROW)
-void operator delete[](void *const ptr, const std::align_val_t, const std::nothrow_t &) noexcept {
+void operator delete[](void *const ptr, const std::align_val_t,
+                       const std::nothrow_t &) noexcept {
   puts("delete_array_align_nothrow");
   mem.free(ptr);
 }
 #endif // MISSING_ARRAY_DELETE_NOTHROW
 
 #if (DEFINED_REPLACEMENTS & SCALAR_SIZED_ALIGNED_DELETE)
-void operator delete(void *const ptr, const size_t sz, const std::align_val_t) noexcept {
+void operator delete(void *const ptr, const size_t sz,
+                     const std::align_val_t) noexcept {
   puts("delete_scalar_size_align");
   mem.free(ptr);
 }
 #endif // MISSING_SCALAR_SIZED_DELETE
 
 #if (DEFINED_REPLACEMENTS & SCALAR_ALIGNED_DELETE_NOTHROW)
-void operator delete(void *const ptr, const std::align_val_t, const std::nothrow_t &) noexcept {
+void operator delete(void *const ptr, const std::align_val_t,
+                     const std::nothrow_t &) noexcept {
   puts("delete_scalar_align_nothrow");
   mem.free(ptr);
 }
@@ -312,17 +329,15 @@ void operator delete(void *const ptr, const std::align_val_t, const std::nothrow
 
 // Explicitly call delete so we can explicitly choose sized vs non-sized versions of each.
 // Also provide explicit nothrow version, since that can't be implicitly invoked.
-template <typename T>
-void op_delete_scalar(T *ptr) {
+template <typename T> void op_delete_scalar(T *ptr) {
   if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
-    operator delete (ptr, std::align_val_t{alignof(T)});
+    operator delete(ptr, std::align_val_t{alignof(T)});
   } else {
     operator delete(ptr);
   }
 }
 
-template <typename T>
-void op_delete_array(T *ptr) {
+template <typename T> void op_delete_array(T *ptr) {
   if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
     operator delete[](ptr, std::align_val_t{alignof(T)});
   } else {
@@ -330,17 +345,15 @@ void op_delete_array(T *ptr) {
   }
 }
 
-template <typename T>
-void op_delete_scalar_nothrow(T *ptr) {
+template <typename T> void op_delete_scalar_nothrow(T *ptr) {
   if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
-    operator delete (ptr, std::align_val_t{alignof(T)}, std::nothrow_t{});
+    operator delete(ptr, std::align_val_t{alignof(T)}, std::nothrow_t{});
   } else {
-    operator delete (ptr, std::nothrow_t{});
+    operator delete(ptr, std::nothrow_t{});
   }
 }
 
-template <typename T>
-void op_delete_array_nothrow(T *ptr) {
+template <typename T> void op_delete_array_nothrow(T *ptr) {
   if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
     operator delete[](ptr, std::align_val_t{alignof(T)}, std::nothrow_t{});
   } else {
@@ -348,17 +361,15 @@ void op_delete_array_nothrow(T *ptr) {
   }
 }
 
-template <typename T>
-void op_delete_scalar_size(T *ptr) {
+template <typename T> void op_delete_scalar_size(T *ptr) {
   if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
-    operator delete (ptr, sizeof(T), std::align_val_t{alignof(T)});
+    operator delete(ptr, sizeof(T), std::align_val_t{alignof(T)});
   } else {
     operator delete(ptr, sizeof(T));
   }
 }
 
-template <size_t N, typename T>
-void op_delete_array_size(T *ptr) {
+template <size_t N, typename T> void op_delete_array_size(T *ptr) {
   if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
     operator delete[](ptr, sizeof(T) * N, std::align_val_t{alignof(T)});
   } else {
@@ -366,8 +377,7 @@ void op_delete_array_size(T *ptr) {
   }
 }
 
-template <typename T>
-void test_allocations() {
+template <typename T> void test_allocations() {
   T *scalar = new T();
   T *array = new T[5];
 
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_macros.h b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_macros.h
index 87e3afdfeea0692..7ea1744bf9bd377 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_macros.h
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_delete_replacement_macros.h
@@ -1,29 +1,30 @@
-#define SCALAR_NEW                    0x000001
-#define SCALAR_NEW_NOTHROW            0x000002
-#define ARRAY_NEW                     0x000004
-#define ARRAY_NEW_NOTHROW             0x000008
-#define ALL_NEW                       0x00000f
+#define SCALAR_NEW 0x000001
+#define SCALAR_NEW_NOTHROW 0x000002
+#define ARRAY_NEW 0x000004
+#define ARRAY_NEW_NOTHROW 0x000008
+#define ALL_NEW 0x00000f
 
-#define SCALAR_ALIGNED_NEW            0x000010
-#define SCALAR_ALIGNED_NEW_NOTHROW    0x000020
-#define ARRAY_ALIGNED_NEW             0x000040
-#define ARRAY_ALIGNED_NEW_NOTHROW     0x000080
-#define ALL_ALIGNED_NEW               0x0000f0
+#define SCALAR_ALIGNED_NEW 0x000010
+#define SCALAR_ALIGNED_NEW_NOTHROW 0x000020
+#define ARRAY_ALIGNED_NEW 0x000040
+#define ARRAY_ALIGNED_NEW_NOTHROW 0x000080
+#define ALL_ALIGNED_NEW 0x0000f0
 
-#define SCALAR_DELETE                 0x000100
-#define ARRAY_DELETE                  0x000200
-#define ARRAY_SIZED_DELETE            0x000400
-#define ARRAY_DELETE_NOTHROW          0x000800
-#define SCALAR_SIZED_DELETE           0x001000
-#define SCALAR_DELETE_NOTHROW         0x002000
-#define ALL_DELETE                    0x003f00
+#define SCALAR_DELETE 0x000100
+#define ARRAY_DELETE 0x000200
+#define ARRAY_SIZED_DELETE 0x000400
+#define ARRAY_DELETE_NOTHROW 0x000800
+#define SCALAR_SIZED_DELETE 0x001000
+#define SCALAR_DELETE_NOTHROW 0x002000
+#define ALL_DELETE 0x003f00
 
-#define SCALAR_ALIGNED_DELETE         0x010000
-#define ARRAY_ALIGNED_DELETE          0x020000
-#define ARRAY_SIZED_ALIGNED_DELETE    0x040000
-#define ARRAY_ALIGNED_DELETE_NOTHROW  0x080000
-#define SCALAR_SIZED_ALIGNED_DELETE   0x100000
+#define SCALAR_ALIGNED_DELETE 0x010000
+#define ARRAY_ALIGNED_DELETE 0x020000
+#define ARRAY_SIZED_ALIGNED_DELETE 0x040000
+#define ARRAY_ALIGNED_DELETE_NOTHROW 0x080000
+#define SCALAR_SIZED_ALIGNED_DELETE 0x100000
 #define SCALAR_ALIGNED_DELETE_NOTHROW 0x200000
-#define ALL_ALIGNED_DELETE            0x3f0000
+#define ALL_ALIGNED_DELETE 0x3f0000
 
-#define ALL_OPERATORS (ALL_NEW | ALL_ALIGNED_NEW | ALL_DELETE | ALL_ALIGNED_DELETE)
+#define ALL_OPERATORS                                                          \
+  (ALL_NEW | ALL_ALIGNED_NEW | ALL_DELETE | ALL_ALIGNED_DELETE)
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_array.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_array.cpp
index 8e5757dc204064c..d36e235cb137ddb 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_array.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_array.cpp
@@ -5,7 +5,9 @@
 // RUN: %run %t %t.dll 2>&1 | FileCheck %s
 
 #include "operator_new_delete_replacement_macros.h"
-#define DEFINED_REPLACEMENTS (SCALAR_NEW | ARRAY_NEW | SCALAR_ALIGNED_NEW | ARRAY_ALIGNED_NEW | ALL_DELETE | ALL_ALIGNED_DELETE)
+#define DEFINED_REPLACEMENTS                                                   \
+  (SCALAR_NEW | ARRAY_NEW | SCALAR_ALIGNED_NEW | ARRAY_ALIGNED_NEW |           \
+   ALL_DELETE | ALL_ALIGNED_DELETE)
 #include "operator_new_delete_replacement_common.h"
 
 // Covers:
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_scalar.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_scalar.cpp
index 0900e8d9b43950f..032904e12430255 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_scalar.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_replacement_scalar.cpp
@@ -5,7 +5,8 @@
 // RUN: %run %t %t.dll 2>&1 | FileCheck %s
 
 #include "operator_new_delete_replacement_macros.h"
-#define DEFINED_REPLACEMENTS (SCALAR_NEW | SCALAR_ALIGNED_NEW | ALL_DELETE | ALL_ALIGNED_DELETE)
+#define DEFINED_REPLACEMENTS                                                   \
+  (SCALAR_NEW | SCALAR_ALIGNED_NEW | ALL_DELETE | ALL_ALIGNED_DELETE)
 #include "operator_new_delete_replacement_common.h"
 
 // Covers:

>From e051421826a8c7ecc29dead1651179ba3dc71824 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Mon, 24 Jul 2023 14:58:26 -0700
Subject: [PATCH 06/19] only do the implib injections on windows, fixes build
 on linux

---
 compiler-rt/lib/asan/CMakeLists.txt | 36 +++++++++++++++--------------
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index c93df93c88617f8..0af3844dd53afd0 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -359,23 +359,25 @@ else()
       DEFS ${ASAN_DYNAMIC_DEFINITIONS}
       PARENT_TARGET asan)
 
-    set_target_properties(clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch}
-      PROPERTIES ARCHIVE_OUTPUT_NAME clang_rt.asan_dynamic-${arch}_implib
-                 ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
-
-    add_library(clang_rt.asan-${arch}_implib STATIC)
-    target_link_libraries(clang_rt.asan-${arch}_implib RTAsan_static_implib.${arch})
-    add_dependencies(clang_rt.asan-${arch}_implib clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch})
-    get_compiler_rt_output_dir(${arch} IMPLIB_OUTPUT_DIR)
-    set_target_properties(clang_rt.asan-${arch}_implib
-      PROPERTIES ARCHIVE_OUTPUT_NAME clang_rt.asan${MSVC_DBG_SUFFIX}_dynamic-${arch}
-                  ARCHIVE_OUTPUT_DIRECTORY ${IMPLIB_OUTPUT_DIR}
-                  STATIC_LIBRARY_OPTIONS "$<TARGET_LINKER_FILE:clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch}>")
-    get_compiler_rt_install_dir(${arch} IMPLIB_INSTALL_DIR)
-    install(TARGETS clang_rt.asan-${arch}_implib
-      ARCHIVE DESTINATION ${IMPLIB_INSTALL_DIR}
-      LIBRARY DESTINATION ${IMPLIB_INSTALL_DIR}
-      RUNTIME DESTINATION ${IMPLIB_INSTALL_DIR})
+    if(WIN32)
+      set_target_properties(clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch}
+        PROPERTIES ARCHIVE_OUTPUT_NAME clang_rt.asan_dynamic-${arch}_implib
+                  ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+      add_library(clang_rt.asan-${arch}_implib STATIC)
+      target_link_libraries(clang_rt.asan-${arch}_implib RTAsan_static_implib.${arch})
+      add_dependencies(clang_rt.asan-${arch}_implib clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch})
+      get_compiler_rt_output_dir(${arch} IMPLIB_OUTPUT_DIR)
+      set_target_properties(clang_rt.asan-${arch}_implib
+        PROPERTIES ARCHIVE_OUTPUT_NAME clang_rt.asan${MSVC_DBG_SUFFIX}_dynamic-${arch}
+                    ARCHIVE_OUTPUT_DIRECTORY ${IMPLIB_OUTPUT_DIR}
+                    STATIC_LIBRARY_OPTIONS "$<TARGET_LINKER_FILE:clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch}>")
+      get_compiler_rt_install_dir(${arch} IMPLIB_INSTALL_DIR)
+      install(TARGETS clang_rt.asan-${arch}_implib
+        ARCHIVE DESTINATION ${IMPLIB_INSTALL_DIR}
+        LIBRARY DESTINATION ${IMPLIB_INSTALL_DIR}
+        RUNTIME DESTINATION ${IMPLIB_INSTALL_DIR})
+    endif()
 
     if (SANITIZER_USE_SYMBOLS AND NOT ${arch} STREQUAL "i386")
       add_sanitizer_rt_symbols(clang_rt.asan_cxx

>From cf0eb9334eb19a978b9daa12b5f6f3763a61ca44 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Tue, 25 Jul 2023 11:03:40 -0700
Subject: [PATCH 07/19] Use conditionals at configure time to add implib object
 library

Previously I was using generator expressions which fails because the implib
object library doesn't exist at all on non-windows platforms
---
 compiler-rt/lib/asan/CMakeLists.txt | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index 0af3844dd53afd0..735c770f4339ff4 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -286,14 +286,24 @@ else()
     DEFS ${ASAN_COMMON_DEFINITIONS}
     PARENT_TARGET asan)
 
+if(WIN32)
   add_compiler_rt_runtime(clang_rt.asan_static
     STATIC
     ARCHS ${ASAN_SUPPORTED_ARCH}
     OBJECT_LIBS RTAsan_static
-      $<$<PLATFORM_ID:Windows>:RTAsan_static_implib>
+      RTAsan_static_implib
     CFLAGS ${ASAN_CFLAGS}
     DEFS ${ASAN_COMMON_DEFINITIONS}
     PARENT_TARGET asan)
+else()
+  add_compiler_rt_runtime(clang_rt.asan_static
+    STATIC
+    ARCHS ${ASAN_SUPPORTED_ARCH}
+    OBJECT_LIBS RTAsan_static
+    CFLAGS ${ASAN_CFLAGS}
+    DEFS ${ASAN_COMMON_DEFINITIONS}
+    PARENT_TARGET asan)
+endif()
 
   add_compiler_rt_runtime(clang_rt.asan-preinit
     STATIC

>From 4e8b2ce24b73b8128ce704fc03bef35a2506b629 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Wed, 2 Aug 2023 16:00:50 -0700
Subject: [PATCH 08/19] add new and delete asan implementations to
 interface.inc

---
 compiler-rt/lib/asan/asan_interface.inc | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc
index bfc44b46196232f..83c0c1cffb85363 100644
--- a/compiler-rt/lib/asan/asan_interface.inc
+++ b/compiler-rt/lib/asan/asan_interface.inc
@@ -187,3 +187,22 @@ INTERFACE_FUNCTION(__asan_update_allocation_context)
 INTERFACE_WEAK_FUNCTION(__asan_default_options)
 INTERFACE_WEAK_FUNCTION(__asan_default_suppressions)
 INTERFACE_WEAK_FUNCTION(__asan_on_error)
+
+#if SANITIZER_WINDOWS
+INTERFACE_FUNCTION(__asan_delete)
+INTERFACE_FUNCTION(__asan_delete_align)
+INTERFACE_FUNCTION(__asan_delete_array)
+INTERFACE_FUNCTION(__asan_delete_array_align)
+INTERFACE_FUNCTION(__asan_delete_array_size)
+INTERFACE_FUNCTION(__asan_delete_array_size_align)
+INTERFACE_FUNCTION(__asan_delete_size)
+INTERFACE_FUNCTION(__asan_delete_size_align)
+INTERFACE_FUNCTION(__asan_new)
+INTERFACE_FUNCTION(__asan_new_align)
+INTERFACE_FUNCTION(__asan_new_align_nothrow)
+INTERFACE_FUNCTION(__asan_new_array)
+INTERFACE_FUNCTION(__asan_new_array_align)
+INTERFACE_FUNCTION(__asan_new_array_align_nothrow)
+INTERFACE_FUNCTION(__asan_new_array_nothrow)
+INTERFACE_FUNCTION(__asan_new_nothrow)
+#endif  // SANITIZER_WINDOWS

>From dc990f4ea5131205176fb628a31ca147377d6851 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Wed, 2 Aug 2023 19:04:22 -0700
Subject: [PATCH 09/19] Add dependency between overall asan target and the
 modified implib

---
 compiler-rt/lib/asan/CMakeLists.txt | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index 735c770f4339ff4..049fbc32815c89c 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -313,6 +313,13 @@ endif()
     DEFS ${ASAN_COMMON_DEFINITIONS}
     PARENT_TARGET asan)
 
+
+  if (MSVC AND COMPILER_RT_DEBUG)
+    set(MSVC_DBG_SUFFIX _dbg)
+  else()
+    set(MSVC_DBG_SUFFIX )
+  endif()
+
   foreach(arch ${ASAN_SUPPORTED_ARCH})
     if (COMPILER_RT_HAS_VERSION_SCRIPT)
       add_sanitizer_rt_version_list(clang_rt.asan-dynamic-${arch}
@@ -376,6 +383,7 @@ endif()
 
       add_library(clang_rt.asan-${arch}_implib STATIC)
       target_link_libraries(clang_rt.asan-${arch}_implib RTAsan_static_implib.${arch})
+      add_dependencies(asan clang_rt.asan-${arch}_implib)
       add_dependencies(clang_rt.asan-${arch}_implib clang_rt.asan${MSVC_DBG_SUFFIX}-dynamic-${arch})
       get_compiler_rt_output_dir(${arch} IMPLIB_OUTPUT_DIR)
       set_target_properties(clang_rt.asan-${arch}_implib

>From e438a19c7a8507db8d5e92ff9feefc14ff0843f3 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Mon, 9 Oct 2023 14:56:03 -0700
Subject: [PATCH 10/19] use the same __asan_win_stack_data in every TU

---
 compiler-rt/lib/asan/asan_win_new_delete.cpp | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_win_new_delete.cpp b/compiler-rt/lib/asan/asan_win_new_delete.cpp
index c4de9159d5b0cbc..6f721c92cb3813a 100644
--- a/compiler-rt/lib/asan/asan_win_new_delete.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_delete.cpp
@@ -12,11 +12,15 @@
 //===----------------------------------------------------------------------===//
 #include <stddef.h>
 
+#include "asan_win_thunk_common.h"
 #include "asan_allocator.h"
 #include "asan_internal.h"
 #include "asan_report.h"
 #include "asan_stack.h"
 
+
+using __asan_win_new_delete_data = __asan_win_stack_data;
+
 // Fake std::align_val_t to avoid including <new>.
 namespace std {
 enum class align_val_t : size_t {};
@@ -24,15 +28,6 @@ enum class align_val_t : size_t {};
 
 using namespace __asan;
 
-struct __asan_win_new_delete_data {
-  size_t size;        // Size of this struct (it travels over the DLL boundary).
-  int extra_context;  // Number of extra frames we need to collect in the
-                      // backtrace.
-  __sanitizer::uptr pc;
-  __sanitizer::uptr bp;
-  __sanitizer::uptr caller_pc;
-};
-
 #define OPERATOR_NEW_BODY(type, nothrow)                          \
   GET_STACK_TRACE_MALLOC_WIN(data->pc, data->bp, data->caller_pc, \
                              data->extra_context);                \

>From d5668b27f7d79a6c75208430102c4307a9018f5b Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Tue, 10 Oct 2023 15:44:08 -0700
Subject: [PATCH 11/19] eliminate duplicate definition of GET_CALLER_PC and
 GET_CURRENT_FRAME

---
 compiler-rt/lib/asan/asan_win_new_delete.cpp  |  2 +-
 .../asan/asan_win_new_delete_thunk_common.h   |  2 +-
 compiler-rt/lib/asan/asan_win_thunk_common.h  | 19 +++----------------
 3 files changed, 5 insertions(+), 18 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_win_new_delete.cpp b/compiler-rt/lib/asan/asan_win_new_delete.cpp
index 6f721c92cb3813a..be62ce7828fd5ba 100644
--- a/compiler-rt/lib/asan/asan_win_new_delete.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_delete.cpp
@@ -19,7 +19,7 @@
 #include "asan_stack.h"
 
 
-using __asan_win_new_delete_data = __asan_win_stack_data;
+using __asan_win_new_delete_data = __sanitizer::__asan_win_stack_data;
 
 // Fake std::align_val_t to avoid including <new>.
 namespace std {
diff --git a/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
index 1502c04b611df38..e9715acb4ea1e8d 100644
--- a/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
+++ b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
@@ -35,7 +35,7 @@ void* operator new[](size_t, std::align_val_t);
 void operator delete(void* ptr, std::align_val_t align);
 void operator delete[](void* ptr, std::align_val_t align);
 
-using __asan_win_new_delete_data = __asan_win_stack_data;
+using __asan_win_new_delete_data = __sanitizer::__asan_win_stack_data;
 
 ////////////////////////////////////
 // clang-format off
diff --git a/compiler-rt/lib/asan/asan_win_thunk_common.h b/compiler-rt/lib/asan/asan_win_thunk_common.h
index 49d17a74e367865..2957de4dd3e29a8 100644
--- a/compiler-rt/lib/asan/asan_win_thunk_common.h
+++ b/compiler-rt/lib/asan/asan_win_thunk_common.h
@@ -18,23 +18,8 @@
 //===----------------------------------------------------------------------===//
 
 #pragma once
-
+#include <sanitizer_common/sanitizer_internal_defs.h>
 namespace __sanitizer {
-#if defined(_WIN64)
-typedef unsigned long long uptr;
-#else
-typedef unsigned long uptr;
-#endif
-}  // namespace __sanitizer
-
-extern "C" void* _ReturnAddress(void);
-extern "C" void* _AddressOfReturnAddress(void);
-#pragma intrinsic(_ReturnAddress)
-#pragma intrinsic(_AddressOfReturnAddress)
-
-#define GET_CALLER_PC() (__sanitizer::uptr) _ReturnAddress()
-#define GET_CURRENT_FRAME() \
-  (((__sanitizer::uptr)_AddressOfReturnAddress()) + sizeof(__sanitizer::uptr))
 
 __declspec(noinline) inline __sanitizer::uptr __asan_GetCurrentPc() {
   return GET_CALLER_PC();
@@ -62,3 +47,5 @@ struct __asan_win_stack_data {
   __sanitizer::uptr bp;
   __sanitizer::uptr caller_pc;
 };
+
+}
\ No newline at end of file

>From 4cd5d2c85fe9898e3b7b5ecaa061b9549318aeab Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Tue, 31 Oct 2023 14:00:57 -0700
Subject: [PATCH 12/19] clang-format

---
 compiler-rt/lib/asan/asan_win_new_delete.cpp | 3 +--
 compiler-rt/lib/asan/asan_win_thunk_common.h | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_win_new_delete.cpp b/compiler-rt/lib/asan/asan_win_new_delete.cpp
index be62ce7828fd5ba..9024be167a845b3 100644
--- a/compiler-rt/lib/asan/asan_win_new_delete.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_delete.cpp
@@ -12,12 +12,11 @@
 //===----------------------------------------------------------------------===//
 #include <stddef.h>
 
-#include "asan_win_thunk_common.h"
 #include "asan_allocator.h"
 #include "asan_internal.h"
 #include "asan_report.h"
 #include "asan_stack.h"
-
+#include "asan_win_thunk_common.h"
 
 using __asan_win_new_delete_data = __sanitizer::__asan_win_stack_data;
 
diff --git a/compiler-rt/lib/asan/asan_win_thunk_common.h b/compiler-rt/lib/asan/asan_win_thunk_common.h
index 2957de4dd3e29a8..5a9106cc447944f 100644
--- a/compiler-rt/lib/asan/asan_win_thunk_common.h
+++ b/compiler-rt/lib/asan/asan_win_thunk_common.h
@@ -48,4 +48,4 @@ struct __asan_win_stack_data {
   __sanitizer::uptr caller_pc;
 };
 
-}
\ No newline at end of file
+}  // namespace __sanitizer
\ No newline at end of file

>From dfdd9a282cce8bf0e811f750328e5a89c9fba459 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Tue, 31 Oct 2023 15:44:37 -0700
Subject: [PATCH 13/19] remove usage of special _WIN stack trace functions

---
 .../asan_win_delete_array_align_thunk.cpp     |  6 +-
 ...asan_win_delete_array_size_align_thunk.cpp |  6 +-
 .../asan/asan_win_delete_array_size_thunk.cpp |  6 +-
 .../lib/asan/asan_win_delete_array_thunk.cpp  |  6 +-
 .../asan_win_delete_scalar_align_thunk.cpp    |  6 +-
 ...san_win_delete_scalar_size_align_thunk.cpp |  6 +-
 .../asan_win_delete_scalar_size_thunk.cpp     |  6 +-
 .../lib/asan/asan_win_delete_scalar_thunk.cpp |  6 +-
 ...asan_win_new_array_align_nothrow_thunk.cpp |  6 +-
 .../asan/asan_win_new_array_align_thunk.cpp   |  6 +-
 .../asan/asan_win_new_array_nothrow_thunk.cpp |  6 +-
 .../lib/asan/asan_win_new_array_thunk.cpp     |  5 +-
 compiler-rt/lib/asan/asan_win_new_delete.cpp  | 69 ++++++-------------
 .../asan/asan_win_new_delete_thunk_common.h   |  3 +-
 ...san_win_new_scalar_align_nothrow_thunk.cpp |  5 +-
 .../asan/asan_win_new_scalar_align_thunk.cpp  |  5 +-
 .../asan_win_new_scalar_nothrow_thunk.cpp     |  5 +-
 .../lib/asan/asan_win_new_scalar_thunk.cpp    |  5 +-
 compiler-rt/lib/asan/asan_win_thunk_common.h  | 51 --------------
 19 files changed, 55 insertions(+), 159 deletions(-)
 delete mode 100644 compiler-rt/lib/asan/asan_win_thunk_common.h

diff --git a/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp
index eb7351a3e9d5f50..2aefb6f70ba53f8 100644
--- a/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp
@@ -33,15 +33,13 @@
 
 __asan_InitDefine<op_delete_array_align> init_delete_array_align;
 
-extern "C" void __cdecl __asan_delete_array_align(
-    __asan_win_new_delete_data* data, void* ptr, std::align_val_t align);
+extern "C" void __cdecl __asan_delete_array_align(void* ptr, std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void operator delete[](void* ptr, std::align_val_t align) noexcept {
   if (__asan_InitDefine<op_delete_scalar_align>::defined) {
-    __asan_win_new_delete_data data{};
-    __asan_delete_array_align(&data, ptr, align);
+    __asan_delete_array_align(ptr, align);
   } else {
     operator delete(ptr, align);
   }
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp
index d27e2ebb83fd37d..a8ac74d709db5d2 100644
--- a/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp
@@ -31,8 +31,7 @@
 // +-----------------------+  +--------------------------+
 // clang-format on
 
-extern "C" void __cdecl __asan_delete_array_size_align(
-    __asan_win_new_delete_data* data, void* ptr, size_t size,
+extern "C" void __cdecl __asan_delete_array_size_align(void* ptr, size_t size,
     std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
@@ -41,8 +40,7 @@ void operator delete[](void* ptr, size_t size,
                        std::align_val_t align) noexcept {
   if (__asan_InitDefine<op_delete_scalar_align>::defined &&
       __asan_InitDefine<op_delete_array_align>::defined) {
-    __asan_win_new_delete_data data{};
-    __asan_delete_array_size_align(&data, ptr, size, align);
+    __asan_delete_array_size_align(ptr, size, align);
   } else {
     operator delete[](ptr, align);
   }
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_size_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_size_thunk.cpp
index 0720b6337bc7a67..d59619cedc8b505 100644
--- a/compiler-rt/lib/asan/asan_win_delete_array_size_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_array_size_thunk.cpp
@@ -31,16 +31,14 @@
 // +-----------------+  +--------------------+
 // clang-format on
 
-extern "C" void __cdecl __asan_delete_array_size(
-    __asan_win_new_delete_data* data, void* ptr, size_t size);
+extern "C" void __cdecl __asan_delete_array_size(void* ptr, size_t size);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void operator delete[](void* ptr, size_t size) noexcept {
   if (__asan_InitDefine<op_delete_scalar>::defined &&
       __asan_InitDefine<op_delete_array>::defined) {
-    __asan_win_new_delete_data data{};
-    __asan_delete_array_size(&data, ptr, size);
+    __asan_delete_array_size(ptr, size);
   } else {
     operator delete[](ptr);
   }
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_thunk.cpp
index 02e8b7a5af80b64..e06ba3703d63877 100644
--- a/compiler-rt/lib/asan/asan_win_delete_array_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_array_thunk.cpp
@@ -33,15 +33,13 @@
 
 __asan_InitDefine<op_delete_array> init_delete_array;
 
-extern "C" void __cdecl __asan_delete_array(__asan_win_new_delete_data* data,
-                                            void* ptr);
+extern "C" void __cdecl __asan_delete_array(void* ptr);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void operator delete[](void* ptr) noexcept {
   if (__asan_InitDefine<op_delete_scalar>::defined) {
-    __asan_win_new_delete_data data{};
-    __asan_delete_array(&data, ptr);
+    __asan_delete_array(ptr);
   } else {
     operator delete(ptr);
   }
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_align_thunk.cpp
index b9a53963fc6d711..9f8afc5e2b2d1f8 100644
--- a/compiler-rt/lib/asan/asan_win_delete_scalar_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_align_thunk.cpp
@@ -33,12 +33,10 @@
 
 __asan_InitDefine<op_delete_scalar_align> init_delete_scalar_align;
 
-extern "C" void __cdecl __asan_delete_align(__asan_win_new_delete_data* data,
-                                            void* ptr, std::align_val_t align);
+extern "C" void __cdecl __asan_delete_align(void* ptr, std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void operator delete(void* ptr, std::align_val_t align) noexcept {
-  __asan_win_new_delete_data data{};
-  __asan_delete_align(&data, ptr, align);
+  __asan_delete_align(ptr, align);
 }
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp
index 6bcc00f4f12a5da..c874159671c0ba8 100644
--- a/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp
@@ -31,16 +31,14 @@
 // +-----------------------+  +--------------------------+
 // clang-format on
 
-extern "C" void __cdecl __asan_delete_size_align(
-    __asan_win_new_delete_data* data, void* ptr, size_t size,
+extern "C" void __cdecl __asan_delete_size_align(void* ptr, size_t size,
     std::align_val_t align) noexcept;
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void operator delete(void* ptr, size_t size, std::align_val_t align) noexcept {
   if (__asan_InitDefine<op_delete_scalar_align>::defined) {
-    __asan_win_new_delete_data data{};
-    __asan_delete_size_align(&data, ptr, size, align);
+    __asan_delete_size_align(ptr, size, align);
   } else {
     operator delete(ptr, align);
   }
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_size_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_size_thunk.cpp
index 31e2846995e6321..1528f7abfdc4879 100644
--- a/compiler-rt/lib/asan/asan_win_delete_scalar_size_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_size_thunk.cpp
@@ -31,15 +31,13 @@
 // +-----------------+  +--------------------+
 // clang-format on
 
-extern "C" void __cdecl __asan_delete_size(__asan_win_new_delete_data* data,
-                                           void* ptr, size_t size);
+extern "C" void __cdecl __asan_delete_size(void* ptr, size_t size);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void operator delete(void* ptr, size_t size) noexcept {
   if (__asan_InitDefine<op_delete_scalar>::defined) {
-    __asan_win_new_delete_data data{};
-    __asan_delete_size(&data, ptr, size);
+    __asan_delete_size(ptr, size);
   } else {
     operator delete(ptr);
   }
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp
index 38d3899816b0486..1b9f53c42f5eee1 100644
--- a/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp
@@ -33,12 +33,10 @@
 
 __asan_InitDefine<op_delete_scalar> init_delete_scalar;
 
-extern "C" void __cdecl __asan_delete(__asan_win_new_delete_data* data,
-                                      void* ptr);
+extern "C" void __cdecl __asan_delete(void* ptr);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void operator delete(void* ptr) noexcept {
-  __asan_win_new_delete_data data{};
-  __asan_delete(&data, ptr);
+  __asan_delete(ptr);
 }
diff --git a/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp
index bf8bc78ec4206a3..f0ba1a04c8ad55b 100644
--- a/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp
@@ -29,8 +29,7 @@
 //                     +-----------------------+
 // clang-format on
 
-extern "C" void* __cdecl __asan_new_array_align_nothrow(
-    __asan_win_new_delete_data* data, size_t size, std::align_val_t align);
+extern "C" void* __cdecl __asan_new_array_align_nothrow(size_t size, std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
@@ -38,8 +37,7 @@ void* operator new[](size_t size, std::align_val_t align,
                      std::nothrow_t const&) noexcept {
   if (__asan_InitDefine<op_new_scalar_align>::defined &&
       __asan_InitDefine<op_new_array_align>::defined) {
-    __asan_win_new_delete_data data{};
-    return __asan_new_array_align_nothrow(&data, size, align);
+    return __asan_new_array_align_nothrow(size, align);
   }
 
   try {
diff --git a/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp
index faa39b2a008b0d7..34fff88cdeff77e 100644
--- a/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp
@@ -31,15 +31,13 @@
 
 __asan_InitDefine<op_new_array_align> init_new_array_align;
 
-extern "C" void* __cdecl __asan_new_array_align(
-    __asan_win_new_delete_data* data, size_t size, std::align_val_t align);
+extern "C" void* __cdecl __asan_new_array_align(size_t size, std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void* operator new[](size_t size, std::align_val_t align) {
   if (__asan_InitDefine<op_new_scalar_align>::defined) {
-    __asan_win_new_delete_data data{};
-    return __asan_new_array_align(&data, size, align);
+    return __asan_new_array_align(size, align);
   }
 
   return operator new(size, align);
diff --git a/compiler-rt/lib/asan/asan_win_new_array_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_nothrow_thunk.cpp
index 526e9abf54d1e0d..ea882e7f7e3c13b 100644
--- a/compiler-rt/lib/asan/asan_win_new_array_nothrow_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_array_nothrow_thunk.cpp
@@ -29,16 +29,14 @@
 //               +-----------------+
 // clang-format on
 
-extern "C" void* __cdecl __asan_new_array_nothrow(
-    __asan_win_new_delete_data* data, size_t size);
+extern "C" void* __cdecl __asan_new_array_nothrow(size_t size);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void* operator new[](size_t size, std::nothrow_t const&) noexcept {
   if (__asan_InitDefine<op_new_scalar>::defined &&
       __asan_InitDefine<op_new_array>::defined) {
-    __asan_win_new_delete_data data{};
-    return __asan_new_array_nothrow(&data, size);
+    return __asan_new_array_nothrow(size);
   }
 
   try {
diff --git a/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp
index b848e343f81b845..a0571682f39a236 100644
--- a/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp
@@ -31,15 +31,14 @@
 
 __asan_InitDefine<op_new_array> init_new_array;
 
-extern "C" void* __cdecl __asan_new_array(__asan_win_new_delete_data* data,
+extern "C" void* __cdecl __asan_new_array(
                                           size_t size);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void* operator new[](size_t size) {
   if (__asan_InitDefine<op_new_scalar>::defined) {
-    __asan_win_new_delete_data data{};
-    return __asan_new_array(&data, size);
+    return __asan_new_array(size);
   }
   return operator new(size);
 }
diff --git a/compiler-rt/lib/asan/asan_win_new_delete.cpp b/compiler-rt/lib/asan/asan_win_new_delete.cpp
index 9024be167a845b3..ba0b3215579e710 100644
--- a/compiler-rt/lib/asan/asan_win_new_delete.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_delete.cpp
@@ -16,9 +16,6 @@
 #include "asan_internal.h"
 #include "asan_report.h"
 #include "asan_stack.h"
-#include "asan_win_thunk_common.h"
-
-using __asan_win_new_delete_data = __sanitizer::__asan_win_stack_data;
 
 // Fake std::align_val_t to avoid including <new>.
 namespace std {
@@ -28,126 +25,104 @@ enum class align_val_t : size_t {};
 using namespace __asan;
 
 #define OPERATOR_NEW_BODY(type, nothrow)                          \
-  GET_STACK_TRACE_MALLOC_WIN(data->pc, data->bp, data->caller_pc, \
-                             data->extra_context);                \
+  GET_STACK_TRACE_MALLOC \
   void *res = asan_memalign(0, size, &stack, type);               \
   if (!nothrow && UNLIKELY(!res))                                 \
     ReportOutOfMemory(size, &stack);                              \
   return res;
 
 #define OPERATOR_NEW_BODY_ALIGN(type, nothrow)                    \
-  GET_STACK_TRACE_MALLOC_WIN(data->pc, data->bp, data->caller_pc, \
-                             data->extra_context);                \
+  GET_STACK_TRACE_MALLOC \
   void *res = asan_memalign((uptr)align, size, &stack, type);     \
   if (!nothrow && UNLIKELY(!res))                                 \
     ReportOutOfMemory(size, &stack);                              \
   return res;
 
 #define OPERATOR_DELETE_BODY(type)                              \
-  GET_STACK_TRACE_FREE_WIN(data->pc, data->bp, data->caller_pc, \
-                           data->extra_context);                \
+  GET_STACK_TRACE_FREE \
   asan_delete(ptr, 0, 0, &stack, type);
 
 #define OPERATOR_DELETE_BODY_SIZE(type)                         \
-  GET_STACK_TRACE_FREE_WIN(data->pc, data->bp, data->caller_pc, \
-                           data->extra_context);                \
+  GET_STACK_TRACE_FREE \
   asan_delete(ptr, size, 0, &stack, type);
 
 #define OPERATOR_DELETE_BODY_ALIGN(type)                        \
-  GET_STACK_TRACE_FREE_WIN(data->pc, data->bp, data->caller_pc, \
-                           data->extra_context);                \
+  GET_STACK_TRACE_FREE \
   asan_delete(ptr, 0, static_cast<uptr>(align), &stack, type);
 
 #define OPERATOR_DELETE_BODY_SIZE_ALIGN(type)                   \
-  GET_STACK_TRACE_FREE_WIN(data->pc, data->bp, data->caller_pc, \
-                           data->extra_context);                \
+  GET_STACK_TRACE_FREE \
   asan_delete(ptr, size, static_cast<uptr>(align), &stack, type);
 
 extern "C" {
-__declspec(dllexport) void *__cdecl __asan_new(
-    __asan_win_new_delete_data *const data, size_t const size) {
+__declspec(dllexport) void *__cdecl __asan_new(size_t const size) {
   OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_array(
-    __asan_win_new_delete_data *const data, size_t const size) {
+__declspec(dllexport) void *__cdecl __asan_new_array(size_t const size) {
   OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_nothrow(
-    __asan_win_new_delete_data *const data, size_t const size) {
+__declspec(dllexport) void *__cdecl __asan_new_nothrow(size_t const size) {
   OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_array_nothrow(
-    __asan_win_new_delete_data *const data, size_t const size) {
+__declspec(dllexport) void *__cdecl __asan_new_array_nothrow(size_t const size) {
   OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_align(
-    __asan_win_new_delete_data *const data, size_t const size,
+__declspec(dllexport) void *__cdecl __asan_new_align(size_t const size,
     std::align_val_t const align) {
   OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_array_align(
-    __asan_win_new_delete_data *const data, size_t const size,
+__declspec(dllexport) void *__cdecl __asan_new_array_align(size_t const size,
     std::align_val_t const align) {
   OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_align_nothrow(
-    __asan_win_new_delete_data *const data, size_t const size,
+__declspec(dllexport) void *__cdecl __asan_new_align_nothrow(size_t const size,
     std::align_val_t const align) {
   OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_array_align_nothrow(
-    __asan_win_new_delete_data *const data, size_t const size,
+__declspec(dllexport) void *__cdecl __asan_new_array_align_nothrow(size_t const size,
     std::align_val_t const align) {
   OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete(
-    __asan_win_new_delete_data *const data, void *ptr) {
+__declspec(dllexport) void __cdecl __asan_delete(void *ptr) {
   OPERATOR_DELETE_BODY(FROM_NEW);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_array(
-    __asan_win_new_delete_data *const data, void *ptr) {
+__declspec(dllexport) void __cdecl __asan_delete_array(void *ptr) {
   OPERATOR_DELETE_BODY(FROM_NEW_BR);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_size(
-    __asan_win_new_delete_data *const data, void *ptr, size_t const size) {
+__declspec(dllexport) void __cdecl __asan_delete_size(void *ptr, size_t const size) {
   OPERATOR_DELETE_BODY_SIZE(FROM_NEW);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_array_size(
-    __asan_win_new_delete_data *const data, void *ptr, size_t const size) {
+__declspec(dllexport) void __cdecl __asan_delete_array_size(void *ptr, size_t const size) {
   OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_align(
-    __asan_win_new_delete_data *const data, void *ptr,
+__declspec(dllexport) void __cdecl __asan_delete_align(void *ptr,
     std::align_val_t const align) {
   OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_array_align(
-    __asan_win_new_delete_data *const data, void *ptr,
+__declspec(dllexport) void __cdecl __asan_delete_array_align(void *ptr,
     std::align_val_t const align) {
   OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_size_align(
-    __asan_win_new_delete_data *const data, void *ptr, size_t const size,
+__declspec(dllexport) void __cdecl __asan_delete_size_align(void *ptr, size_t const size,
     std::align_val_t const align) {
   OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_array_size_align(
-    __asan_win_new_delete_data *const data, void *ptr, size_t const size,
+__declspec(dllexport) void __cdecl __asan_delete_array_size_align(void *ptr, size_t const size,
     std::align_val_t const align) {
   OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR);
 }
diff --git a/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
index e9715acb4ea1e8d..cd25b26e4dd4294 100644
--- a/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
+++ b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
@@ -23,7 +23,7 @@
 // initializer to those TUs to mark whether that overload is included.
 //===----------------------------------------------------------------------===//
 
-#include "asan_win_thunk_common.h"
+#include <sanitizer_common/sanitizer_internal_defs.h>
 // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
 namespace std {
 struct nothrow_t {};
@@ -35,7 +35,6 @@ void* operator new[](size_t, std::align_val_t);
 void operator delete(void* ptr, std::align_val_t align);
 void operator delete[](void* ptr, std::align_val_t align);
 
-using __asan_win_new_delete_data = __sanitizer::__asan_win_stack_data;
 
 ////////////////////////////////////
 // clang-format off
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
index a6ae7c6890667f4..685bef562e6f962 100644
--- a/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
@@ -29,8 +29,7 @@
 //                     +-----------------------+
 // clang-format on
 
-extern "C" void* __cdecl __asan_new_align_nothrow(
-    __asan_win_new_delete_data* data, size_t size, std::align_val_t align);
+extern "C" void* __cdecl __asan_new_align_nothrow(size_t size, std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
@@ -38,7 +37,7 @@ void* operator new(size_t size, std::align_val_t align,
                    std::nothrow_t const&) noexcept {
   if (__asan_InitDefine<op_new_scalar_align>::defined) {
     __asan_win_new_delete_data data{};
-    return __asan_new_align_nothrow(&data, size, align);
+    return __asan_new_align_nothrow(size, align);
   }
 
   try {
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp
index dfffb956657c69e..c7633615d0115fc 100644
--- a/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp
@@ -31,12 +31,11 @@
 
 __asan_InitDefine<op_new_scalar_align> init_new_scalar_align;
 
-extern "C" void* __cdecl __asan_new_align(__asan_win_new_delete_data* data,
+extern "C" void* __cdecl __asan_new_align(
                                           size_t size, std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void* operator new(size_t size, std::align_val_t align) {
-  __asan_win_new_delete_data data{};
-  return __asan_new_align(&data, size, align);
+  return __asan_new_align(size, align);
 }
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp
index 53306d435a75ac3..b80075f4835b0ad 100644
--- a/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp
@@ -29,15 +29,14 @@
 //               +-----------------+
 // clang-format on
 
-extern "C" void* __cdecl __asan_new_nothrow(__asan_win_new_delete_data* data,
+extern "C" void* __cdecl __asan_new_nothrow(
                                             size_t size);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void* operator new(size_t size, std::nothrow_t const&) noexcept {
   if (__asan_InitDefine<op_new_scalar>::defined) {
-    __asan_win_new_delete_data data{};
-    return __asan_new_nothrow(&data, size);
+    return __asan_new_nothrow(size);
   }
 
   try {
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp
index 47d9fa84ce55124..5bc2ffce6515879 100644
--- a/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp
@@ -31,12 +31,11 @@
 
 __asan_InitDefine<op_new_scalar> init_new_scalar;
 
-extern "C" void* __cdecl __asan_new(__asan_win_new_delete_data* data,
+extern "C" void* __cdecl __asan_new(
                                     size_t size);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
 void* operator new(size_t size) {
-  __asan_win_new_delete_data data{};
-  return __asan_new(&data, size);
+  return __asan_new(size);
 }
diff --git a/compiler-rt/lib/asan/asan_win_thunk_common.h b/compiler-rt/lib/asan/asan_win_thunk_common.h
deleted file mode 100644
index 5a9106cc447944f..000000000000000
--- a/compiler-rt/lib/asan/asan_win_thunk_common.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===-- asan_win_thunk_common.h  --------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// Windows-specific common utilities to communicate between static and DLL
-// portions of the ASAN runtime.
-//
-// This file must not include any core components of the ASAN runtime as it must
-// be able to be included in the portions statically linked with the user
-// program.
-//
-//===----------------------------------------------------------------------===//
-
-#pragma once
-#include <sanitizer_common/sanitizer_internal_defs.h>
-namespace __sanitizer {
-
-__declspec(noinline) inline __sanitizer::uptr __asan_GetCurrentPc() {
-  return GET_CALLER_PC();
-}
-
-struct __asan_win_stack_data {
-  // Put calls to get pc, bp, and caller_pc in ctor arguments so they occur in
-  // the calling frame and don't rely on inlining to get correct stack
-  // information.
-  __forceinline explicit __asan_win_stack_data(
-      __sanitizer::uptr pc_arg = __asan_GetCurrentPc(),
-      __sanitizer::uptr bp_arg = GET_CURRENT_FRAME(),
-      __sanitizer::uptr caller_pc_arg = GET_CALLER_PC())
-      : size(sizeof(__asan_win_stack_data)),
-        extra_context(2),  // TODO: Should only need one - investigate why we
-                           // need an extra frame.
-        pc(pc_arg),
-        bp(bp_arg),
-        caller_pc(caller_pc_arg) {}
-
-  size_t size;        // Size of this struct (it travels over the DLL boundary).
-  int extra_context;  // Number of extra frames we need to collect in the
-                      // backtrace.
-  __sanitizer::uptr pc;
-  __sanitizer::uptr bp;
-  __sanitizer::uptr caller_pc;
-};
-
-}  // namespace __sanitizer
\ No newline at end of file

>From 541f6f43d911e619ce1dcf2367fa94a5f85acd71 Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Thu, 2 Nov 2023 18:44:55 -0700
Subject: [PATCH 14/19] enable exception handling in asan under MSVC

---
 compiler-rt/lib/asan/CMakeLists.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index 049fbc32815c89c..989beec973677cb 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -127,6 +127,7 @@ set(ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
 set(ASAN_COMMON_DEFINITIONS ${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION})
 
 append_rtti_flag(OFF ASAN_CFLAGS)
+append_list_if(MSVC /EHsc ASAN_CFLAGS)
 
 # Silence warnings in system headers with MSVC.
 if(NOT CLANG_CL)

>From 3a0dbeafa6b9c135e602380b489a928482e9ac9f Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Mon, 6 Nov 2023 16:52:46 -0800
Subject: [PATCH 15/19] clang format

---
 .../asan_win_delete_array_align_thunk.cpp     |  3 +-
 ...asan_win_delete_array_size_align_thunk.cpp |  2 +-
 ...san_win_delete_scalar_size_align_thunk.cpp |  4 +-
 .../lib/asan/asan_win_delete_scalar_thunk.cpp |  4 +-
 ...asan_win_new_array_align_nothrow_thunk.cpp |  3 +-
 .../asan/asan_win_new_array_align_thunk.cpp   |  3 +-
 .../lib/asan/asan_win_new_array_thunk.cpp     |  3 +-
 compiler-rt/lib/asan/asan_win_new_delete.cpp  | 77 ++++++++++---------
 .../asan/asan_win_new_delete_thunk_common.h   |  1 -
 ...san_win_new_scalar_align_nothrow_thunk.cpp |  3 +-
 .../asan/asan_win_new_scalar_align_thunk.cpp  |  3 +-
 .../asan_win_new_scalar_nothrow_thunk.cpp     |  3 +-
 .../lib/asan/asan_win_new_scalar_thunk.cpp    |  7 +-
 13 files changed, 57 insertions(+), 59 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp
index 2aefb6f70ba53f8..44e1ed1af23e7b2 100644
--- a/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_array_align_thunk.cpp
@@ -33,7 +33,8 @@
 
 __asan_InitDefine<op_delete_array_align> init_delete_array_align;
 
-extern "C" void __cdecl __asan_delete_array_align(void* ptr, std::align_val_t align);
+extern "C" void __cdecl __asan_delete_array_align(void* ptr,
+                                                  std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
diff --git a/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp
index a8ac74d709db5d2..88d18073ffee64a 100644
--- a/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_array_size_align_thunk.cpp
@@ -32,7 +32,7 @@
 // clang-format on
 
 extern "C" void __cdecl __asan_delete_array_size_align(void* ptr, size_t size,
-    std::align_val_t align);
+                                                       std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp
index c874159671c0ba8..1538f92a947dba2 100644
--- a/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_size_align_thunk.cpp
@@ -31,8 +31,8 @@
 // +-----------------------+  +--------------------------+
 // clang-format on
 
-extern "C" void __cdecl __asan_delete_size_align(void* ptr, size_t size,
-    std::align_val_t align) noexcept;
+extern "C" void __cdecl __asan_delete_size_align(
+    void* ptr, size_t size, std::align_val_t align) noexcept;
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
diff --git a/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp b/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp
index 1b9f53c42f5eee1..f93af4eb6c5d2c1 100644
--- a/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_delete_scalar_thunk.cpp
@@ -37,6 +37,4 @@ extern "C" void __cdecl __asan_delete(void* ptr);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
-void operator delete(void* ptr) noexcept {
-  __asan_delete(ptr);
-}
+void operator delete(void* ptr) noexcept { __asan_delete(ptr); }
diff --git a/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp
index f0ba1a04c8ad55b..da416e1dffed591 100644
--- a/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_array_align_nothrow_thunk.cpp
@@ -29,7 +29,8 @@
 //                     +-----------------------+
 // clang-format on
 
-extern "C" void* __cdecl __asan_new_array_align_nothrow(size_t size, std::align_val_t align);
+extern "C" void* __cdecl __asan_new_array_align_nothrow(size_t size,
+                                                        std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
diff --git a/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp
index 34fff88cdeff77e..f7426a91716874a 100644
--- a/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_array_align_thunk.cpp
@@ -31,7 +31,8 @@
 
 __asan_InitDefine<op_new_array_align> init_new_array_align;
 
-extern "C" void* __cdecl __asan_new_array_align(size_t size, std::align_val_t align);
+extern "C" void* __cdecl __asan_new_array_align(size_t size,
+                                                std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
diff --git a/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp
index a0571682f39a236..c99739339fac182 100644
--- a/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_array_thunk.cpp
@@ -31,8 +31,7 @@
 
 __asan_InitDefine<op_new_array> init_new_array;
 
-extern "C" void* __cdecl __asan_new_array(
-                                          size_t size);
+extern "C" void* __cdecl __asan_new_array(size_t size);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
diff --git a/compiler-rt/lib/asan/asan_win_new_delete.cpp b/compiler-rt/lib/asan/asan_win_new_delete.cpp
index ba0b3215579e710..a3db56ffef7a96e 100644
--- a/compiler-rt/lib/asan/asan_win_new_delete.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_delete.cpp
@@ -24,34 +24,34 @@ enum class align_val_t : size_t {};
 
 using namespace __asan;
 
-#define OPERATOR_NEW_BODY(type, nothrow)                          \
-  GET_STACK_TRACE_MALLOC \
-  void *res = asan_memalign(0, size, &stack, type);               \
-  if (!nothrow && UNLIKELY(!res))                                 \
-    ReportOutOfMemory(size, &stack);                              \
+#define OPERATOR_NEW_BODY(type, nothrow)            \
+  GET_STACK_TRACE_MALLOC                            \
+  void *res = asan_memalign(0, size, &stack, type); \
+  if (!nothrow && UNLIKELY(!res))                   \
+    ReportOutOfMemory(size, &stack);                \
   return res;
 
-#define OPERATOR_NEW_BODY_ALIGN(type, nothrow)                    \
-  GET_STACK_TRACE_MALLOC \
-  void *res = asan_memalign((uptr)align, size, &stack, type);     \
-  if (!nothrow && UNLIKELY(!res))                                 \
-    ReportOutOfMemory(size, &stack);                              \
+#define OPERATOR_NEW_BODY_ALIGN(type, nothrow)                \
+  GET_STACK_TRACE_MALLOC                                      \
+  void *res = asan_memalign((uptr)align, size, &stack, type); \
+  if (!nothrow && UNLIKELY(!res))                             \
+    ReportOutOfMemory(size, &stack);                          \
   return res;
 
-#define OPERATOR_DELETE_BODY(type)                              \
-  GET_STACK_TRACE_FREE \
+#define OPERATOR_DELETE_BODY(type) \
+  GET_STACK_TRACE_FREE             \
   asan_delete(ptr, 0, 0, &stack, type);
 
-#define OPERATOR_DELETE_BODY_SIZE(type)                         \
-  GET_STACK_TRACE_FREE \
+#define OPERATOR_DELETE_BODY_SIZE(type) \
+  GET_STACK_TRACE_FREE                  \
   asan_delete(ptr, size, 0, &stack, type);
 
-#define OPERATOR_DELETE_BODY_ALIGN(type)                        \
-  GET_STACK_TRACE_FREE \
+#define OPERATOR_DELETE_BODY_ALIGN(type) \
+  GET_STACK_TRACE_FREE                   \
   asan_delete(ptr, 0, static_cast<uptr>(align), &stack, type);
 
-#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type)                   \
-  GET_STACK_TRACE_FREE \
+#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \
+  GET_STACK_TRACE_FREE                        \
   asan_delete(ptr, size, static_cast<uptr>(align), &stack, type);
 
 extern "C" {
@@ -67,27 +67,28 @@ __declspec(dllexport) void *__cdecl __asan_new_nothrow(size_t const size) {
   OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_array_nothrow(size_t const size) {
+__declspec(dllexport) void *__cdecl __asan_new_array_nothrow(
+    size_t const size) {
   OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_align(size_t const size,
-    std::align_val_t const align) {
+__declspec(dllexport) void *__cdecl __asan_new_align(
+    size_t const size, std::align_val_t const align) {
   OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_array_align(size_t const size,
-    std::align_val_t const align) {
+__declspec(dllexport) void *__cdecl __asan_new_array_align(
+    size_t const size, std::align_val_t const align) {
   OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_align_nothrow(size_t const size,
-    std::align_val_t const align) {
+__declspec(dllexport) void *__cdecl __asan_new_align_nothrow(
+    size_t const size, std::align_val_t const align) {
   OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/);
 }
 
-__declspec(dllexport) void *__cdecl __asan_new_array_align_nothrow(size_t const size,
-    std::align_val_t const align) {
+__declspec(dllexport) void *__cdecl __asan_new_array_align_nothrow(
+    size_t const size, std::align_val_t const align) {
   OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/);
 }
 
@@ -99,31 +100,33 @@ __declspec(dllexport) void __cdecl __asan_delete_array(void *ptr) {
   OPERATOR_DELETE_BODY(FROM_NEW_BR);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_size(void *ptr, size_t const size) {
+__declspec(dllexport) void __cdecl __asan_delete_size(void *ptr,
+                                                      size_t const size) {
   OPERATOR_DELETE_BODY_SIZE(FROM_NEW);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_array_size(void *ptr, size_t const size) {
+__declspec(dllexport) void __cdecl __asan_delete_array_size(void *ptr,
+                                                            size_t const size) {
   OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_align(void *ptr,
-    std::align_val_t const align) {
+__declspec(dllexport) void __cdecl __asan_delete_align(
+    void *ptr, std::align_val_t const align) {
   OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_array_align(void *ptr,
-    std::align_val_t const align) {
+__declspec(dllexport) void __cdecl __asan_delete_array_align(
+    void *ptr, std::align_val_t const align) {
   OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_size_align(void *ptr, size_t const size,
-    std::align_val_t const align) {
+__declspec(dllexport) void __cdecl __asan_delete_size_align(
+    void *ptr, size_t const size, std::align_val_t const align) {
   OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW);
 }
 
-__declspec(dllexport) void __cdecl __asan_delete_array_size_align(void *ptr, size_t const size,
-    std::align_val_t const align) {
+__declspec(dllexport) void __cdecl __asan_delete_array_size_align(
+    void *ptr, size_t const size, std::align_val_t const align) {
   OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR);
 }
 }  // extern "C"
diff --git a/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
index cd25b26e4dd4294..710248181e5078a 100644
--- a/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
+++ b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
@@ -35,7 +35,6 @@ void* operator new[](size_t, std::align_val_t);
 void operator delete(void* ptr, std::align_val_t align);
 void operator delete[](void* ptr, std::align_val_t align);
 
-
 ////////////////////////////////////
 // clang-format off
 // Fallback Ordering for new/delete
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
index 685bef562e6f962..ac584a720ee6057 100644
--- a/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
@@ -29,7 +29,8 @@
 //                     +-----------------------+
 // clang-format on
 
-extern "C" void* __cdecl __asan_new_align_nothrow(size_t size, std::align_val_t align);
+extern "C" void* __cdecl __asan_new_align_nothrow(size_t size,
+                                                  std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp
index c7633615d0115fc..0fc2523154cb5de 100644
--- a/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_align_thunk.cpp
@@ -31,8 +31,7 @@
 
 __asan_InitDefine<op_new_scalar_align> init_new_scalar_align;
 
-extern "C" void* __cdecl __asan_new_align(
-                                          size_t size, std::align_val_t align);
+extern "C" void* __cdecl __asan_new_align(size_t size, std::align_val_t align);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp
index b80075f4835b0ad..ef29a37dc2f61f2 100644
--- a/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_nothrow_thunk.cpp
@@ -29,8 +29,7 @@
 //               +-----------------+
 // clang-format on
 
-extern "C" void* __cdecl __asan_new_nothrow(
-                                            size_t size);
+extern "C" void* __cdecl __asan_new_nothrow(size_t size);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp
index 5bc2ffce6515879..8be32956f737d06 100644
--- a/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_thunk.cpp
@@ -31,11 +31,8 @@
 
 __asan_InitDefine<op_new_scalar> init_new_scalar;
 
-extern "C" void* __cdecl __asan_new(
-                                    size_t size);
+extern "C" void* __cdecl __asan_new(size_t size);
 
 // Avoid tailcall optimization to preserve stack frame.
 #pragma optimize("", off)
-void* operator new(size_t size) {
-  return __asan_new(size);
-}
+void* operator new(size_t size) { return __asan_new(size); }

>From 9fd02b3b7a32b7a92ea0343a0395b980d6bd136d Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Mon, 6 Nov 2023 16:47:17 -0800
Subject: [PATCH 16/19] remove special stack trace functions from new/delete
 overrides for windows

---
 compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h       | 4 ++--
 .../lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp      | 1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
index 710248181e5078a..07e65d5359ced47 100644
--- a/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
+++ b/compiler-rt/lib/asan/asan_win_new_delete_thunk_common.h
@@ -32,8 +32,8 @@ enum class align_val_t : size_t {};
 
 void* operator new(size_t, std::align_val_t);
 void* operator new[](size_t, std::align_val_t);
-void operator delete(void* ptr, std::align_val_t align);
-void operator delete[](void* ptr, std::align_val_t align);
+void operator delete(void* ptr, std::align_val_t align) noexcept;
+void operator delete[](void* ptr, std::align_val_t align) noexcept;
 
 ////////////////////////////////////
 // clang-format off
diff --git a/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp b/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
index ac584a720ee6057..b23b2d14b89f2a9 100644
--- a/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_new_scalar_align_nothrow_thunk.cpp
@@ -37,7 +37,6 @@ extern "C" void* __cdecl __asan_new_align_nothrow(size_t size,
 void* operator new(size_t size, std::align_val_t align,
                    std::nothrow_t const&) noexcept {
   if (__asan_InitDefine<op_new_scalar_align>::defined) {
-    __asan_win_new_delete_data data{};
     return __asan_new_align_nothrow(size, align);
   }
 

>From 71a6c3e1ffae6e4862fd9321e978ed583e56ef7a Mon Sep 17 00:00:00 2001
From: Charlie Barto <Charles.Barto at microsoft.com>
Date: Mon, 6 Nov 2023 16:47:35 -0800
Subject: [PATCH 17/19] make tests deal with new/delete not being on top of the
 reported stacktrace

---
 .../Windows/double_operator_delete.cpp        | 12 +++++-----
 .../new_delete_mfc_already_defined_dbg.cpp    |  2 +-
 .../Windows/operator_array_new_left_oob.cpp   |  4 ++--
 .../Windows/operator_array_new_right_oob.cpp  |  4 ++--
 .../Windows/operator_array_new_uaf.cpp        |  8 +++----
 .../operator_array_new_with_dtor_left_oob.cpp |  4 ++--
 .../operator_delete_wrong_argument.cpp        |  4 ++--
 .../Windows/operator_new_left_oob.cpp         |  4 ++--
 .../Windows/operator_new_right_oob.cpp        |  4 ++--
 .../TestCases/Windows/operator_new_uaf.cpp    |  8 +++----
 .../Windows/wrong_downcast_on_heap.cpp        |  2 +-
 .../test/asan/TestCases/large_func_test.cpp   |  4 ++--
 .../asan/TestCases/malloc_context_size.cpp    | 19 ++++++++-------
 .../test/asan/TestCases/use-after-delete.cpp  | 24 +++++++++----------
 14 files changed, 53 insertions(+), 50 deletions(-)

diff --git a/compiler-rt/test/asan/TestCases/Windows/double_operator_delete.cpp b/compiler-rt/test/asan/TestCases/Windows/double_operator_delete.cpp
index 3668a40ce01d898..3966b36738f9255 100644
--- a/compiler-rt/test/asan/TestCases/Windows/double_operator_delete.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/double_operator_delete.cpp
@@ -8,15 +8,15 @@ int main() {
   delete [] x;
   delete [] x;
   // CHECK: AddressSanitizer: attempting double-free on [[ADDR:0x[0-9a-f]+]]
-  // CHECK-NEXT: {{#0 .* operator delete}}[]
-  // CHECK-NEXT: {{#1 .* main .*double_operator_delete.cpp}}:[[@LINE-3]]
+  // CHECK: {{#1 .* operator delete}}[]
+  // CHECK-NEXT: {{#2 .* main .*double_operator_delete.cpp}}:[[@LINE-3]]
   // CHECK: [[ADDR]] is located 0 bytes inside of 168-byte region
   // CHECK-LABEL: freed by thread T0 here:
-  // CHECK-NEXT: {{#0 .* operator delete}}[]
-  // CHECK-NEXT: {{#1 .* main .*double_operator_delete.cpp}}:[[@LINE-8]]
+  // CHECK: {{#1 .* operator delete}}[]
+  // CHECK-NEXT: {{#2 .* main .*double_operator_delete.cpp}}:[[@LINE-8]]
   // CHECK-LABEL: previously allocated by thread T0 here:
-  // CHECK-NEXT: {{#0 .* operator new}}[]
-  // CHECK-NEXT: {{#1 .* main .*double_operator_delete.cpp}}:[[@LINE-12]]
+  // CHECK: {{#1 .* operator new}}[]
+  // CHECK-NEXT: {{#2 .* main .*double_operator_delete.cpp}}:[[@LINE-12]]
   return 0;
 }
 
diff --git a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp
index b7554ca288056ac..63ecf5fcfa56ac3 100644
--- a/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/new_delete_mfc_already_defined_dbg.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cl_asan -Od %s -Fe%t /link /WX
+// RUN: %clang_cl_asan -Od %s -Fe%t /MT /link /WX
 // RUN: %env_asan_opts=alloc_dealloc_mismatch=true %run %t
 
 // test fixing new already defined and mismatch between allocation and deallocation APis
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_left_oob.cpp
index 96b9378cc51786a..3ea71934dc6b10b 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_left_oob.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_left_oob.cpp
@@ -10,7 +10,7 @@ int main() {
   //
   // CHECK: [[ADDR]] is located 1 bytes before 42-byte region
   // CHECK-LABEL: allocated by thread T0 here:
-  // CHECK-NEXT: {{#0 .* operator new}}[]
-  // CHECK-NEXT: {{#1 .* main .*operator_array_new_left_oob.cpp}}:[[@LINE-9]]
+  // CHECK: #[[#NEW:]] {{.* operator new}}[]
+  // CHECK-NEXT: #[[#NEW+1]] {{.* main .*operator_array_new_left_oob.cpp}}:[[@LINE-9]]
   delete [] buffer;
 }
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_right_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_right_oob.cpp
index 1e29d752a783f92..2b3e14f98d57627 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_right_oob.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_right_oob.cpp
@@ -11,7 +11,7 @@ int main() {
   // CHECK:   {{#0 .* main .*operator_array_new_right_oob.cpp}}:[[@LINE-3]]
   // CHECK: [[ADDR]] is located 0 bytes after 42-byte region
   // CHECK: allocated by thread T0 here:
-  // CHECK:   {{#0 .* operator new}}[]
-  // CHECK:   {{#1 .* main .*operator_array_new_right_oob.cpp}}:[[@LINE-8]]
+  // CHECK: #[[#NEW:]] {{.* operator new}}[]
+  // CHECK: #[[#NEW+1]] {{.* main .*operator_array_new_right_oob.cpp}}:[[@LINE-8]]
   delete [] buffer;
 }
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_uaf.cpp
index edeee99a76530bf..cb1b510c4856bbf 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_uaf.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_uaf.cpp
@@ -12,11 +12,11 @@ int main() {
   // CHECK:   {{#0 .* main .*operator_array_new_uaf.cpp}}:[[@LINE-3]]
   // CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region
   // CHECK-LABEL: freed by thread T0 here:
-  // CHECK:   {{#0 .* operator delete}}[]
-  // CHECK:   {{#1 .* main .*operator_array_new_uaf.cpp}}:[[@LINE-8]]
+  // CHECK:   #[[#DEL:]] {{.* operator delete}}[]
+  // CHECK:   #[[#DEL+1]] {{.* main .*operator_array_new_uaf.cpp}}:[[@LINE-8]]
   // CHECK-LABEL: previously allocated by thread T0 here:
-  // CHECK:   {{#0 .* operator new}}[]
-  // CHECK:   {{#1 .* main .*operator_array_new_uaf.cpp}}:[[@LINE-12]]
+  // CHECK:   #[[#NEW:]] {{.* operator new}}[]
+  // CHECK:   #[[#NEW+1]] {{.* main .*operator_array_new_uaf.cpp}}:[[@LINE-12]]
   return 0;
 }
 
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cpp
index 06a8939b3a2a04f..929fee44693c93f 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cpp
@@ -24,7 +24,7 @@ int main() {
   //        https://code.google.com/p/address-sanitizer/issues/detail?id=314
   // CHECK: [[ADDR]] is located {{.*}} bytes before {{(172|176)}}-byte region
   // CHECK-LABEL: allocated by thread T0 here:
-  // CHECK-NEXT: {{#0 .* operator new}}[]
-  // CHECK-NEXT: {{#1 .* main .*operator_array_new_with_dtor_left_oob.cpp}}:[[@LINE-12]]
+  // CHECK: #[[#NEW:]] {{.* operator new}}[]
+  // CHECK-NEXT: #[[#NEW+1]] {{.* main .*operator_array_new_with_dtor_left_oob.cpp}}:[[@LINE-12]]
   delete [] buffer;
 }
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cpp
index f5be333a8db1866..933fab13c219656 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cpp
@@ -7,6 +7,6 @@ int main() {
   int *x = new int[42];
   delete (x + 1);
 // CHECK: AddressSanitizer: attempting free on address which was not malloc()-ed
-// CHECK:   {{#0 0x.* operator delete}}
-// CHECK:   {{#1 .* main .*operator_delete_wrong_argument.cpp}}:[[@LINE-3]]
+// CHECK:   #[[#DEL:]] {{0x.* operator delete}}
+// CHECK:   #[[#DEL+1]] {{.* main .*operator_delete_wrong_argument.cpp}}:[[@LINE-3]]
 }
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cpp
index ab104ba1a4cddef..8030ec04a245040 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cpp
@@ -11,7 +11,7 @@ int main() {
 // CHECK:   {{#0 .* main .*operator_new_left_oob.cpp}}:[[@LINE-3]]
 // CHECK: [[ADDR]] is located 1 bytes before 1-byte region
 // CHECK: allocated by thread T0 here:
-// CHECK:   {{#0 .* operator new}}
-// CHECK:   {{#1 .* main .*operator_new_left_oob.cpp}}:[[@LINE-8]]
+// CHECK:   #[[#NEW:]] {{.* operator new}}
+// CHECK:   #[[#NEW+1]] {{.* main .*operator_new_left_oob.cpp}}:[[@LINE-8]]
   delete buffer;
 }
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cpp
index 75db1498bb1a5a5..fa10bae48c34932 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cpp
@@ -11,7 +11,7 @@ int main() {
 // CHECK:   {{#0 .* main .*operator_new_right_oob.cpp}}:[[@LINE-3]]
 // CHECK: [[ADDR]] is located 0 bytes after 1-byte region
 // CHECK: allocated by thread T0 here:
-// CHECK:   {{#0 .* operator new}}
-// CHECK:   {{#1 .* main .*operator_new_right_oob.cpp}}:[[@LINE-8]]
+// CHECK:   #[[#NEW:]] {{.* operator new}}
+// CHECK:   #[[#NEW+1]] {{.* main .*operator_new_right_oob.cpp}}:[[@LINE-8]]
   delete buffer;
 }
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp
index 457e83a19f055eb..f4752612a95393c 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp
@@ -14,11 +14,11 @@ int main() {
 // CHECK:   {{#0 .* main .*operator_new_uaf.cpp}}:[[@LINE-3]]
 // CHECK: [[ADDR]] is located 0 bytes inside of 1-byte region
 // CHECK-LABEL: freed by thread T0 here:
-// CHECK:   {{#0 .* operator delete}}
-// CHECK:   {{#1 .* main .*operator_new_uaf.cpp}}:[[@LINE-8]]
+// CHECK:   #[[#DEL:]] {{.* operator delete}}
+// CHECK:   #[[#DEL+1]] {{.* main .*operator_new_uaf.cpp}}:[[@LINE-8]]
 // CHECK-LABEL: previously allocated by thread T0 here:
-// CHECK:   {{#0 .* operator new}}
-// CHECK:   {{#1 .* main .*operator_new_uaf.cpp}}:[[@LINE-12]]
+// CHECK:   #[[#NEW:]] {{.* operator new}}
+// CHECK:   #[[#NEW+1]] {{.* main .*operator_new_uaf.cpp}}:[[@LINE-12]]
   return 0;
 }
 
diff --git a/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cpp b/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cpp
index a70a86eafec6fad..cb52a0abe7c5c26 100644
--- a/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cpp
@@ -20,7 +20,7 @@ int main(void) {
 // CHECK:   {{#0 0x[0-9a-f]* in main .*wrong_downcast_on_heap.cpp}}:[[@LINE-3]]
 // CHECK: [[ADDR]] is located 0 bytes after 4-byte region
 // CHECK: allocated by thread T0 here:
-// CHECK:   #0 {{.*}} operator new
+// CHECK:   {{.*}} operator new
   return 0;
 }
 
diff --git a/compiler-rt/test/asan/TestCases/large_func_test.cpp b/compiler-rt/test/asan/TestCases/large_func_test.cpp
index 37fec8bef6ce813..4d289586ac0416f 100644
--- a/compiler-rt/test/asan/TestCases/large_func_test.cpp
+++ b/compiler-rt/test/asan/TestCases/large_func_test.cpp
@@ -50,10 +50,10 @@ int main(int argc, char **argv) {
   // CHECK: {{allocated by thread T0 here:}}
   // CHECK-Linux:  {{    #0 0x.* in operator new}}
   // CHECK-SunOS:  {{    #0 0x.* in operator new}}
-  // CHECK-Windows:{{    #0 0x.* in operator new}}
+  // CHECK-Windows:{{    #0 0x.* in __asan_new_array}}
   // CHECK-FreeBSD:{{    #0 0x.* in operator new}}
   // CHECK-Darwin: {{    #0 0x.* in .*_Zna}}
-  // CHECK-NEXT:   {{    #1 0x.* in main .*large_func_test.cpp:}}[[@LINE-10]]
+  // CHECK:   {{    0x.* in main .*large_func_test.cpp:}}[[@LINE-10]]
   int y = x[argc];
   delete[] x;
   return y;
diff --git a/compiler-rt/test/asan/TestCases/malloc_context_size.cpp b/compiler-rt/test/asan/TestCases/malloc_context_size.cpp
index e75bc48793ad135..e90cd017682a0c2 100644
--- a/compiler-rt/test/asan/TestCases/malloc_context_size.cpp
+++ b/compiler-rt/test/asan/TestCases/malloc_context_size.cpp
@@ -1,9 +1,9 @@
 // RUN: %clangxx_asan -O0 %s -o %t
-// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s
-// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s
-// RUN: %env_asan_opts=malloc_context_size=1:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s
-// RUN: %env_asan_opts=malloc_context_size=1:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s
-// RUN: %env_asan_opts=malloc_context_size=2 not %run %t 2>&1 | FileCheck %s --check-prefix=TWO
+// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,%if target={{.*-windows-.*}} %{CHECK-WIN%} %else %{CHECK-NOT-WIN%}
+// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,%if target={{.*-windows-.*}} %{CHECK-WIN%} %else %{CHECK-NOT-WIN%}
+// RUN: %env_asan_opts=malloc_context_size=1:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,%if target={{.*-windows-.*}} %{CHECK-WIN%} %else %{CHECK-NOT-WIN%}
+// RUN: %env_asan_opts=malloc_context_size=1:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,%if target={{.*-windows-.*}} %{CHECK-WIN%} %else %{CHECK-NOT-WIN%}
+// RUN: %env_asan_opts=malloc_context_size=2 not %run %t 2>&1 | FileCheck %s --check-prefixes=TWO,%if target={{.*-windows-.*}} %{TWO-WIN%} %else %{TWO-NOT-WIN%}
 
 int main() {
   char *x = new char[20];
@@ -11,17 +11,20 @@ int main() {
   return x[0];
 
   // CHECK: freed by thread T{{.*}} here:
-  // CHECK-NEXT: #0 0x{{.*}} in {{operator delete( )?\[\]|_ZdaPv}}
+  // CHECK-NOT-WIN-NEXT: #0 0x{{.*}} in {{operator delete( )?\[\]|_ZdaPv}}
+  // CHECK-WIN-NEXT: #0 0x{{.*}} in {{__asan_delete_array}}
   // CHECK-NOT: #1 0x{{.*}}
 
   // CHECK: previously allocated by thread T{{.*}} here:
-  // CHECK-NEXT: #0 0x{{.*}} in {{operator new( )?\[\]|_Znam}}
+  // CHECK-NOT-WIN-NEXT: #0 0x{{.*}} in {{operator new( )?\[\]|_Znam}}
+  // CHECK-WIN-NEXT: #0 0x{{.*}} in {{__asan_new_array}}
   // CHECK-NOT: #1 0x{{.*}}
 
   // CHECK: SUMMARY: AddressSanitizer: heap-use-after-free
 
   // TWO: previously allocated by thread T{{.*}} here:
   // TWO-NEXT: #0 0x{{.*}}
-  // TWO-NEXT: #1 0x{{.*}} in main {{.*}}malloc_context_size.cpp
+  // TWO-NOT-WIN-NEXT: #1 0x{{.*}} in main {{.*}}malloc_context_size.cpp
+  // TWO-WIN-NEXT: #1 0x{{.*}} in {{operator new( )?\[\]|_Znam}}
   // TWO: SUMMARY: AddressSanitizer: heap-use-after-free
 }
diff --git a/compiler-rt/test/asan/TestCases/use-after-delete.cpp b/compiler-rt/test/asan/TestCases/use-after-delete.cpp
index 4d0c055368bb0c5..2acb5e53e9b52bb 100644
--- a/compiler-rt/test/asan/TestCases/use-after-delete.cpp
+++ b/compiler-rt/test/asan/TestCases/use-after-delete.cpp
@@ -16,20 +16,20 @@ int main() {
   // CHECK: {{0x.* is located 5 bytes inside of 10-byte region .0x.*,0x.*}}
 
   // CHECK: {{freed by thread T0 here:}}
-  // CHECK-Linux:  {{    #0 0x.* in operator delete\[\]}}
-  // CHECK-SunOS:  {{    #0 0x.* in operator delete\[\]}}
-  // CHECK-Windows:{{    #0 0x.* in operator delete\[\]}}
-  // CHECK-FreeBSD:{{    #0 0x.* in operator delete\[\]}}
-  // CHECK-Darwin: {{    #0 0x.* in .*_Zda}}
-  // CHECK-NEXT:   {{    #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-14]]
+  // CHECK-Linux: #[[#DEL:]] {{0x.* in operator delete\[\]}}
+  // CHECK-SunOS: #[[#DEL:]] {{0x.* in operator delete\[\]}}
+  // CHECK-Windows: #[[#DEL:]] {{0x.* in operator delete\[\]}}
+  // CHECK-FreeBSD: #[[#DEL:]] {{0x.* in operator delete\[\]}}
+  // CHECK-Darwin: #[[#DEL:]] {{0x.* in .*_Zda}}
+  // CHECK-NEXT: #[[#DEL+1]] {{0x.* in main .*use-after-delete.cpp:}}[[@LINE-14]]
 
   // CHECK: {{previously allocated by thread T0 here:}}
-  // CHECK-Linux:  {{    #0 0x.* in operator new\[\]}}
-  // CHECK-SunOS:  {{    #0 0x.* in operator new\[\]}}
-  // CHECK-Windows:{{    #0 0x.* in operator new\[\]}}
-  // CHECK-FreeBSD:{{    #0 0x.* in operator new\[\]}}
-  // CHECK-Darwin: {{    #0 0x.* in .*_Zna}}
-  // CHECK-NEXT:   {{    #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-23]]
+  // CHECK-Linux: #[[#NEW:]] {{0x.* in operator new\[\]}}
+  // CHECK-SunOS: #[[#NEW:]] {{0x.* in operator new\[\]}}
+  // CHECK-Windows: #[[#NEW:]] {{0x.* in operator new\[\]}}
+  // CHECK-FreeBSD: #[[#NEW:]] {{0x.* in operator new\[\]}}
+  // CHECK-Darwin: #[[#NEW:]] {{0x.* in .*_Zna}}
+  // CHECK-NEXT: #[[#NEW+1]] {{0x.* in main .*use-after-delete.cpp:}}[[@LINE-23]]
 
 
   // CHECK: Shadow byte legend (one shadow byte represents {{[0-9]+}} application bytes):

>From 70459a109c2822a09cc344c87bd5fb9493e27441 Mon Sep 17 00:00:00 2001
From: Charlie Barto <chbarto at microsoft.com>
Date: Thu, 9 Nov 2023 15:19:05 -0800
Subject: [PATCH 18/19] clang-format

---
 .../operator_delete_wrong_argument.cpp        |  6 +++---
 .../Windows/operator_new_left_oob.cpp         | 14 ++++++-------
 .../Windows/operator_new_right_oob.cpp        | 14 ++++++-------
 .../TestCases/Windows/operator_new_uaf.cpp    | 20 +++++++++----------
 .../Windows/wrong_downcast_on_heap.cpp        | 12 +++++------
 .../test/asan/TestCases/use-after-delete.cpp  |  1 -
 6 files changed, 33 insertions(+), 34 deletions(-)

diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cpp
index 933fab13c219656..c5be40a810e7c3f 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_delete_wrong_argument.cpp
@@ -6,7 +6,7 @@
 int main() {
   int *x = new int[42];
   delete (x + 1);
-// CHECK: AddressSanitizer: attempting free on address which was not malloc()-ed
-// CHECK:   #[[#DEL:]] {{0x.* operator delete}}
-// CHECK:   #[[#DEL+1]] {{.* main .*operator_delete_wrong_argument.cpp}}:[[@LINE-3]]
+  // CHECK: AddressSanitizer: attempting free on address which was not malloc()-ed
+  // CHECK:   #[[#DEL:]] {{0x.* operator delete}}
+  // CHECK:   #[[#DEL+1]] {{.* main .*operator_delete_wrong_argument.cpp}}:[[@LINE-3]]
 }
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cpp
index 8030ec04a245040..81303704da11e7e 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_left_oob.cpp
@@ -6,12 +6,12 @@
 int main() {
   char *buffer = new char;
   buffer[-1] = 42;
-// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
-// CHECK: WRITE of size 1 at [[ADDR]] thread T0
-// CHECK:   {{#0 .* main .*operator_new_left_oob.cpp}}:[[@LINE-3]]
-// CHECK: [[ADDR]] is located 1 bytes before 1-byte region
-// CHECK: allocated by thread T0 here:
-// CHECK:   #[[#NEW:]] {{.* operator new}}
-// CHECK:   #[[#NEW+1]] {{.* main .*operator_new_left_oob.cpp}}:[[@LINE-8]]
+  // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+  // CHECK: WRITE of size 1 at [[ADDR]] thread T0
+  // CHECK:   {{#0 .* main .*operator_new_left_oob.cpp}}:[[@LINE-3]]
+  // CHECK: [[ADDR]] is located 1 bytes before 1-byte region
+  // CHECK: allocated by thread T0 here:
+  // CHECK:   #[[#NEW:]] {{.* operator new}}
+  // CHECK:   #[[#NEW+1]] {{.* main .*operator_new_left_oob.cpp}}:[[@LINE-8]]
   delete buffer;
 }
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cpp
index fa10bae48c34932..0950e6f0802b72e 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_right_oob.cpp
@@ -6,12 +6,12 @@
 int main() {
   char *buffer = new char;
   buffer[1] = 42;
-// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
-// CHECK: WRITE of size 1 at [[ADDR]] thread T0
-// CHECK:   {{#0 .* main .*operator_new_right_oob.cpp}}:[[@LINE-3]]
-// CHECK: [[ADDR]] is located 0 bytes after 1-byte region
-// CHECK: allocated by thread T0 here:
-// CHECK:   #[[#NEW:]] {{.* operator new}}
-// CHECK:   #[[#NEW+1]] {{.* main .*operator_new_right_oob.cpp}}:[[@LINE-8]]
+  // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+  // CHECK: WRITE of size 1 at [[ADDR]] thread T0
+  // CHECK:   {{#0 .* main .*operator_new_right_oob.cpp}}:[[@LINE-3]]
+  // CHECK: [[ADDR]] is located 0 bytes after 1-byte region
+  // CHECK: allocated by thread T0 here:
+  // CHECK:   #[[#NEW:]] {{.* operator new}}
+  // CHECK:   #[[#NEW+1]] {{.* main .*operator_new_right_oob.cpp}}:[[@LINE-8]]
   delete buffer;
 }
diff --git a/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp
index f4752612a95393c..762d84f8c955025 100644
--- a/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/operator_new_uaf.cpp
@@ -9,16 +9,16 @@ int main() {
   char *buffer = new char;
   delete buffer;
   *buffer = 42;
-// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
-// CHECK: WRITE of size 1 at [[ADDR]] thread T0
-// CHECK:   {{#0 .* main .*operator_new_uaf.cpp}}:[[@LINE-3]]
-// CHECK: [[ADDR]] is located 0 bytes inside of 1-byte region
-// CHECK-LABEL: freed by thread T0 here:
-// CHECK:   #[[#DEL:]] {{.* operator delete}}
-// CHECK:   #[[#DEL+1]] {{.* main .*operator_new_uaf.cpp}}:[[@LINE-8]]
-// CHECK-LABEL: previously allocated by thread T0 here:
-// CHECK:   #[[#NEW:]] {{.* operator new}}
-// CHECK:   #[[#NEW+1]] {{.* main .*operator_new_uaf.cpp}}:[[@LINE-12]]
+  // CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
+  // CHECK: WRITE of size 1 at [[ADDR]] thread T0
+  // CHECK:   {{#0 .* main .*operator_new_uaf.cpp}}:[[@LINE-3]]
+  // CHECK: [[ADDR]] is located 0 bytes inside of 1-byte region
+  // CHECK-LABEL: freed by thread T0 here:
+  // CHECK:   #[[#DEL:]] {{.* operator delete}}
+  // CHECK:   #[[#DEL+1]] {{.* main .*operator_new_uaf.cpp}}:[[@LINE-8]]
+  // CHECK-LABEL: previously allocated by thread T0 here:
+  // CHECK:   #[[#NEW:]] {{.* operator new}}
+  // CHECK:   #[[#NEW+1]] {{.* main .*operator_new_uaf.cpp}}:[[@LINE-12]]
   return 0;
 }
 
diff --git a/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cpp b/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cpp
index cb52a0abe7c5c26..6b5d54d87cdeeb0 100644
--- a/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/wrong_downcast_on_heap.cpp
@@ -15,12 +15,12 @@ int main(void) {
   Parent *p = new Parent;
   Child *c = (Child*)p;  // Intentional error here!
   c->extra_field = 42;
-// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
-// CHECK: WRITE of size 4 at [[ADDR]] thread T0
-// CHECK:   {{#0 0x[0-9a-f]* in main .*wrong_downcast_on_heap.cpp}}:[[@LINE-3]]
-// CHECK: [[ADDR]] is located 0 bytes after 4-byte region
-// CHECK: allocated by thread T0 here:
-// CHECK:   {{.*}} operator new
+  // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+  // CHECK: WRITE of size 4 at [[ADDR]] thread T0
+  // CHECK:   {{#0 0x[0-9a-f]* in main .*wrong_downcast_on_heap.cpp}}:[[@LINE-3]]
+  // CHECK: [[ADDR]] is located 0 bytes after 4-byte region
+  // CHECK: allocated by thread T0 here:
+  // CHECK:   {{.*}} operator new
   return 0;
 }
 
diff --git a/compiler-rt/test/asan/TestCases/use-after-delete.cpp b/compiler-rt/test/asan/TestCases/use-after-delete.cpp
index 2acb5e53e9b52bb..273ebf72f132f6a 100644
--- a/compiler-rt/test/asan/TestCases/use-after-delete.cpp
+++ b/compiler-rt/test/asan/TestCases/use-after-delete.cpp
@@ -31,7 +31,6 @@ int main() {
   // CHECK-Darwin: #[[#NEW:]] {{0x.* in .*_Zna}}
   // CHECK-NEXT: #[[#NEW+1]] {{0x.* in main .*use-after-delete.cpp:}}[[@LINE-23]]
 
-
   // CHECK: Shadow byte legend (one shadow byte represents {{[0-9]+}} application bytes):
   // CHECK: Global redzone:
   // CHECK: ASan internal:

>From b725812f69f919b82dac00e662d65beaf9b689c3 Mon Sep 17 00:00:00 2001
From: Charlie Barto <chbarto at microsoft.com>
Date: Thu, 16 Nov 2023 10:13:42 -0800
Subject: [PATCH 19/19] remove GET_STACK_TRACE_*_WIN and
 GET_STACK_TRACE_EXPLICIT

---
 compiler-rt/lib/asan/asan_stack.h | 23 -----------------------
 1 file changed, 23 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_stack.h b/compiler-rt/lib/asan/asan_stack.h
index bc1b676e3d45ba6..02a76af847ae6e4 100644
--- a/compiler-rt/lib/asan/asan_stack.h
+++ b/compiler-rt/lib/asan/asan_stack.h
@@ -47,21 +47,6 @@ u32 GetMallocContextSize();
                  fast, max_size);                                          \
   }
 
-#define GET_STACK_TRACE_EXPLICIT(max_size, fast, pc, bp, caller_pc, \
-                                 extra_context)                     \
-  UNINITIALIZED __sanitizer::BufferedStackTrace stack;              \
-  if (max_size <= 2) {                                              \
-    stack.size = max_size;                                          \
-    if (max_size > 0) {                                             \
-      stack.top_frame_bp = bp;                                      \
-      stack.trace_buffer[0] = pc;                                   \
-      if (max_size > 1)                                             \
-        stack.trace_buffer[1] = caller_pc;                          \
-    }                                                               \
-  } else {                                                          \
-    stack.Unwind(pc, bp, nullptr, fast, max_size + extra_context);  \
-  }
-
 #define GET_STACK_TRACE_FATAL(pc, bp)     \
   UNINITIALIZED BufferedStackTrace stack; \
   stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal)
@@ -75,16 +60,8 @@ u32 GetMallocContextSize();
 #define GET_STACK_TRACE_MALLOC                                                 \
   GET_STACK_TRACE(GetMallocContextSize(), common_flags()->fast_unwind_on_malloc)
 
-#define GET_STACK_TRACE_MALLOC_WIN(pc, bp, caller_pc, extra_context)      \
-  GET_STACK_TRACE_EXPLICIT(__asan::GetMallocContextSize(),                \
-                           common_flags()->fast_unwind_on_malloc, pc, bp, \
-                           caller_pc, extra_context)
-
 #define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC
 
-#define GET_STACK_TRACE_FREE_WIN(pc, bp, caller_pc, extra_context) \
-  GET_STACK_TRACE_MALLOC_WIN(pc, bp, caller_pc, extra_context)
-
 #define PRINT_CURRENT_STACK()   \
   {                             \
     GET_STACK_TRACE_FATAL_HERE; \



More information about the llvm-commits mailing list