hctim created this revision.
hctim added reviewers: cryptoad, pcc.
Herald added subscribers: phosek, mgorny.
hctim requested review of this revision.
Herald added projects: clang, Sanitizers.
Herald added subscribers: Sanitizers, cfe-commits.

This patch moves -fsanitize=scudo to link the standalone scudo library,
rather than the original compiler-rt based library. This is one of the
major remaining roadblocks to deleting the compiler-rt based scudo,
which should not be used any more. The standalone Scudo is better in
pretty much every way and is much more suitable for production usage.

As well as patching the litmus tests for checking that the
scudo_standalone lib is linked instead of the scudo lib, this patch also
ports all the scudo lit tests to run under scudo standalone.

This patch also adds a feature to scudo standalone that was under test
in the original scudo - that arguments passed to an aligned operator new
were checked that the alignment was a power of two.

Some lit tests could not be migrated, due to the following issues:

1. Features that aren't supported in scudo standalone, like the rss limit.
2. Different quarantine implementation where the test needs some more thought.
3. Small bugs in scudo standalone that should probably be fixed, like the 
Secondary allocator having a full page on the LHS of an allocation that only 
contains the chunk header, so underflows by <= a page aren't caught.
4. Slight differences in behaviour that's technically correct, like 
'realloc(malloc(1), 0)' returns nullptr in standalone, but a real pointer in 
old scudo.
5. Some tests that might be migratable, but not easily.

Tests that are obviously not applicable to scudo standalone (like
testing that no sanitizer symbols made it into the DSO) have been
deleted.

After this patch, the remaining work is:

1. Update the Scudo documentation. The flags have changed, etc.
2. Delete the old version of scudo.
3. Patch up the tests in lit-unmigrated, or fix Scudo standalone.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D102543

Files:
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  
clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-fuchsia/libclang_rt.scudo.so
  
clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-fuchsia/libclang_rt.scudo_standalone.so
  
clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-fuchsia/libclang_rt.scudo.so
  
clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-fuchsia/libclang_rt.scudo_standalone.so
  clang/test/Driver/fuchsia.c
  clang/test/Driver/sanitizer-ld.c
  compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
  compiler-rt/test/scudo/CMakeLists.txt
  compiler-rt/test/scudo/aligned-new.cpp
  compiler-rt/test/scudo/alignment.c
  compiler-rt/test/scudo/dealloc-race.c
  compiler-rt/test/scudo/double-free.cpp
  compiler-rt/test/scudo/fsanitize.c
  compiler-rt/test/scudo/interface.cpp
  compiler-rt/test/scudo/lit.cfg.py
  compiler-rt/test/scudo/lit.site.cfg.py.in
  compiler-rt/test/scudo/malloc.cpp
  compiler-rt/test/scudo/memalign.c
  compiler-rt/test/scudo/mismatch.cpp
  compiler-rt/test/scudo/options.cpp
  compiler-rt/test/scudo/overflow.c
  compiler-rt/test/scudo/preinit.c
  compiler-rt/test/scudo/preload.cpp
  compiler-rt/test/scudo/quarantine.c
  compiler-rt/test/scudo/random_shuffle.cpp
  compiler-rt/test/scudo/realloc.cpp
  compiler-rt/test/scudo/rss.c
  compiler-rt/test/scudo/secondary.c
  compiler-rt/test/scudo/sized-delete.cpp
  compiler-rt/test/scudo/sizes.cpp
  compiler-rt/test/scudo/standalone/CMakeLists.txt
  compiler-rt/test/scudo/standalone/aligned-new.cpp
  compiler-rt/test/scudo/standalone/alignment.c
  compiler-rt/test/scudo/standalone/dealloc-race.c
  compiler-rt/test/scudo/standalone/double-free.cpp
  compiler-rt/test/scudo/standalone/fsanitize.c
  compiler-rt/test/scudo/standalone/lit-unmigrated/overflow.c
  compiler-rt/test/scudo/standalone/lit-unmigrated/quarantine.c
  compiler-rt/test/scudo/standalone/lit-unmigrated/realloc.cpp
  compiler-rt/test/scudo/standalone/lit-unmigrated/rss.c
  compiler-rt/test/scudo/standalone/lit-unmigrated/secondary.c
  compiler-rt/test/scudo/standalone/lit-unmigrated/sizes.cpp
  compiler-rt/test/scudo/standalone/lit-unmigrated/threads.c
  compiler-rt/test/scudo/standalone/lit-unmigrated/valloc.c
  compiler-rt/test/scudo/standalone/lit.cfg.py
  compiler-rt/test/scudo/standalone/lit.site.cfg.py.in
  compiler-rt/test/scudo/standalone/malloc.cpp
  compiler-rt/test/scudo/standalone/memalign.c
  compiler-rt/test/scudo/standalone/mismatch.cpp
  compiler-rt/test/scudo/standalone/options.cpp
  compiler-rt/test/scudo/standalone/preinit.c
  compiler-rt/test/scudo/standalone/preload.cpp
  compiler-rt/test/scudo/standalone/random_shuffle.cpp
  compiler-rt/test/scudo/standalone/sized-delete.cpp
  compiler-rt/test/scudo/standalone/stats.c
  compiler-rt/test/scudo/standalone/tsd_destruction.c
  compiler-rt/test/scudo/stats.c
  compiler-rt/test/scudo/symbols.test
  compiler-rt/test/scudo/threads.c
  compiler-rt/test/scudo/tsd_destruction.c
  compiler-rt/test/scudo/valloc.c

Index: compiler-rt/test/scudo/symbols.test
===================================================================
--- compiler-rt/test/scudo/symbols.test
+++ /dev/null
@@ -1,8 +0,0 @@
-UNSUPPORTED: android
-
-Verify that various functions are *not* present in the minimal binary. Presence
-of those symbols in the minimal runtime would mean that the split code made it
-back into the core Sanitizer runtime library.
-
-RUN: nm %shared_minlibscudo | not grep Symbolizer
-RUN: nm %shared_minlibscudo | not grep Coverage
Index: compiler-rt/test/scudo/tsd_destruction.c
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/tsd_destruction.c
@@ -1,42 +0,0 @@
-// RUN: %clang_scudo %s -o %t
-// RUN: %run %t 2>&1
-
-#include <locale.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-// Some of glibc's own thread local data is destroyed after a user's thread
-// local destructors are called, via __libc_thread_freeres. This might involve
-// calling free, as is the case for strerror_thread_freeres.
-// If there is no prior heap operation in the thread, this free would end up 
-// initializing some thread specific data that would never be destroyed
-// properly, while still being deallocated when the TLS goes away. As a result,
-// a program could SEGV, usually in
-// __sanitizer::AllocatorGlobalStats::Unregister, where one of the doubly
-// linked list links would refer to a now unmapped memory area.
-
-// This test reproduces those circumstances. Success means executing without
-// a segmentation fault.
-
-const int kNumThreads = 16;
-pthread_t tid[kNumThreads];
-
-void *thread_func(void *arg) {
-  uintptr_t i = (uintptr_t)arg;
-  if ((i & 1) == 0) free(malloc(16));
-  // Calling strerror_l allows for strerror_thread_freeres to be called.
-  strerror_l(0, LC_GLOBAL_LOCALE);
-  return 0;
-}
-
-int main(int argc, char** argv) {
-  for (uintptr_t j = 0; j < 8; j++) {
-    for (uintptr_t i = 0; i < kNumThreads; i++)
-      pthread_create(&tid[i], 0, thread_func, (void *)i);
-    for (uintptr_t i = 0; i < kNumThreads; i++)
-      pthread_join(tid[i], 0);
-  }
-  return 0;
-}
Index: compiler-rt/test/scudo/stats.c
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/stats.c
@@ -1,21 +0,0 @@
-// RUN: %clang_scudo %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// Tests that the allocator stats printing function exists and outputs
-// "something". Currently that "something" is fairly nebulous, as the 32-bit
-// primary doesn't output anything, and for the 64-bit one it's highly dependent
-// on the size class map and potential library allocations. So keep it very
-// generic for now.
-
-#include <stdlib.h>
-
-#include <sanitizer/scudo_interface.h>
-
-int main(int argc, char **argv)
-{
-  free(malloc(1U));
-  __scudo_print_stats();
-  return 0;
-}
-
-// CHECK: Stats:
Index: compiler-rt/test/scudo/standalone/sized-delete.cpp
===================================================================
--- compiler-rt/test/scudo/standalone/sized-delete.cpp
+++ compiler-rt/test/scudo/standalone/sized-delete.cpp
@@ -1,10 +1,10 @@
 // RUN: %clangxx_scudo -fsized-deallocation %s -o %t
-// RUN: %env_scudo_opts=DeleteSizeMismatch=1     %run %t gooddel    2>&1
-// RUN: %env_scudo_opts=DeleteSizeMismatch=1 not %run %t baddel     2>&1 | FileCheck %s
-// RUN: %env_scudo_opts=DeleteSizeMismatch=0     %run %t baddel     2>&1
-// RUN: %env_scudo_opts=DeleteSizeMismatch=1     %run %t gooddelarr 2>&1
-// RUN: %env_scudo_opts=DeleteSizeMismatch=1 not %run %t baddelarr  2>&1 | FileCheck %s
-// RUN: %env_scudo_opts=DeleteSizeMismatch=0     %run %t baddelarr  2>&1
+// RUN: %env_scudo_opts=delete_size_mismatch=1             %run %t gooddel    2>&1
+// RUN: %env_scudo_opts=delete_size_mismatch=1 not --crash %run %t baddel     2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=delete_size_mismatch=0             %run %t baddel     2>&1
+// RUN: %env_scudo_opts=delete_size_mismatch=1             %run %t gooddelarr 2>&1
+// RUN: %env_scudo_opts=delete_size_mismatch=1 not --crash %run %t baddelarr  2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=delete_size_mismatch=0             %run %t baddelarr  2>&1
 
 // Ensures that the sized delete operator errors out when the appropriate
 // option is passed and the sizes do not match between allocation and
@@ -16,8 +16,7 @@
 
 #include <new>
 
-int main(int argc, char **argv)
-{
+int main(int argc, char **argv) {
   assert(argc == 2);
   if (!strcmp(argv[1], "gooddel")) {
     long long *p = new long long;
Index: compiler-rt/test/scudo/random_shuffle.cpp
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/random_shuffle.cpp
@@ -1,23 +0,0 @@
-// RUN: %clangxx_scudo %s -o %t
-// RUN: rm -rf %t-dir/random_shuffle_tmp_dir
-// RUN: mkdir -p %t-dir/random_shuffle_tmp_dir
-// RUN: %run %t 100 > %t-dir/random_shuffle_tmp_dir/out1
-// RUN: %run %t 100 > %t-dir/random_shuffle_tmp_dir/out2
-// RUN: %run %t 10000 > %t-dir/random_shuffle_tmp_dir/out1
-// RUN: %run %t 10000 > %t-dir/random_shuffle_tmp_dir/out2
-// RUN: not diff %t-dir/random_shuffle_tmp_dir/out?
-// RUN: rm -rf %t-dir/random_shuffle_tmp_dir
-
-// Tests that the allocator shuffles the chunks before returning to the user.
-
-#include <stdlib.h>
-#include <stdio.h>
-
-int main(int argc, char **argv) {
-  int alloc_size = argc == 2 ? atoi(argv[1]) : 100;
-  char *base = new char[alloc_size];
-  for (int i = 0; i < 20; i++) {
-    char *p = new char[alloc_size];
-    printf("%zd\n", base - p);
-  }
-}
Index: compiler-rt/test/scudo/standalone/preload.cpp
===================================================================
--- compiler-rt/test/scudo/standalone/preload.cpp
+++ compiler-rt/test/scudo/standalone/preload.cpp
@@ -1,8 +1,7 @@
 // Test that the preloaded runtime works without linking the static library.
 
 // RUN: %clang %s -lstdc++ -o %t
-// RUN: env LD_PRELOAD=%shared_libscudo    not %run %t 2>&1 | FileCheck %s
-// RUN: env LD_PRELOAD=%shared_minlibscudo not %run %t 2>&1 | FileCheck %s
+// RUN: env LD_PRELOAD=%shared_libscudo    not --crash %run %t 2>&1 | FileCheck %s
 
 // This way of setting LD_PRELOAD does not work with Android test runner.
 // REQUIRES: !android
Index: compiler-rt/test/scudo/preinit.c
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/preinit.c
@@ -1,40 +0,0 @@
-// RUN: %clang_scudo %s -o %t
-// RUN: %run %t 2>&1
-
-// Verifies that calling malloc in a preinit_array function succeeds, and that
-// the resulting pointer can be freed at program termination.
-
-// On some Android versions, calling mmap() from a preinit function segfaults.
-// It looks like __mmap2.S ends up calling a NULL function pointer.
-// UNSUPPORTED: android
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-static void *global_p = NULL;
-
-void __init(void) {
-  global_p = malloc(1);
-  if (!global_p)
-    exit(1);
-}
-
-void __fini(void) {
-  if (global_p)
-    free(global_p);
-}
-
-int main(int argc, char **argv)
-{
-  void *p = malloc(1);
-  assert(p);
-  free(p);
-
-  return 0;
-}
-
-__attribute__((section(".preinit_array"), used))
-  void (*__local_preinit)(void) = __init;
-__attribute__((section(".fini_array"), used))
-  void (*__local_fini)(void) = __fini;
Index: compiler-rt/test/scudo/standalone/options.cpp
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/standalone/options.cpp
@@ -0,0 +1,24 @@
+// RUN: %clangxx_scudo %s -o %t
+// RUN:                                         not --crash %run %t 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=dealloc_type_mismatch=0             %run %t 2>&1
+// RUN: %env_scudo_opts=dealloc_type_mismatch=1 not --crash %run %t 2>&1 | FileCheck %s
+
+// Tests that the options can be passed using getScudoDefaultOptions, and that
+// the environment ones take precedence over them.
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+extern "C" const char *__scudo_default_options() {
+  return "dealloc_type_mismatch=1"; // Defaults to false in flags.inc.
+}
+
+int main(int argc, char **argv) {
+  int *p = (int *)malloc(16);
+  assert(p);
+  delete p;
+  return 0;
+}
+
+// CHECK: ERROR: allocation type mismatch when deallocating address
Index: compiler-rt/test/scudo/standalone/mismatch.cpp
===================================================================
--- compiler-rt/test/scudo/standalone/mismatch.cpp
+++ compiler-rt/test/scudo/standalone/mismatch.cpp
@@ -1,8 +1,8 @@
 // RUN: %clangxx_scudo %s -o %t
-// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t mallocdel 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
-// RUN: %env_scudo_opts=DeallocationTypeMismatch=0     %run %t mallocdel 2>&1
-// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t newfree   2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
-// RUN: %env_scudo_opts=DeallocationTypeMismatch=0     %run %t newfree   2>&1
+// RUN: %env_scudo_opts=dealloc_type_mismatch=1 not --crash %run %t mallocdel 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
+// RUN: %env_scudo_opts=dealloc_type_mismatch=0             %run %t mallocdel 2>&1
+// RUN: %env_scudo_opts=dealloc_type_mismatch=1 not --crash %run %t newfree   2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
+// RUN: %env_scudo_opts=dealloc_type_mismatch=0             %run %t newfree   2>&1
 
 // Tests that type mismatches between allocation and deallocation functions are
 // caught when the related option is set.
@@ -11,8 +11,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-int main(int argc, char **argv)
-{
+int main(int argc, char **argv) {
   assert(argc == 2);
   if (!strcmp(argv[1], "mallocdel")) {
     int *p = (int *)malloc(16);
Index: compiler-rt/test/scudo/standalone/memalign.c
===================================================================
--- compiler-rt/test/scudo/standalone/memalign.c
+++ compiler-rt/test/scudo/standalone/memalign.c
@@ -1,10 +1,10 @@
 // RUN: %clang_scudo %s -o %t
-// RUN:                                                 %run %t valid       2>&1
-// RUN:                                             not %run %t invalid     2>&1 | FileCheck --check-prefix=CHECK-align %s
-// RUN: %env_scudo_opts=allocator_may_return_null=1     %run %t invalid     2>&1
-// RUN:                                             not %run %t double-free 2>&1 | FileCheck --check-prefix=CHECK-double-free %s
-// RUN: %env_scudo_opts=DeallocationTypeMismatch=1  not %run %t realloc     2>&1 | FileCheck --check-prefix=CHECK-realloc %s
-// RUN: %env_scudo_opts=DeallocationTypeMismatch=0      %run %t realloc     2>&1
+// RUN:                                         %run %t valid       2>&1
+// RUN: %env_scudo_opts=may_return_null=0       not --crash %run %t invalid     2>&1 | FileCheck --check-prefix=CHECK-align %s
+// RUN: %env_scudo_opts=may_return_null=1       %run %t invalid     2>&1
+// RUN:                                         not --crash %run %t double-free 2>&1 | FileCheck --check-prefix=CHECK-double-free %s
+// RUN: %env_scudo_opts=dealloc_type_mismatch=1 not --crash %run %t realloc     2>&1 | FileCheck --check-prefix=CHECK-realloc %s
+// RUN: %env_scudo_opts=dealloc_type_mismatch=0 %run %t realloc     2>&1
 
 // Tests that the various aligned allocation functions work as intended. Also
 // tests for the condition where the alignment is not a power of 2.
Index: compiler-rt/test/scudo/malloc.cpp
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/malloc.cpp
@@ -1,37 +0,0 @@
-// RUN: %clangxx_scudo %s -lstdc++ -o %t
-// RUN: %run %t 2>&1
-
-// Tests that a regular workflow of allocation, memory fill and free works as
-// intended. Tests various sizes serviced by the primary and secondary
-// allocators.
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <vector>
-
-int main(int argc, char **argv)
-{
-  void *p;
-  std::vector<ssize_t> sizes{1, 8, 16, 32, 1024, 32768,
-    1 << 16, 1 << 17, 1 << 20, 1 << 24};
-  std::vector<int> offsets{1, 0, -1, -7, -8, -15, -16, -31, -32};
-
-  p = malloc(0);
-  assert(p);
-  free(p);
-  for (ssize_t size : sizes) {
-    for (int offset: offsets) {
-      ssize_t actual_size = size + offset;
-      if (actual_size <= 0)
-        continue;
-      p = malloc(actual_size);
-      assert(p);
-      memset(p, 0xff, actual_size);
-      free(p);
-    }
-  }
-
-  return 0;
-}
Index: compiler-rt/test/scudo/standalone/lit.site.cfg.py.in
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/standalone/lit.site.cfg.py.in
@@ -0,0 +1,11 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+config.name_suffix = "@SCUDO_STANDALONE_TEST_CONFIG_SUFFIX@"
+config.target_arch = "@SCUDO_STANDALONE_TEST_TARGET_ARCH@"
+config.target_cflags = "@SCUDO_STANDALONE_TEST_TARGET_CFLAGS@"
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@SCUDO_STANDALONE_LIT_SOURCE_DIR@/lit.cfg.py")
Index: compiler-rt/test/scudo/standalone/lit.cfg.py
===================================================================
--- compiler-rt/test/scudo/standalone/lit.cfg.py
+++ compiler-rt/test/scudo/standalone/lit.cfg.py
@@ -3,33 +3,25 @@
 import os
 
 # Setup config name.
-config.name = 'Scudo' + config.name_suffix
+config.name = 'ScudoStandalone' + config.name_suffix
 
 # Setup source root.
 config.test_source_root = os.path.dirname(__file__)
 
 # Path to the shared library
-shared_libscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo%s.so" % config.target_suffix)
-shared_minlibscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo_minimal%s.so" % config.target_suffix)
+shared_libscudo = os.path.join(config.compiler_rt_libdir,
+    "libclang_rt.scudo_standalone%s.so" % config.target_suffix)
 
 # Test suffixes.
-config.suffixes = ['.c', '.cpp', '.test']
+config.suffixes = ['.c', '.cpp']
+config.excludes = ['lit-unmigrated']
 
 # C & CXX flags.
 c_flags = ([config.target_cflags] +
-           ["-pthread",
-           "-fPIE",
-           "-pie",
-           "-O0",
-           "-UNDEBUG",
-           "-ldl",
-           "-Wl,--gc-sections"])
+           ["-pthread", "-fPIE", "-pie", "-O0", "-UNDEBUG", "-ldl",
+            "-Wl,--gc-sections"])
 
-# Android doesn't want -lrt.
-if not config.android:
-  c_flags += ["-lrt"]
-
-cxx_flags = (c_flags + config.cxx_mode_flags + ["-std=c++11"])
+cxx_flags = (c_flags + config.cxx_mode_flags + ["-std=c++14"])
 
 scudo_flags = ["-fsanitize=scudo"]
 
@@ -41,21 +33,12 @@
 config.substitutions.append(("%clang_scudo ", build_invocation(c_flags + scudo_flags)))
 config.substitutions.append(("%clangxx_scudo ", build_invocation(cxx_flags + scudo_flags)))
 config.substitutions.append(("%shared_libscudo", shared_libscudo))
-config.substitutions.append(("%shared_minlibscudo", shared_minlibscudo))
-
-# Platform-specific default SCUDO_OPTIONS for lit tests.
-default_scudo_opts = ''
-if config.android:
-  # Android defaults to abort_on_error=1, which doesn't work for us.
-  default_scudo_opts = 'abort_on_error=0'
 
 # Disable GWP-ASan for scudo internal tests.
+default_scudo_opts = ''
 if config.gwp_asan:
-  config.environment['GWP_ASAN_OPTIONS'] = 'Enabled=0'
+  default_scudo_opts += 'GWP_ASAN_Enabled=false:'
 
-if default_scudo_opts:
-  config.environment['SCUDO_OPTIONS'] = default_scudo_opts
-  default_scudo_opts += ':'
 config.substitutions.append(('%env_scudo_opts=',
                              'env SCUDO_OPTIONS=' + default_scudo_opts))
 
Index: compiler-rt/test/scudo/standalone/lit-unmigrated/valloc.c
===================================================================
--- compiler-rt/test/scudo/standalone/lit-unmigrated/valloc.c
+++ compiler-rt/test/scudo/standalone/lit-unmigrated/valloc.c
@@ -1,7 +1,7 @@
 // RUN: %clang_scudo %s -o %t
-// RUN:                                                 %run %t valid   2>&1
-// RUN:                                             not %run %t invalid 2>&1 | FileCheck %s
-// RUN: %env_scudo_opts=allocator_may_return_null=1     %run %t invalid 2>&1
+// RUN:                                       %run %t valid   2>&1
+// RUN:                                       not --crash %run %t invalid 2>&1 | FileCheck %s
+// RUNX: %env_scudo_opts=may_return_null=1     %run %t invalid 2>&1
 // UNSUPPORTED: android
 
 // Tests that valloc and pvalloc work as intended.
Index: compiler-rt/test/scudo/threads.c
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/threads.c
@@ -1,65 +0,0 @@
-// RUN: %clang_scudo %s -o %t
-// RUN: %env_scudo_opts="QuarantineSizeKb=0:ThreadLocalQuarantineSizeKb=0"     %run %t 5 1000000 2>&1
-// RUN: %env_scudo_opts="QuarantineSizeKb=1024:ThreadLocalQuarantineSizeKb=64" %run %t 5 1000000 2>&1
-
-// Tests parallel allocations and deallocations of memory chunks from a number
-// of concurrent threads, with and without quarantine.
-// This test passes if everything executes properly without crashing.
-
-#include <assert.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <sanitizer/allocator_interface.h>
-
-int num_threads;
-int total_num_alloc;
-const int kMaxNumThreads = 500;
-pthread_t tid[kMaxNumThreads];
-
-pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-char go = 0;
-
-void *thread_fun(void *arg) {
-  pthread_mutex_lock(&mutex);
-  while (!go) pthread_cond_wait(&cond, &mutex);
-  pthread_mutex_unlock(&mutex);
-  for (int i = 0; i < total_num_alloc / num_threads; i++) {
-    void *p = malloc(10);
-    __asm__ __volatile__("" : : "r"(p) : "memory");
-    free(p);
-  }
-  return 0;
-}
-
-int main(int argc, char** argv) {
-  assert(argc == 3);
-  num_threads = atoi(argv[1]);
-  assert(num_threads > 0);
-  assert(num_threads <= kMaxNumThreads);
-  total_num_alloc = atoi(argv[2]);
-  assert(total_num_alloc > 0);
-
-  printf("%d threads, %d allocations in each\n", num_threads,
-         total_num_alloc / num_threads);
-  fprintf(stderr, "Heap size before: %zd\n", __sanitizer_get_heap_size());
-  fprintf(stderr, "Allocated bytes before: %zd\n",
-          __sanitizer_get_current_allocated_bytes());
-
-  for (int i = 0; i < num_threads; i++)
-    pthread_create(&tid[i], 0, thread_fun, 0);
-  pthread_mutex_lock(&mutex);
-  go = 1;
-  pthread_cond_broadcast(&cond);
-  pthread_mutex_unlock(&mutex);
-  for (int i = 0; i < num_threads; i++)
-    pthread_join(tid[i], 0);
-
-  fprintf(stderr, "Heap size after: %zd\n", __sanitizer_get_heap_size());
-  fprintf(stderr, "Allocated bytes after: %zd\n",
-          __sanitizer_get_current_allocated_bytes());
-
-  return 0;
-}
Index: compiler-rt/test/scudo/standalone/lit-unmigrated/sizes.cpp
===================================================================
--- compiler-rt/test/scudo/standalone/lit-unmigrated/sizes.cpp
+++ compiler-rt/test/scudo/standalone/lit-unmigrated/sizes.cpp
@@ -1,13 +1,13 @@
 // RUN: %clangxx_scudo %s -lstdc++ -o %t
-// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t malloc 2>&1      | FileCheck %s --check-prefix=CHECK-max
-// RUN: %env_scudo_opts=allocator_may_return_null=1     %run %t malloc 2>&1
-// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t calloc 2>&1      | FileCheck %s --check-prefix=CHECK-calloc
-// RUN: %env_scudo_opts=allocator_may_return_null=1     %run %t calloc 2>&1
-// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new 2>&1         | FileCheck %s --check-prefix=CHECK-max
-// RUN: %env_scudo_opts=allocator_may_return_null=1 not %run %t new 2>&1         | FileCheck %s --check-prefix=CHECK-oom
-// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 | FileCheck %s --check-prefix=CHECK-max
-// RUN: %env_scudo_opts=allocator_may_return_null=1     %run %t new-nothrow 2>&1
-// RUN:                                                 %run %t usable 2>&1
+// RUN: %env_scudo_opts=may_return_null=0 not --crash %run %t malloc 2>&1      | FileCheck %s --check-prefix=CHECK-max
+// RUN: %env_scudo_opts=may_return_null=1             %run %t malloc 2>&1
+// RUNZ: %env_scudo_opts=may_return_null=0 not --crash %run %t calloc 2>&1      | FileCheck %s --check-prefix=CHECK-calloc
+// RUNZ: %env_scudo_opts=may_return_null=1             %run %t calloc 2>&1
+// RUNZ: %env_scudo_opts=may_return_null=0 not --crash %run %t new 2>&1         | FileCheck %s --check-prefix=CHECK-max
+// RUNZ: %env_scudo_opts=may_return_null=1 not --crash %run %t new 2>&1         | FileCheck %s --check-prefix=CHECK-oom
+// RUNZ: %env_scudo_opts=may_return_null=0 not --crash %run %t new-nothrow 2>&1 | FileCheck %s --check-prefix=CHECK-max
+// RUNZ: %env_scudo_opts=may_return_null=1             %run %t new-nothrow 2>&1
+// RUNZ:                                               %run %t usable 2>&1
 
 // Tests for various edge cases related to sizes, notably the maximum size the
 // allocator can allocate. Tests that an integer overflow in the parameters of
@@ -54,12 +54,12 @@
     // Playing with the actual usable size of a chunk.
     void *p = malloc(1007);
     assert(p);
-    size_t size = __sanitizer_get_allocated_size(p);
+    size_t size = malloc_usable_size(p);
     assert(size >= 1007);
     memset(p, 'A', size);
     p = realloc(p, 2014);
     assert(p);
-    size = __sanitizer_get_allocated_size(p);
+    size = malloc_usable_size(p);
     assert(size >= 2014);
     memset(p, 'B', size);
     free(p);
Index: compiler-rt/test/scudo/secondary.c
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/secondary.c
@@ -1,53 +0,0 @@
-// RUN: %clang_scudo %s -o %t
-// RUN: %run %t after  2>&1 | FileCheck %s
-// RUN: %run %t before 2>&1 | FileCheck %s
-
-// Test that we hit a guard page when writing past the end of a chunk
-// allocated by the Secondary allocator, or writing too far in front of it.
-
-#include <assert.h>
-#include <malloc.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-void handler(int signo, siginfo_t *info, void *uctx) {
-  if (info->si_code == SEGV_ACCERR) {
-    fprintf(stderr, "SCUDO SIGSEGV\n");
-    exit(0);
-  }
-  exit(1);
-}
-
-int main(int argc, char **argv)
-{
-  // The size must be large enough to be serviced by the secondary allocator.
-  long page_size = sysconf(_SC_PAGESIZE);
-  size_t size = (1U << 17) + page_size;
-  struct sigaction a;
-
-  assert(argc == 2);
-  memset(&a, 0, sizeof(a));
-  a.sa_sigaction = handler;
-  a.sa_flags = SA_SIGINFO;
-
-  char *p = (char *)malloc(size);
-  assert(p);
-  memset(p, 'A', size); // This should not trigger anything.
-  // Set up the SIGSEGV handler now, as the rest should trigger an AV.
-  sigaction(SIGSEGV, &a, NULL);
-  if (!strcmp(argv[1], "after")) {
-    for (int i = 0; i < page_size; i++)
-      p[size + i] = 'A';
-  }
-  if (!strcmp(argv[1], "before")) {
-    for (int i = 1; i < page_size; i++)
-      p[-i] = 'A';
-  }
-  free(p);
-
-  return 1; // A successful test means we shouldn't reach this.
-}
-
-// CHECK: SCUDO SIGSEGV
Index: compiler-rt/test/scudo/rss.c
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/rss.c
@@ -1,57 +0,0 @@
-// RUN: %clang_scudo %s -o %t
-// RUN:                                                                                                  %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit
-// RUN: %env_scudo_opts="soft_rss_limit_mb=128"                                                          %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit
-// RUN: %env_scudo_opts="hard_rss_limit_mb=128"                                                          %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit
-// RUN: %env_scudo_opts="soft_rss_limit_mb=32:allocator_may_return_null=0"                           not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit
-// RUN: %env_scudo_opts="soft_rss_limit_mb=32:allocator_may_return_null=1"                               %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit-returnnull
-// RUN: %env_scudo_opts="soft_rss_limit_mb=32:allocator_may_return_null=0:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit
-// RUN: %env_scudo_opts="soft_rss_limit_mb=32:allocator_may_return_null=1:can_use_proc_maps_statm=0"     %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit-returnnull
-// RUN: %env_scudo_opts="hard_rss_limit_mb=32:allocator_may_return_null=0"                           not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
-// RUN: %env_scudo_opts="hard_rss_limit_mb=32:allocator_may_return_null=1"                           not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
-// RUN: %env_scudo_opts="hard_rss_limit_mb=32:allocator_may_return_null=0:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
-// RUN: %env_scudo_opts="hard_rss_limit_mb=32:allocator_may_return_null=1:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
-
-// Tests that the soft and hard RSS limits work as intended. Without limit or
-// with a high limit, the test should pass without any malloc returning NULL or
-// the program dying.
-// If a limit is specified, it should return some NULL or die depending on
-// allocator_may_return_null. This should also work without statm.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-static const size_t kNumAllocs = 64;
-static const size_t kAllocSize = 1 << 20;  // 1MB.
-
-static void *allocs[kNumAllocs];
-
-int main(int argc, char *argv[]) {
-  int returned_null = 0;
-  for (int i = 0; i < kNumAllocs; i++) {
-    // sleep for 100ms every 8 allocations, to allow the RSS check to catch up.
-    if (i != 0 && (i & 0x7) == 0)
-      usleep(100000);
-    allocs[i] = malloc(kAllocSize);
-    if (allocs[i])
-      memset(allocs[i], 0xff, kAllocSize);  // Dirty the pages.
-    else
-      returned_null++;
-  }
-  for (int i = 0; i < kNumAllocs; i++)
-    free(allocs[i]);
-  if (returned_null == 0)
-    printf("All malloc calls succeeded\n");
-  else
-    printf("%d malloc calls returned NULL\n", returned_null);
-  return 0;
-}
-
-// CHECK-nolimit: All malloc calls succeeded
-// CHECK-softlimit: soft RSS limit exhausted
-// CHECK-softlimit-NOT: malloc calls
-// CHECK-softlimit-returnnull: soft RSS limit exhausted
-// CHECK-softlimit-returnnull: malloc calls returned NULL
-// CHECK-hardlimit: hard RSS limit exhausted
-// CHECK-hardlimit-NOT: malloc calls
Index: compiler-rt/test/scudo/standalone/lit-unmigrated/realloc.cpp
===================================================================
--- compiler-rt/test/scudo/standalone/lit-unmigrated/realloc.cpp
+++ compiler-rt/test/scudo/standalone/lit-unmigrated/realloc.cpp
@@ -17,8 +17,7 @@
 
 #include <sanitizer/allocator_interface.h>
 
-int main(int argc, char **argv)
-{
+int main(int argc, char **argv) {
   void *p, *old_p;
   // Those sizes will exercise both allocators (Primary & Secondary).
   std::vector<size_t> sizes{1, 16, 1024, 32768, 1 << 16, 1 << 17, 1 << 20};
@@ -34,10 +33,11 @@
     p = nullptr;
     // Make sure we get a chunk with a usable size actually larger than size.
     do {
-      if (p) free(p);
+      if (p)
+        free(p);
       size += 16;
       p = malloc(size);
-      usable_size = __sanitizer_get_allocated_size(p);
+      usable_size = malloc_usable_size(p);
       assert(usable_size >= size);
     } while (usable_size == size);
     for (int i = 0; i < usable_size; i++)
@@ -58,7 +58,7 @@
       if (!strcmp(argv[1], "pointers")) {
         old_p = p = realloc(nullptr, size);
         assert(p);
-        size = __sanitizer_get_allocated_size(p);
+        size = malloc_usable_size(p);
         // Our realloc implementation will return the same pointer if the size
         // requested is lower than or equal to the usable size of the associated
         // chunk.
Index: compiler-rt/test/scudo/quarantine.c
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/quarantine.c
@@ -1,124 +0,0 @@
-// RUN: %clang_scudo %s -o %t
-// RUN: %env_scudo_opts="QuarantineSizeMb=1:QuarantineSizeKb=64"           not %run %t unused 2>&1
-// RUN: %env_scudo_opts="QuarantineSizeMb=1:QuarantineChunksUpToSize=256"  not %run %t unused 2>&1
-// RUN: %env_scudo_opts="QuarantineSizeKb=0:ThreadLocalQuarantineSizeKb=0"     %run %t zeroquarantine 2>&1
-// RUN: %env_scudo_opts=QuarantineSizeKb=64                                    %run %t smallquarantine 2>&1
-// RUN: %env_scudo_opts=QuarantineChunksUpToSize=256                           %run %t threshold 2>&1
-// RUN: %env_scudo_opts="QuarantineSizeMb=1"                                   %run %t oldquarantine 2>&1
-
-// Tests that the quarantine prevents a chunk from being reused right away.
-// Also tests that a chunk will eventually become available again for
-// allocation when the recycling criteria has been met. Finally, tests the
-// threshold up to which a chunk is quarantine, and the old quarantine behavior.
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sanitizer/allocator_interface.h>
-
-int main(int argc, char **argv)
-{
-  void *p, *old_p;
-  size_t allocated_bytes, size = 1U << 8, alignment = 1U << 8;
-
-  assert(argc == 2);
-  // First, warm up the allocator for the classes used.
-  p = malloc(size);
-  assert(p);
-  free(p);
-  p = malloc(size + 1);
-  assert(p);
-  free(p);
-  assert(posix_memalign(&p, alignment, size) == 0);
-  assert(p);
-  free(p);
-  assert(posix_memalign(&p, alignment, size + 1) == 0);
-  assert(p);
-  free(p);
-
-  if (!strcmp(argv[1], "zeroquarantine")) {
-    // Verifies that a chunk is deallocated right away when the local and
-    // global quarantine sizes are 0.
-    allocated_bytes = __sanitizer_get_current_allocated_bytes();
-    p = malloc(size);
-    assert(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    free(p);
-    assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
-  }
-  if (!strcmp(argv[1], "smallquarantine")) {
-    // The delayed freelist will prevent a chunk from being available right
-    // away.
-    p = malloc(size);
-    assert(p);
-    old_p = p;
-    free(p);
-    p = malloc(size);
-    assert(p);
-    assert(old_p != p);
-    free(p);
-
-    // Eventually the chunk should become available again.
-    char found = 0;
-    for (int i = 0; i < 0x200 && !found; i++) {
-      p = malloc(size);
-      assert(p);
-      found = (p == old_p);
-      free(p);
-    }
-    assert(found);
-  }
-  if (!strcmp(argv[1], "threshold")) {
-    // Verifies that a chunk of size greater than the threshold will be freed
-    // right away. Alignment has no impact on the threshold.
-    allocated_bytes = __sanitizer_get_current_allocated_bytes();
-    p = malloc(size + 1);
-    assert(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    free(p);
-    assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
-    assert(posix_memalign(&p, alignment, size + 1) == 0);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    free(p);
-    assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
-    // Verifies that a chunk of size lower or equal to the threshold will be
-    // quarantined.
-    p = malloc(size);
-    assert(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    free(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    allocated_bytes = __sanitizer_get_current_allocated_bytes();
-    assert(posix_memalign(&p, alignment, size) == 0);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    free(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-  }
-  if (!strcmp(argv[1], "oldquarantine")) {
-    // Verifies that we quarantine everything if the deprecated quarantine
-    // option is specified. Alignment has no impact on the threshold.
-    allocated_bytes = __sanitizer_get_current_allocated_bytes();
-    p = malloc(size);
-    assert(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    free(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    allocated_bytes = __sanitizer_get_current_allocated_bytes();
-    assert(posix_memalign(&p, alignment, size) == 0);
-    assert(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    free(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    // Secondary backed allocation.
-    allocated_bytes = __sanitizer_get_current_allocated_bytes();
-    p = malloc(1U << 19);
-    assert(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-    free(p);
-    assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
-  }
-
-  return 0;
-}
Index: compiler-rt/test/scudo/overflow.c
===================================================================
--- /dev/null
+++ compiler-rt/test/scudo/overflow.c
@@ -1,39 +0,0 @@
-// RUN: %clang_scudo %s -o %t
-// RUN:                                     not %run %t malloc     2>&1 | FileCheck %s
-// RUN: %env_scudo_opts=QuarantineSizeKb=64 not %run %t quarantine 2>&1 | FileCheck %s
-
-// Tests that header corruption of an allocated or quarantined chunk is caught.
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
-  ssize_t offset = sizeof(void *) == 8 ? 8 : 0;
-
-  assert(argc == 2);
-
-  if (!strcmp(argv[1], "malloc")) {
-    // Simulate a header corruption of an allocated chunk (1-bit)
-    void *p = malloc(1U << 4);
-    assert(p);
-    ((char *)p)[-(offset + 1)] ^= 1;
-    free(p);
-  }
-  if (!strcmp(argv[1], "quarantine")) {
-    void *p = malloc(1U << 4);
-    assert(p);
-    free(p);
-    // Simulate a header corruption of a quarantined chunk
-    ((char *)p)[-(offset + 2)] ^= 1;
-    // Trigger the quarantine recycle
-    for (int i = 0; i < 0x100; i++) {
-      p = malloc(1U << 8);
-      free(p);
-    }
-  }
-  return 0;
-}
-
-// CHECK: ERROR: corrupted chunk header at address
Index: compiler-rt/test/scudo/standalone/fsanitize.c
===================================================================
--- compiler-rt/test/scudo/standalone/fsanitize.c
+++ compiler-rt/test/scudo/standalone/fsanitize.c
@@ -1,17 +1,15 @@
 // Test various -fsanitize= additional flags combinations.
 
 // RUN: %clang_scudo %s -o %t
-// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: not --crash %run %t 2>&1 | FileCheck %s
 
 // RUN: %clang_scudo -shared-libsan %s -o %t
-// RUN: env LD_LIBRARY_PATH=`dirname %shared_libscudo`:$LD_LIBRARY_PATH not %run %t 2>&1 | FileCheck %s
-// RUN: %clang_scudo -shared-libsan -fsanitize-minimal-runtime %s -o %t
-// RUN: env LD_LIBRARY_PATH=`dirname %shared_minlibscudo`:$LD_LIBRARY_PATH not %run %t 2>&1 | FileCheck %s
+// RUN: env LD_LIBRARY_PATH=`dirname %shared_libscudo`:$LD_LIBRARY_PATH not --crash %run %t 2>&1 | FileCheck %s
 
 // RUN: %clang_scudo -static-libsan %s -o %t
-// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: not --crash %run %t 2>&1 | FileCheck %s
 // RUN: %clang_scudo -static-libsan -fsanitize-minimal-runtime %s -o %t
-// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: not --crash %run %t 2>&1 | FileCheck %s
 
 #include <assert.h>
 #include <stdlib.h>
Index: compiler-rt/test/scudo/standalone/double-free.cpp
===================================================================
--- compiler-rt/test/scudo/standalone/double-free.cpp
+++ compiler-rt/test/scudo/standalone/double-free.cpp
@@ -1,7 +1,7 @@
 // RUN: %clangxx_scudo %s -o %t
-// RUN: not %run %t malloc   2>&1 | FileCheck %s
-// RUN: not %run %t new      2>&1 | FileCheck %s
-// RUN: not %run %t newarray 2>&1 | FileCheck %s
+// RUN: not --crash %run %t malloc   2>&1 | FileCheck %s
+// RUN: not --crash %run %t new      2>&1 | FileCheck %s
+// RUN: not --crash %run %t newarray 2>&1 | FileCheck %s
 
 // Tests double-free error on pointers allocated with different allocation
 // functions.
@@ -10,8 +10,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-int main(int argc, char **argv)
-{
+int main(int argc, char **argv) {
   assert(argc == 2);
   if (!strcmp(argv[1], "malloc")) {
     void *p = malloc(sizeof(int));
Index: compiler-rt/test/scudo/standalone/dealloc-race.c
===================================================================
--- compiler-rt/test/scudo/standalone/dealloc-race.c
+++ compiler-rt/test/scudo/standalone/dealloc-race.c
@@ -1,12 +1,12 @@
 // RUN: %clang_scudo %s -O2 -o %t
 // RUN: %env_scudo_opts="QuarantineChunksUpToSize=0" %run %t 2>&1
 
-// This test attempts to reproduce a race condition in the deallocation path
-// when bypassing the Quarantine. The old behavior was to zero-out the chunk
-// header after checking its checksum, state & various other things, but that
-// left a window during which 2 (or more) threads could deallocate the same
-// chunk, with a net result of having said chunk present in those distinct
-// thread caches.
+// This test attempts to reproduce a race condition in the original Scudo in the
+// deallocation path when bypassing the Quarantine. The old behavior was to
+// zero-out the chunk header after checking its checksum, state & various other
+// things, but that left a window during which 2 (or more) threads could
+// deallocate the same chunk, with a net result of having said chunk present in
+// those distinct thread caches.
 
 // A passing test means all the children died with an error. The failing
 // scenario involves winning a race, so repro can be scarce.
Index: compiler-rt/test/scudo/standalone/alignment.c
===================================================================
--- compiler-rt/test/scudo/standalone/alignment.c
+++ compiler-rt/test/scudo/standalone/alignment.c
@@ -1,5 +1,5 @@
 // RUN: %clang_scudo %s -o %t
-// RUN: not %run %t pointers 2>&1 | FileCheck %s
+// RUN: not --crash %run %t pointers 2>&1 | FileCheck %s
 
 // Tests that a non MinAlignment aligned pointer will trigger the associated
 // error on deallocation.
Index: compiler-rt/test/scudo/standalone/aligned-new.cpp
===================================================================
--- compiler-rt/test/scudo/standalone/aligned-new.cpp
+++ compiler-rt/test/scudo/standalone/aligned-new.cpp
@@ -1,15 +1,15 @@
-// RUN: %clangxx_scudo -std=c++1z -faligned-allocation %s -o %t
+// RUN: %clangxx_scudo -std=c++17 -faligned-allocation %s -o %t
 // RUN:                                                 %run %t valid   2>&1
-// RUN: %env_scudo_opts=allocator_may_return_null=1     %run %t invalid 2>&1
-// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t invalid 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=may_return_null=1     %run %t invalid 2>&1
+// RUN: %env_scudo_opts=may_return_null=0 not --crash %run %t invalid 2>&1 | FileCheck %s
 
 // Tests that the C++17 aligned new/delete operators are working as expected.
 // Currently we do not check the consistency of the alignment on deallocation,
 // so this just tests that the APIs work.
 
 #include <assert.h>
-#include <stdio.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <string.h>
 
 // Define all new/delete to not depend on the version provided by the platform.
@@ -18,41 +18,54 @@
 struct nothrow_t {};
 static const nothrow_t nothrow;
 enum class align_val_t : size_t {};
-}  // namespace std
+} // namespace std
 
 void *operator new(size_t);
 void *operator new[](size_t);
-void *operator new(size_t, std::nothrow_t const&);
-void *operator new[](size_t, std::nothrow_t const&);
+void *operator new(size_t, std::nothrow_t const &);
+void *operator new[](size_t, std::nothrow_t const &);
 void *operator new(size_t, std::align_val_t);
 void *operator new[](size_t, std::align_val_t);
-void *operator new(size_t, std::align_val_t, std::nothrow_t const&);
-void *operator new[](size_t, std::align_val_t, std::nothrow_t const&);
+void *operator new(size_t, std::align_val_t, std::nothrow_t const &);
+void *operator new[](size_t, std::align_val_t, std::nothrow_t const &);
 
-void operator delete(void*) throw();
-void operator delete[](void*) throw();
-void operator delete(void*, std::nothrow_t const&);
-void operator delete[](void*, std::nothrow_t const&);
-void operator delete(void*, size_t) throw();
-void operator delete[](void*, size_t) throw();
-void operator delete(void*, std::align_val_t) throw();
-void operator delete[](void*, std::align_val_t) throw();
-void operator delete(void*, std::align_val_t, std::nothrow_t const&);
-void operator delete[](void*, std::align_val_t, std::nothrow_t const&);
-void operator delete(void*, size_t, std::align_val_t) throw();
-void operator delete[](void*, size_t, std::align_val_t) throw();
+void operator delete(void *) throw();
+void operator delete[](void *) throw();
+void operator delete(void *, std::nothrow_t const &);
+void operator delete[](void *, std::nothrow_t const &);
+void operator delete(void *, size_t) throw();
+void operator delete[](void *, size_t) throw();
+void operator delete(void *, std::align_val_t) throw();
+void operator delete[](void *, std::align_val_t) throw();
+void operator delete(void *, std::align_val_t, std::nothrow_t const &);
+void operator delete[](void *, std::align_val_t, std::nothrow_t const &);
+void operator delete(void *, size_t, std::align_val_t) throw();
+void operator delete[](void *, size_t, std::align_val_t) throw();
 
-template<typename T>
-inline T* break_optimization(T *arg) {
-  __asm__ __volatile__("" : : "r" (arg) : "memory");
+template <typename T>
+inline T *break_optimization(T *arg) {
+  __asm__ __volatile__(""
+                       :
+                       : "r"(arg)
+                       : "memory");
   return arg;
 }
 
-struct S12 { int a, b, c; };
-struct alignas(128) S12_128 { int a, b, c; };
-struct alignas(256) S12_256 { int a, b, c; };
-struct alignas(512) S1024_512 { char a[1024]; };
-struct alignas(1024) S1024_1024 { char a[1024]; };
+struct S12 {
+  int a, b, c;
+};
+struct alignas(128) S12_128 {
+  int a, b, c;
+};
+struct alignas(256) S12_256 {
+  int a, b, c;
+};
+struct alignas(512) S1024_512 {
+  char a[1024];
+};
+struct alignas(1024) S1024_1024 {
+  char a[1024];
+};
 
 int main(int argc, char **argv) {
   assert(argc == 2);
Index: compiler-rt/test/scudo/standalone/CMakeLists.txt
===================================================================
--- compiler-rt/test/scudo/standalone/CMakeLists.txt
+++ compiler-rt/test/scudo/standalone/CMakeLists.txt
@@ -1,3 +1,26 @@
+set(SCUDO_STANDALONE_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(SCUDO_STANDALONE_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+set(SCUDO_STANDALONE_TESTSUITES)
+set(SCUDO_STANDALONE_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} scudo_standalone)
+
+configure_lit_site_cfg(
+  ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+  ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py)
+
+foreach(arch ${SCUDO_STANDALONE_SUPPORTED_ARCH})
+  set(SCUDO_STANDALONE_TEST_TARGET_ARCH ${arch})
+  string(TOLOWER "-${arch}" SCUDO_STANDALONE_TEST_CONFIG_SUFFIX)
+  get_test_cc_for_arch(${arch} SCUDO_STANDALONE_TEST_TARGET_CC
+                       SCUDO_STANDALONE_TEST_TARGET_CFLAGS)
+  string(TOUPPER ${arch} ARCH_UPPER_CASE)
+  set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
+
+  configure_lit_site_cfg(
+    ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+    ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg.py)
+  list(APPEND SCUDO_STANDALONE_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endforeach()
+
 if(COMPILER_RT_INCLUDE_TESTS AND COMPILER_RT_HAS_SCUDO_STANDALONE)
   configure_lit_site_cfg(
     ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.py.in
Index: compiler-rt/test/scudo/options.cpp
===================================================================
--- compiler-rt/test/scudo/options.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN: %clangxx_scudo %s -o %t
-// RUN:                                                %run %t 2>&1
-// RUN: %env_scudo_opts=DeallocationTypeMismatch=0     %run %t 2>&1
-// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t 2>&1 | FileCheck %s
-
-// Tests that the options can be passed using getScudoDefaultOptions, and that
-// the environment ones take precedence over them.
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdlib.h>
-
-extern "C" const char* __scudo_default_options() {
-  return "DeallocationTypeMismatch=0";  // Defaults to true in scudo_flags.inc.
-}
-
-int main(int argc, char **argv)
-{
-  int *p = (int *)malloc(16);
-  assert(p);
-  delete p;
-  return 0;
-}
-
-// CHECK: ERROR: allocation type mismatch when deallocating address
Index: compiler-rt/test/scudo/lit.site.cfg.py.in
===================================================================
--- compiler-rt/test/scudo/lit.site.cfg.py.in
+++ /dev/null
@@ -1,11 +0,0 @@
-@LIT_SITE_CFG_IN_HEADER@
-
-config.name_suffix = "@SCUDO_TEST_CONFIG_SUFFIX@"
-config.target_arch = "@SCUDO_TEST_TARGET_ARCH@"
-config.target_cflags = "@SCUDO_TEST_TARGET_CFLAGS@"
-
-# Load common config for all compiler-rt lit tests.
-lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
-
-# Load tool-specific config that would do the real work.
-lit_config.load_config(config, "@SCUDO_LIT_SOURCE_DIR@/lit.cfg.py")
Index: compiler-rt/test/scudo/interface.cpp
===================================================================
--- compiler-rt/test/scudo/interface.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-// RUN: %clangxx_scudo %s -lstdc++ -o %t
-// RUN:                                                   %run %t ownership          2>&1
-// RUN:                                                   %run %t ownership-and-size 2>&1
-// RUN:                                                   %run %t heap-size          2>&1
-// RUN: %env_scudo_opts="allocator_may_return_null=1"     %run %t soft-limit         2>&1
-// RUN: %env_scudo_opts="allocator_may_return_null=1" not %run %t hard-limit         2>&1
-
-// Tests that the sanitizer interface functions behave appropriately.
-
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <vector>
-
-#include <sanitizer/allocator_interface.h>
-#include <sanitizer/scudo_interface.h>
-
-int main(int argc, char **argv)
-{
-  assert(argc == 2);
-
-  if (!strcmp(argv[1], "ownership")) {
-    // Ensures that __sanitizer_get_ownership can be called before any other
-    // allocator function, and that it behaves properly on a pointer not owned
-    // by us.
-    assert(!__sanitizer_get_ownership(argv));
-  }
-  if (!strcmp(argv[1], "ownership-and-size")) {
-    // Tests that __sanitizer_get_ownership and __sanitizer_get_allocated_size
-    // behave properly on chunks allocated by the Primary and Secondary.
-    void *p;
-    std::vector<ssize_t> sizes{1, 8, 16, 32, 1024, 32768,
-      1 << 16, 1 << 17, 1 << 20, 1 << 24};
-    for (size_t size : sizes) {
-      p = malloc(size);
-      assert(p);
-      assert(__sanitizer_get_ownership(p));
-      assert(__sanitizer_get_allocated_size(p) >= size);
-      free(p);
-    }
-  }
-  if (!strcmp(argv[1], "heap-size")) {
-    // Ensures that __sanitizer_get_heap_size can be called before any other
-    // allocator function.
-    assert(__sanitizer_get_heap_size() >= 0);
-  }
-  if (!strcmp(argv[1], "soft-limit")) {
-    // Verifies that setting the soft RSS limit at runtime works as expected.
-    std::vector<void *> pointers;
-    size_t size = 1 << 19;  // 512Kb
-    for (int i = 0; i < 5; i++) {
-      void *p = malloc(size);
-      memset(p, 0, size);
-      pointers.push_back(p);
-    }
-    // Set the soft RSS limit to 1Mb.
-    __scudo_set_rss_limit(1, 0);
-    usleep(20000);
-    // The following allocation should return NULL.
-    void *p = malloc(size);
-    assert(!p);
-    // Remove the soft RSS limit.
-    __scudo_set_rss_limit(0, 0);
-    // The following allocation should succeed.
-    p = malloc(size);
-    assert(p);
-    free(p);
-    while (!pointers.empty()) {
-      free(pointers.back());
-      pointers.pop_back();
-    }
-  }
-  if (!strcmp(argv[1], "hard-limit")) {
-    // Verifies that setting the hard RSS limit at runtime works as expected.
-    std::vector<void *> pointers;
-    size_t size = 1 << 19;  // 512Kb
-    for (int i = 0; i < 5; i++) {
-      void *p = malloc(size);
-      memset(p, 0, size);
-      pointers.push_back(p);
-    }
-    // Set the hard RSS limit to 1Mb
-    __scudo_set_rss_limit(1, 1);
-    usleep(20000);
-    // The following should trigger our death.
-    void *p = malloc(size);
-  }
-
-  return 0;
-}
Index: compiler-rt/test/scudo/CMakeLists.txt
===================================================================
--- compiler-rt/test/scudo/CMakeLists.txt
+++ compiler-rt/test/scudo/CMakeLists.txt
@@ -1,35 +1 @@
-set(SCUDO_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
-set(SCUDO_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
-
-set(SCUDO_TESTSUITES)
-
-set(SCUDO_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
-if(NOT COMPILER_RT_STANDALONE_BUILD)
-  list(APPEND SCUDO_TEST_DEPS scudo)
-endif()
-
-configure_lit_site_cfg(
-  ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
-  ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
-  )
-
-set(SCUDO_TEST_ARCH ${SCUDO_SUPPORTED_ARCH})
-foreach(arch ${SCUDO_TEST_ARCH})
-  set(SCUDO_TEST_TARGET_ARCH ${arch})
-  string(TOLOWER "-${arch}" SCUDO_TEST_CONFIG_SUFFIX)
-  get_test_cc_for_arch(${arch} SCUDO_TEST_TARGET_CC SCUDO_TEST_TARGET_CFLAGS)
-  string(TOUPPER ${arch} ARCH_UPPER_CASE)
-  set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
-
-  configure_lit_site_cfg(
-    ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
-    ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg.py)
-  list(APPEND SCUDO_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
-endforeach()
-
 add_subdirectory(standalone)
-
-add_lit_testsuite(check-scudo "Running the Scudo Hardened Allocator tests"
-  ${SCUDO_TESTSUITES}
-  DEPENDS ${SCUDO_TEST_DEPS})
-set_target_properties(check-scudo PROPERTIES FOLDER "Compiler-RT Misc")
Index: compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
===================================================================
--- compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
+++ compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
@@ -13,6 +13,7 @@
 
 #include "allocator_config.h"
 
+#include <errno.h>
 #include <stdint.h>
 
 extern "C" void malloc_postinit();
@@ -23,6 +24,28 @@
 enum class align_val_t : size_t {};
 } // namespace std
 
+// It's not valid for a non-throwing non-noreturn operator new to return
+// nullptr. In these cases, just terminate.
+#define CHECK_ALIGN_NORETURN(align)                                            \
+  do {                                                                         \
+    scudo::uptr alignment = static_cast<scudo::uptr>(align);                   \
+    if (UNLIKELY(!scudo::isPowerOfTwo(alignment))) {                           \
+      scudo::reportAlignmentNotPowerOfTwo(alignment);                          \
+    }                                                                          \
+  } while (0)
+
+#define CHECK_ALIGN(align)                                                     \
+  do {                                                                         \
+    scudo::uptr alignment = static_cast<scudo::uptr>(align);                   \
+    if (UNLIKELY(!scudo::isPowerOfTwo(alignment))) {                           \
+      if (Allocator.canReturnNull()) {                                         \
+        errno = EINVAL;                                                        \
+        return nullptr;                                                        \
+      }                                                                        \
+      scudo::reportAlignmentNotPowerOfTwo(alignment);                          \
+    }                                                                          \
+  } while (0)
+
 INTERFACE WEAK void *operator new(size_t size) {
   return Allocator.allocate(size, scudo::Chunk::Origin::New);
 }
@@ -38,20 +61,24 @@
   return Allocator.allocate(size, scudo::Chunk::Origin::NewArray);
 }
 INTERFACE WEAK void *operator new(size_t size, std::align_val_t align) {
+  CHECK_ALIGN_NORETURN(align);
   return Allocator.allocate(size, scudo::Chunk::Origin::New,
                             static_cast<scudo::uptr>(align));
 }
 INTERFACE WEAK void *operator new[](size_t size, std::align_val_t align) {
+  CHECK_ALIGN_NORETURN(align);
   return Allocator.allocate(size, scudo::Chunk::Origin::NewArray,
                             static_cast<scudo::uptr>(align));
 }
 INTERFACE WEAK void *operator new(size_t size, std::align_val_t align,
                                   std::nothrow_t const &) NOEXCEPT {
+  CHECK_ALIGN(align);
   return Allocator.allocate(size, scudo::Chunk::Origin::New,
                             static_cast<scudo::uptr>(align));
 }
 INTERFACE WEAK void *operator new[](size_t size, std::align_val_t align,
                                     std::nothrow_t const &) NOEXCEPT {
+  CHECK_ALIGN(align);
   return Allocator.allocate(size, scudo::Chunk::Origin::NewArray,
                             static_cast<scudo::uptr>(align));
 }
Index: clang/test/Driver/sanitizer-ld.c
===================================================================
--- clang/test/Driver/sanitizer-ld.c
+++ clang/test/Driver/sanitizer-ld.c
@@ -773,21 +773,11 @@
 // RUN:   | FileCheck --check-prefix=CHECK-SCUDO-LINUX %s
 // CHECK-SCUDO-LINUX: "{{.*}}ld{{(.exe)?}}"
 // CHECK-SCUDO-LINUX: "-pie"
-// CHECK-SCUDO-LINUX: "--whole-archive" "{{.*}}libclang_rt.scudo-i386.a" "--no-whole-archive"
+// CHECK-SCUDO-LINUX: "--whole-archive" "{{.*}}libclang_rt.scudo_standalone-i386.a" "--no-whole-archive"
 // CHECK-SCUDO-LINUX-NOT: "-lstdc++"
 // CHECK-SCUDO-LINUX: "-lpthread"
 // CHECK-SCUDO-LINUX: "-ldl"
 
-// RUN: %clang -fsanitize=scudo -fsanitize-minimal-runtime %s -### -o %t.o 2>&1 \
-// RUN:     -target i386-unknown-linux -fuse-ld=ld \
-// RUN:     -resource-dir=%S/Inputs/resource_dir \
-// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-SCUDO-MINIMAL-LINUX %s
-// CHECK-SCUDO-MINIMAL-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-SCUDO-MINIMAL-LINUX: "-pie"
-// CHECK-SCUDO-MINIMAL-LINUX: "--whole-archive" "{{.*}}libclang_rt.scudo_minimal-i386.a" "--no-whole-archive"
-// CHECK-SCUDO-MINIMAL-LINUX: "-lpthread"
-
 // RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \
 // RUN:     -target i386-unknown-linux -fuse-ld=ld -fsanitize=scudo -shared-libsan \
 // RUN:     -resource-dir=%S/Inputs/resource_dir \
@@ -796,8 +786,8 @@
 //
 // CHECK-SCUDO-SHARED-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
 // CHECK-SCUDO-SHARED-LINUX-NOT: "-lc"
-// CHECK-SCUDO-SHARED-LINUX-NOT: libclang_rt.scudo-i386.a"
-// CHECK-SCUDO-SHARED-LINUX: libclang_rt.scudo-i386.so"
+// CHECK-SCUDO-SHARED-LINUX-NOT: libclang_rt.scudo_standalone-i386.a"
+// CHECK-SCUDO-SHARED-LINUX: libclang_rt.scudo_standalone-i386.so"
 // CHECK-SCUDO-SHARED-LINUX-NOT: "-lpthread"
 // CHECK-SCUDO-SHARED-LINUX-NOT: "-lrt"
 // CHECK-SCUDO-SHARED-LINUX-NOT: "-ldl"
@@ -813,7 +803,7 @@
 // CHECK-SCUDO-ANDROID-NOT: "-lc"
 // CHECK-SCUDO-ANDROID: "-pie"
 // CHECK-SCUDO-ANDROID-NOT: "-lpthread"
-// CHECK-SCUDO-ANDROID: libclang_rt.scudo-arm-android.so"
+// CHECK-SCUDO-ANDROID: libclang_rt.scudo_standalone-arm-android.so"
 // CHECK-SCUDO-ANDROID-NOT: "-lpthread"
 
 // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
@@ -823,7 +813,7 @@
 // RUN:   | FileCheck --check-prefix=CHECK-SCUDO-ANDROID-STATIC %s
 // CHECK-SCUDO-ANDROID-STATIC: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
 // CHECK-SCUDO-ANDROID-STATIC: "-pie"
-// CHECK-SCUDO-ANDROID-STATIC: "--whole-archive" "{{.*}}libclang_rt.scudo-arm-android.a" "--no-whole-archive"
+// CHECK-SCUDO-ANDROID-STATIC: "--whole-archive" "{{.*}}libclang_rt.scudo_standalone-arm-android.a" "--no-whole-archive"
 // CHECK-SCUDO-ANDROID-STATIC-NOT: "-lstdc++"
 // CHECK-SCUDO-ANDROID-STATIC-NOT: "-lpthread"
 // CHECK-SCUDO-ANDROID-STATIC-NOT: "-lrt"
Index: clang/test/Driver/fuchsia.c
===================================================================
--- clang/test/Driver/fuchsia.c
+++ clang/test/Driver/fuchsia.c
@@ -153,7 +153,7 @@
 // CHECK-SCUDO-X86: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
 // CHECK-SCUDO-X86: "-fsanitize=safe-stack,scudo"
 // CHECK-SCUDO-X86: "-pie"
-// CHECK-SCUDO-X86: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.scudo.so"
+// CHECK-SCUDO-X86: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.scudo_standalone.so"
 
 // RUN: %clang %s -### --target=aarch64-unknown-fuchsia \
 // RUN:     -fsanitize=scudo 2>&1 \
@@ -163,7 +163,7 @@
 // CHECK-SCUDO-AARCH64: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
 // CHECK-SCUDO-AARCH64: "-fsanitize=shadow-call-stack,scudo"
 // CHECK-SCUDO-AARCH64: "-pie"
-// CHECK-SCUDO-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.scudo.so"
+// CHECK-SCUDO-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}aarch64-unknown-fuchsia{{/|\\\\}}libclang_rt.scudo_standalone.so"
 
 // RUN: %clang %s -### --target=x86_64-unknown-fuchsia \
 // RUN:     -fsanitize=scudo -fPIC -shared 2>&1 \
@@ -172,7 +172,7 @@
 // RUN:     | FileCheck %s -check-prefix=CHECK-SCUDO-SHARED
 // CHECK-SCUDO-SHARED: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
 // CHECK-SCUDO-SHARED: "-fsanitize=safe-stack,scudo"
-// CHECK-SCUDO-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.scudo.so"
+// CHECK-SCUDO-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.scudo_standalone.so"
 
 // RUN: %clang %s -### --target=aarch64-unknown-fuchsia \
 // RUN:     -fsanitize=leak 2>&1 \
Index: clang/lib/Driver/ToolChains/CommonArgs.cpp
===================================================================
--- clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -809,10 +809,7 @@
         SharedRuntimes.push_back("ubsan_standalone");
     }
     if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
-      if (SanArgs.requiresMinimalRuntime())
-        SharedRuntimes.push_back("scudo_minimal");
-      else
-        SharedRuntimes.push_back("scudo");
+      SharedRuntimes.push_back("scudo_standalone");
     }
     if (SanArgs.needsTsanRt() && SanArgs.linkRuntimes())
       SharedRuntimes.push_back("tsan");
@@ -893,15 +890,9 @@
     RequiredSymbols.push_back("__sanitizer_stats_register");
   }
   if (!SanArgs.needsSharedRt() && SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
-    if (SanArgs.requiresMinimalRuntime()) {
-      StaticRuntimes.push_back("scudo_minimal");
-      if (SanArgs.linkCXXRuntimes())
-        StaticRuntimes.push_back("scudo_cxx_minimal");
-    } else {
-      StaticRuntimes.push_back("scudo");
-      if (SanArgs.linkCXXRuntimes())
-        StaticRuntimes.push_back("scudo_cxx");
-    }
+    StaticRuntimes.push_back("scudo_standalone");
+    if (SanArgs.linkCXXRuntimes())
+      StaticRuntimes.push_back("scudo_standalone_cxx");
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to