llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-driver

Author: Bojun Seo (Bojun-Seo)

<details>
<summary>Changes</summary>

Add DoubleFreeSanitizer (DSan), a standalone runtime sanitizer that detects 
double-free errors.

DSan intercepts allocation and free APIs and records per-allocation state 
together with allocation and free stack traces. When an allocation is freed 
again, it reports the invalid second free, the first free, and the original 
allocation.

Unlike AddressSanitizer, DSan does not require compiler instrumentation or 
shadow memory. This provides a focused option for resource-constrained 
environments, including embedded devices, where running ASan may not be 
feasible.

DSan is enabled with -fsanitize=doublefree.

RFC: DoubleFreeSanitizer proposal on Discourse
https://discourse.llvm.org/t/rfc-introduction-of-doublefreesanitizer-dsan/91363

---

Patch is 110.03 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/213846.diff


45 Files Affected:

- (modified) clang/include/clang/Basic/Sanitizers.def (+3) 
- (modified) clang/include/clang/Driver/SanitizerArgs.h (+5) 
- (modified) clang/lib/Driver/SanitizerArgs.cpp (+4) 
- (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+2) 
- (modified) clang/lib/Driver/ToolChains/Darwin.cpp (+3) 
- (modified) clang/lib/Driver/ToolChains/Fuchsia.cpp (+1) 
- (modified) clang/lib/Driver/ToolChains/Linux.cpp (+3) 
- (modified) clang/lib/Driver/ToolChains/NetBSD.cpp (+1) 
- (added) clang/test/Driver/fsanitize-doublefree.c (+21) 
- (modified) compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake (+6) 
- (modified) compiler-rt/cmake/config-ix.cmake (+17) 
- (modified) compiler-rt/include/CMakeLists.txt (+1) 
- (added) compiler-rt/include/sanitizer/dsan_interface.h (+30) 
- (modified) compiler-rt/lib/CMakeLists.txt (+2) 
- (added) compiler-rt/lib/dsan/.clang-format (+3) 
- (added) compiler-rt/lib/dsan/CMakeLists.txt (+85) 
- (added) compiler-rt/lib/dsan/dsan.cpp (+111) 
- (added) compiler-rt/lib/dsan/dsan.h (+56) 
- (added) compiler-rt/lib/dsan/dsan_allocator.cpp (+508) 
- (added) compiler-rt/lib/dsan/dsan_allocator.h (+150) 
- (added) compiler-rt/lib/dsan/dsan_common.cpp (+31) 
- (added) compiler-rt/lib/dsan/dsan_common.h (+103) 
- (added) compiler-rt/lib/dsan/dsan_fuchsia.cpp (+131) 
- (added) compiler-rt/lib/dsan/dsan_fuchsia.h (+35) 
- (added) compiler-rt/lib/dsan/dsan_interceptors.cpp (+570) 
- (added) compiler-rt/lib/dsan/dsan_linux.cpp (+33) 
- (added) compiler-rt/lib/dsan/dsan_mac.cpp (+234) 
- (added) compiler-rt/lib/dsan/dsan_malloc_mac.cpp (+66) 
- (added) compiler-rt/lib/dsan/dsan_posix.cpp (+121) 
- (added) compiler-rt/lib/dsan/dsan_posix.h (+49) 
- (added) compiler-rt/lib/dsan/dsan_preinit.cpp (+21) 
- (added) compiler-rt/lib/dsan/dsan_thread.cpp (+123) 
- (added) compiler-rt/lib/dsan/dsan_thread.h (+66) 
- (added) compiler-rt/lib/dsan/weak_symbols.txt (+1) 
- (modified) compiler-rt/test/CMakeLists.txt (+2-1) 
- (added) compiler-rt/test/dsan/CMakeLists.txt (+28) 
- (added) compiler-rt/test/dsan/TestCases/concurrent-double-free.cpp (+28) 
- (added) compiler-rt/test/dsan/TestCases/double-free.c (+17) 
- (added) compiler-rt/test/dsan/TestCases/invalid-free.c (+12) 
- (added) compiler-rt/test/dsan/TestCases/large-double-free.c (+15) 
- (added) compiler-rt/test/dsan/TestCases/realloc.c (+16) 
- (added) compiler-rt/test/dsan/TestCases/reallocarray.c (+18) 
- (added) compiler-rt/test/dsan/TestCases/smoke.cpp (+10) 
- (added) compiler-rt/test/dsan/lit.common.cfg.py (+114) 
- (added) compiler-rt/test/dsan/lit.site.cfg.py.in (+13) 


``````````diff
diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index da85431625026..47ff011e82550 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -88,6 +88,9 @@ SANITIZER("realtime", Realtime)
 // LeakSanitizer
 SANITIZER("leak", Leak)
 
+// DoubleFreeSanitizer
+SANITIZER("doublefree", DoubleFree)
+
 // UndefinedBehaviorSanitizer
 SANITIZER("alignment", Alignment)
 SANITIZER("array-bounds", ArrayBounds)
diff --git a/clang/include/clang/Driver/SanitizerArgs.h 
b/clang/include/clang/Driver/SanitizerArgs.h
index 6a01b3e36d44c..6e774c5ef8c77 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -111,6 +111,11 @@ class SanitizerArgs {
            !Sanitizers.has(SanitizerKind::Address) &&
            !Sanitizers.has(SanitizerKind::HWAddress);
   }
+  bool needsDsanRt() const {
+    return Sanitizers.has(SanitizerKind::DoubleFree) &&
+           !Sanitizers.has(SanitizerKind::Address) &&
+           !Sanitizers.has(SanitizerKind::HWAddress);
+  }
   bool needsFuzzerInterceptors() const;
   bool needsUbsanRt() const;
   bool needsUbsanCXXRt() const;
diff --git a/clang/lib/Driver/SanitizerArgs.cpp 
b/clang/lib/Driver/SanitizerArgs.cpp
index c77ba78122a81..e24d6c1794a79 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -48,6 +48,7 @@ static const SanitizerMask SupportsCoverage =
     SanitizerKind::Type | SanitizerKind::MemtagStack |
     SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |
     SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |
+    SanitizerKind::DoubleFree |
     SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
     SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
     SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
@@ -709,6 +710,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
       std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
       std::make_pair(SanitizerKind::Leak,
                      SanitizerKind::Thread | SanitizerKind::Memory),
+      std::make_pair(SanitizerKind::DoubleFree,
+               SanitizerKind::Leak | SanitizerKind::Thread |
+                 SanitizerKind::Memory | SanitizerKind::Scudo),
       std::make_pair(SanitizerKind::KernelAddress,
                      SanitizerKind::Address | SanitizerKind::Leak |
                          SanitizerKind::Thread | SanitizerKind::Memory),
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 883296e43111b..019880ca24253 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1747,6 +1747,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const 
ArgList &Args,
     StaticRuntimes.push_back("dfsan");
   if (SanArgs.needsLsanRt())
     StaticRuntimes.push_back("lsan");
+  if (SanArgs.needsDsanRt())
+    StaticRuntimes.push_back("dsan");
   if (SanArgs.needsMsanRt()) {
     StaticRuntimes.push_back("msan");
     if (SanArgs.linkCXXRuntimes())
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index d3de04fc5155e..a491e0cf3a74f 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1760,6 +1760,8 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList 
&Args,
     }
     if (Sanitize.needsLsanRt())
       AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
+    if (Sanitize.needsDsanRt())
+      AddLinkSanitizerLibArgs(Args, CmdArgs, "dsan");
     if (Sanitize.needsUbsanRt()) {
       assert(Sanitize.needsSharedRt() &&
              "Static sanitizer runtimes not supported");
@@ -4064,6 +4066,7 @@ Darwin::getSupportedSanitizers(BoundArch BA,
   Res |= SanitizerKind::PointerSubtract;
   Res |= SanitizerKind::Realtime;
   Res |= SanitizerKind::Leak;
+  Res |= SanitizerKind::DoubleFree;
   Res |= SanitizerKind::Fuzzer;
   Res |= SanitizerKind::FuzzerNoLink;
   Res |= SanitizerKind::ObjCCast;
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp 
b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index abde9fa10482d..36cadd7db9bf5 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -483,6 +483,7 @@ Fuchsia::getSupportedSanitizers(BoundArch BA,
   Res |= SanitizerKind::Fuzzer;
   Res |= SanitizerKind::FuzzerNoLink;
   Res |= SanitizerKind::Leak;
+  Res |= SanitizerKind::DoubleFree;
   Res |= SanitizerKind::Scudo;
   Res |= SanitizerKind::Thread;
   if (getTriple().getArch() == llvm::Triple::x86_64 ||
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp 
b/clang/lib/Driver/ToolChains/Linux.cpp
index 1ab385a9ea001..486d22e16145a 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -997,6 +997,9 @@ Linux::getSupportedSanitizers(BoundArch BA,
   if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 ||
       IsRISCV64 || IsSystemZ || IsHexagon || IsLoongArch64)
     Res |= SanitizerKind::Leak;
+  if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 ||
+      IsRISCV64 || IsSystemZ || IsHexagon || IsLoongArch64)
+    Res |= SanitizerKind::DoubleFree;
   if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ ||
       IsLoongArch64 || IsRISCV64)
     Res |= SanitizerKind::Thread;
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp 
b/clang/lib/Driver/ToolChains/NetBSD.cpp
index f03114b53bb61..dab65e9b46995 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -521,6 +521,7 @@ NetBSD::getSupportedSanitizers(BoundArch BA,
     Res |= SanitizerKind::PointerCompare;
     Res |= SanitizerKind::PointerSubtract;
     Res |= SanitizerKind::Leak;
+    Res |= SanitizerKind::DoubleFree;
     Res |= SanitizerKind::SafeStack;
     Res |= SanitizerKind::Scudo;
     Res |= SanitizerKind::Vptr;
diff --git a/clang/test/Driver/fsanitize-doublefree.c 
b/clang/test/Driver/fsanitize-doublefree.c
new file mode 100644
index 0000000000000..f8a7bf26c0994
--- /dev/null
+++ b/clang/test/Driver/fsanitize-doublefree.c
@@ -0,0 +1,21 @@
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=doublefree %s -### 2>&1 | 
FileCheck %s --check-prefix=DSAN
+// DSAN: "-fsanitize=doublefree"
+// DSAN: libclang_rt.dsan
+
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=doublefree,undefined %s 
-### 2>&1 | FileCheck %s --check-prefix=DSAN-UBSAN
+// DSAN-UBSAN: libclang_rt.dsan
+// DSAN-UBSAN: libclang_rt.ubsan_standalone
+
+// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=doublefree,leak %s 
-fsyntax-only 2>&1 | FileCheck %s --check-prefix=DSAN-LEAK
+// DSAN-LEAK: '-fsanitize=doublefree' not allowed with '-fsanitize=leak'
+
+// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=doublefree,scudo %s 
-fsyntax-only 2>&1 | FileCheck %s --check-prefix=DSAN-SCUDO
+// DSAN-SCUDO: '-fsanitize=doublefree' not allowed with '-fsanitize=scudo'
+
+// RUN: not %clang --target=x86_64-unknown-freebsd -fsanitize=doublefree %s 
-fsyntax-only 2>&1 | FileCheck %s --check-prefix=FREEBSD
+// FREEBSD: unsupported option '-fsanitize=doublefree' for target 
'x86_64-unknown-freebsd'
+
+// RUN: not %clang --target=wasm32-unknown-emscripten -fsanitize=doublefree %s 
-fsyntax-only 2>&1 | FileCheck %s --check-prefix=EMSCRIPTEN
+// EMSCRIPTEN: unsupported option '-fsanitize=doublefree' for target 
'wasm32-unknown-emscripten'
+
+int main(void) { return 0; }
diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake 
b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
index 9c9874d94a1f2..fffd2c69f03fb 100644
--- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
+++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
@@ -85,6 +85,12 @@ else()
   set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32}
       ${PPC64} ${S390X} ${RISCV64} ${HEXAGON} ${LOONGARCH64})
 endif()
+if(APPLE)
+  set(ALL_DSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64})
+else()
+  set(ALL_DSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32}
+      ${PPC64} ${S390X} ${RISCV64} ${HEXAGON} ${LOONGARCH64})
+endif()
 if (OS_NAME MATCHES "FreeBSD")
   set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${ARM64})
 else()
diff --git a/compiler-rt/cmake/config-ix.cmake 
b/compiler-rt/cmake/config-ix.cmake
index 083f1c98d0f16..a36fe8f2d27a0 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -482,6 +482,7 @@ if(APPLE)
   set(ORC_SUPPORTED_OS)
   set(UBSAN_SUPPORTED_OS osx)
   set(LSAN_SUPPORTED_OS osx)
+  set(DSAN_SUPPORTED_OS osx)
   set(STATS_SUPPORTED_OS osx)
 
   # FIXME: Support a general COMPILER_RT_ENABLE_OSX to match other platforms.
@@ -579,6 +580,7 @@ if(APPLE)
           list(APPEND ORC_SUPPORTED_OS ${platform}sim)
           list(APPEND UBSAN_SUPPORTED_OS ${platform}sim)
           list(APPEND LSAN_SUPPORTED_OS ${platform}sim)
+          list(APPEND DSAN_SUPPORTED_OS ${platform}sim)
           list(APPEND STATS_SUPPORTED_OS ${platform}sim)
         endif()
         foreach(arch ${DARWIN_${platform}sim_ARCHS})
@@ -614,6 +616,7 @@ if(APPLE)
           list(APPEND UBSAN_SUPPORTED_OS ${platform})
           list(APPEND TYSAN_SUPPORTED_OS ${platform})
           list(APPEND LSAN_SUPPORTED_OS ${platform})
+          list(APPEND DSAN_SUPPORTED_OS ${platform})
           list(APPEND STATS_SUPPORTED_OS ${platform})
         endif()
         foreach(arch ${DARWIN_${platform}_ARCHS})
@@ -636,6 +639,7 @@ if(APPLE)
     COMPILER_RT_SUPPORTED_ARCH
     )
   set(LSAN_COMMON_SUPPORTED_ARCH ${SANITIZER_COMMON_SUPPORTED_ARCH})
+  set(DSAN_COMMON_SUPPORTED_ARCH ${SANITIZER_COMMON_SUPPORTED_ARCH})
   set(UBSAN_COMMON_SUPPORTED_ARCH ${SANITIZER_COMMON_SUPPORTED_ARCH})
   set(ASAN_ABI_SUPPORTED_ARCH ${ALL_ASAN_ABI_SUPPORTED_ARCH})
   list_intersect(ASAN_SUPPORTED_ARCH
@@ -653,6 +657,9 @@ if(APPLE)
   list_intersect(LSAN_SUPPORTED_ARCH
     ALL_LSAN_SUPPORTED_ARCH
     SANITIZER_COMMON_SUPPORTED_ARCH)
+  list_intersect(DSAN_SUPPORTED_ARCH
+    ALL_DSAN_SUPPORTED_ARCH
+    SANITIZER_COMMON_SUPPORTED_ARCH)
   list_intersect(MSAN_SUPPORTED_ARCH
     ALL_MSAN_SUPPORTED_ARCH
     SANITIZER_COMMON_SUPPORTED_ARCH)
@@ -713,6 +720,8 @@ else()
   # supported by other sanitizers (even if they build into dummy object files).
   filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH
     ${SANITIZER_COMMON_SUPPORTED_ARCH})
+  filter_available_targets(DSAN_COMMON_SUPPORTED_ARCH
+    ${SANITIZER_COMMON_SUPPORTED_ARCH})
   filter_available_targets(UBSAN_COMMON_SUPPORTED_ARCH
     ${ALL_UBSAN_SUPPORTED_ARCH})
   filter_available_targets(ASAN_SUPPORTED_ARCH ${ALL_ASAN_SUPPORTED_ARCH})
@@ -720,6 +729,7 @@ else()
   filter_available_targets(FUZZER_SUPPORTED_ARCH ${ALL_FUZZER_SUPPORTED_ARCH})
   filter_available_targets(DFSAN_SUPPORTED_ARCH ${ALL_DFSAN_SUPPORTED_ARCH})
   filter_available_targets(LSAN_SUPPORTED_ARCH ${ALL_LSAN_SUPPORTED_ARCH})
+  filter_available_targets(DSAN_SUPPORTED_ARCH ${ALL_DSAN_SUPPORTED_ARCH})
   filter_available_targets(MSAN_SUPPORTED_ARCH ${ALL_MSAN_SUPPORTED_ARCH})
   filter_available_targets(HWASAN_SUPPORTED_ARCH ${ALL_HWASAN_SUPPORTED_ARCH})
   filter_available_targets(MEMPROF_SUPPORTED_ARCH 
${ALL_MEMPROF_SUPPORTED_ARCH})
@@ -832,6 +842,13 @@ else()
   set(COMPILER_RT_HAS_LSAN FALSE)
 endif()
 
+if (COMPILER_RT_HAS_SANITIZER_COMMON AND DSAN_SUPPORTED_ARCH AND
+    OS_NAME MATCHES "Android|Darwin|Linux|NetBSD|Fuchsia")
+  set(COMPILER_RT_HAS_DSAN TRUE)
+else()
+  set(COMPILER_RT_HAS_DSAN FALSE)
+endif()
+
 if (COMPILER_RT_HAS_SANITIZER_COMMON AND MSAN_SUPPORTED_ARCH AND
     OS_NAME MATCHES "Linux|FreeBSD|NetBSD")
   set(COMPILER_RT_HAS_MSAN TRUE)
diff --git a/compiler-rt/include/CMakeLists.txt 
b/compiler-rt/include/CMakeLists.txt
index eb998478b081b..1045a1836a9fb 100644
--- a/compiler-rt/include/CMakeLists.txt
+++ b/compiler-rt/include/CMakeLists.txt
@@ -5,6 +5,7 @@ if (COMPILER_RT_BUILD_SANITIZERS)
     sanitizer/common_interface_defs.h
     sanitizer/coverage_interface.h
     sanitizer/dfsan_interface.h
+    sanitizer/dsan_interface.h
     sanitizer/hwasan_interface.h
     sanitizer/linux_syscall_hooks.h
     sanitizer/lsan_interface.h
diff --git a/compiler-rt/include/sanitizer/dsan_interface.h 
b/compiler-rt/include/sanitizer/dsan_interface.h
new file mode 100644
index 0000000000000..a545b7206678e
--- /dev/null
+++ b/compiler-rt/include/sanitizer/dsan_interface.h
@@ -0,0 +1,30 @@
+//===-- sanitizer/dsan_interface.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 DoubleFreeSanitizer (DSan).
+//
+// Public interface header.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_DSAN_INTERFACE_H
+#define SANITIZER_DSAN_INTERFACE_H
+
+#include <sanitizer/common_interface_defs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// This function may be optionally provided by user and should return
+// a string containing common sanitizer runtime options.
+const char *SANITIZER_CDECL __dsan_default_options(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SANITIZER_DSAN_INTERFACE_H
diff --git a/compiler-rt/lib/CMakeLists.txt b/compiler-rt/lib/CMakeLists.txt
index a5b2fbb38762c..5fe86db866c33 100644
--- a/compiler-rt/lib/CMakeLists.txt
+++ b/compiler-rt/lib/CMakeLists.txt
@@ -45,6 +45,8 @@ if(COMPILER_RT_BUILD_SANITIZERS)
     add_subdirectory(stats)
     # Contains RTLSanCommon used even without COMPILER_RT_HAS_LSAN.
     add_subdirectory(lsan)
+    # Contains RTDSanCommon used even without COMPILER_RT_HAS_DSAN.
+    add_subdirectory(dsan)
     # Contains RTUbsan used even without COMPILER_RT_HAS_UBSAN.
     add_subdirectory(ubsan)
   endif()
diff --git a/compiler-rt/lib/dsan/.clang-format 
b/compiler-rt/lib/dsan/.clang-format
new file mode 100644
index 0000000000000..1f2a97030379d
--- /dev/null
+++ b/compiler-rt/lib/dsan/.clang-format
@@ -0,0 +1,3 @@
+BasedOnStyle: Google
+AllowShortIfStatementsOnASingleLine: false
+IndentPPDirectives: AfterHash
diff --git a/compiler-rt/lib/dsan/CMakeLists.txt 
b/compiler-rt/lib/dsan/CMakeLists.txt
new file mode 100644
index 0000000000000..616c28bc6add1
--- /dev/null
+++ b/compiler-rt/lib/dsan/CMakeLists.txt
@@ -0,0 +1,85 @@
+include_directories(..)
+
+set(DSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+append_rtti_flag(OFF DSAN_CFLAGS)
+
+# Too many existing bugs, needs cleanup.
+append_list_if(COMPILER_RT_HAS_WNO_FORMAT -Wno-format DSAN_CFLAGS)
+
+set(DSAN_COMMON_SOURCES
+  dsan_common.cpp
+  )
+
+set(DSAN_SOURCES
+  dsan.cpp
+  dsan_allocator.cpp
+  dsan_fuchsia.cpp
+  dsan_interceptors.cpp
+  dsan_linux.cpp
+  dsan_mac.cpp
+  dsan_malloc_mac.cpp
+  dsan_posix.cpp
+  dsan_preinit.cpp
+  dsan_thread.cpp
+  )
+
+set(DSAN_HEADERS
+  dsan.h
+  dsan_allocator.h
+  dsan_common.h
+  dsan_thread.h
+  )
+
+set(DSAN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+# Shared DSan runtime functionality.
+add_compiler_rt_object_libraries(RTDSanCommon
+    OS ${SANITIZER_COMMON_SUPPORTED_OS}
+    ARCHS ${DSAN_COMMON_SUPPORTED_ARCH}
+    SOURCES ${DSAN_COMMON_SOURCES}
+    ADDITIONAL_HEADERS ${DSAN_HEADERS}
+    CFLAGS ${DSAN_CFLAGS})
+
+if(COMPILER_RT_HAS_DSAN)
+  add_compiler_rt_component(dsan)
+  if(APPLE)
+    set(DSAN_LINK_LIBS ${SANITIZER_COMMON_LINK_LIBS})
+
+    add_weak_symbols("dsan" WEAK_SYMBOL_LINK_FLAGS)
+    add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS)
+
+    add_compiler_rt_runtime(clang_rt.dsan
+      SHARED
+      OS ${DSAN_SUPPORTED_OS}
+      ARCHS ${DSAN_SUPPORTED_ARCH}
+      SOURCES ${DSAN_SOURCES}
+      ADDITIONAL_HEADERS ${DSAN_HEADERS}
+      OBJECT_LIBS RTDSanCommon
+                  RTInterception
+                  RTSanitizerCommon
+                  RTSanitizerCommonLibc
+                  RTSanitizerCommonCoverage
+                  RTSanitizerCommonSymbolizer
+      CFLAGS ${DSAN_CFLAGS}
+      LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS}
+      LINK_LIBS ${DSAN_LINK_LIBS}
+      PARENT_TARGET dsan)
+  else()
+    foreach(arch ${DSAN_SUPPORTED_ARCH})
+      add_compiler_rt_runtime(clang_rt.dsan
+        STATIC
+        ARCHS ${arch}
+        SOURCES ${DSAN_SOURCES}
+                $<TARGET_OBJECTS:RTInterception.${arch}>
+                $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
+                $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
+                $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}>
+                $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>
+                $<TARGET_OBJECTS:RTSanitizerCommonSymbolizerInternal.${arch}>
+                $<TARGET_OBJECTS:RTDSanCommon.${arch}>
+        ADDITIONAL_HEADERS ${DSAN_HEADERS}
+        CFLAGS ${DSAN_CFLAGS}
+        PARENT_TARGET dsan)
+    endforeach()
+  endif()
+endif()
diff --git a/compiler-rt/lib/dsan/dsan.cpp b/compiler-rt/lib/dsan/dsan.cpp
new file mode 100644
index 0000000000000..524604220f8dc
--- /dev/null
+++ b/compiler-rt/lib/dsan/dsan.cpp
@@ -0,0 +1,111 @@
+//=-- dsan.cpp 
------------------------------------------------------------===//
+//
+// 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 DoubleFreeSanitizer.
+// Standalone DSan RTL.
+//
+//===----------------------------------------------------------------------===//
+
+#include "dsan.h"
+
+#include "dsan_allocator.h"
+#include "dsan_common.h"
+#include "dsan_thread.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+
+bool dsan_inited;
+bool dsan_init_is_running;
+
+namespace __dsan {
+
+///// Interface to the common DSan module. /////
+bool WordIsPoisoned(uptr addr) {
+  return false;
+}
+
+}  // namespace __dsan
+
+void __sanitizer::BufferedStackTrace::UnwindImpl(
+    uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
+  using namespace __dsan;
+  uptr stack_top = 0, stack_bottom = 0;
+  if (ThreadContextDsanBase *t = GetCurrentThread()) {
+    stack_top = t->stack_end();
+    stack_bottom = t->stack_begin();
+  }
+  if (SANITIZER_MIPS && !IsValidFrame(bp, stack_top, stack_bottom))
+    return;
+  bool fast = StackTrace::WillUseFastUnwind(request_fast);
+  Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast);
+}
+
+using namespace __dsan;
+
+static void InitializeFlags() {
+  // Set all the default values.
+  SetCommonFlagsDefaults();
+  {
+    CommonFlags cf;
+    cf.CopyFrom(*common_flags());
+    cf.external_symbolizer_path = GetEnv("DSAN_SYMBOLIZER_PATH");
+    cf.malloc_context_size = 30;
+    cf.intercept_tls_get_addr = true;
+    cf.detect_leaks = false;
+    cf.exitcode = 77;
+    OverrideCommonFlags(cf);
+  }
+
+  FlagParser parser;
+  RegisterCommonFlags(&parser);
+
+  // Override from user-specified string.
+  const char *dsan_default_options = __dsan_default_options();
+  parser.ParseString(dsan_default_options);
+  parser.ParseStringFromEnv("DSAN_OPTIONS");
+
+  InitializeCommonFlags();
+
+  if (Verbosity()) ReportUnrecognizedFlags();
+
+  if (common_flags()->help) parser.PrintFlagDescriptions();
+
+  __sanitizer_set_report_path(common_flags()->log_path);
+}
+
+extern "C" void __dsan_init() {
+  CHECK(!dsan_init_is_running);
+  if (dsan_inited)
+    return;
+  dsan_init_is_running = true;
+  SanitizerToolName = "DoubleFreeSanitizer";
+  CacheBinaryName();
+  AvoidCVE_2016_2143();
+  InitializeFlags();
+  InitializePlatformEarly();
+  InitCommonDsan();
+  InitializeAllocator();
+  ReplaceSystemMalloc();
+  InitializeInterceptors();
+  InitializeThreads();
+  InstallDeadlySignalHandlers(DsanOnDeadlySignal);
+  InitializeMainThread();
+  InstallAtForkHandler();
+
+  InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
+
+  dsan_inited = true;
+  dsan_init_is_running = false;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+  GET_STACK_TRACE_FATAL;
+  ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/213846
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to