[GWP-ASan] Split options_parser and backtrace_sanitizer_common.
Summary:
optional/options_parser and optional/backtrace_sanitizer_common are logically
separate components. They both use sanitizer-common to power their
functionality, but there was an unstated implicit dependency that in order for
backtrace_sanitizer_common to function correctly, one had to also use
options_parser.
This was because options_parser called __sanitizer::InitialiseCommonFlags. This
is a requirement for backtrace_sanitizer_common to work, as the sanitizer
unwinder uses the sanitizer_common flags and will SEGV on a null page if
they're not initialised correctly.
This patch removes this hidden dependency. You can now use
backtrace_sanitizer_common without the requirements of options_parser.
This patch also makes the GWP-ASan unit tests only have a soft dependency on
sanitizer-common. The unit tests previously explicitly used
__sanitizer::Printf, which is now provided under
tests/optional/printf_sanitizer_common. This allows Android to build the unit
tests using their own signal-safe printf().
Reviewers: eugenis
Reviewed By: eugenis
Subscribers: srhines, mgorny, #sanitizers, llvm-commits, vlad.tsyrklevich, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D66684
llvm-svn: 369825
GitOrigin-RevId: 27d69b2f4f6bf9b09755ae2428a4703eb4a4663b
diff --git a/optional/backtrace.h b/optional/backtrace.h
index 3aad9ea..6c9ee9f 100644
--- a/optional/backtrace.h
+++ b/optional/backtrace.h
@@ -17,7 +17,9 @@
// and backtrace printing functions when RTGwpAsanBacktraceLibc or
// RTGwpAsanBacktraceSanitizerCommon are linked. Use these functions to get the
// backtrace function for populating the Options::Backtrace and
-// Options::PrintBacktrace when initialising the GuardedPoolAllocator.
+// Options::PrintBacktrace when initialising the GuardedPoolAllocator. Please
+// note any thread-safety descriptions for the implementation of these functions
+// that you use.
Backtrace_t getBacktraceFunction();
PrintBacktrace_t getPrintBacktraceFunction();
} // namespace options
diff --git a/optional/backtrace_sanitizer_common.cpp b/optional/backtrace_sanitizer_common.cpp
index 427ac77..5e07fd6 100644
--- a/optional/backtrace_sanitizer_common.cpp
+++ b/optional/backtrace_sanitizer_common.cpp
@@ -13,6 +13,9 @@
#include "gwp_asan/optional/backtrace.h"
#include "gwp_asan/options.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
@@ -58,7 +61,18 @@
namespace gwp_asan {
namespace options {
-Backtrace_t getBacktraceFunction() { return Backtrace; }
+// This function is thread-compatible. It must be synchronised in respect to any
+// other calls to getBacktraceFunction(), calls to getPrintBacktraceFunction(),
+// and calls to either of the functions that they return. Furthermore, this may
+// require synchronisation with any calls to sanitizer_common that use flags.
+// Generally, this function will be called during the initialisation of the
+// allocator, which is done in a thread-compatible manner.
+Backtrace_t getBacktraceFunction() {
+ // The unwinder requires the default flags to be set.
+ __sanitizer::SetCommonFlagsDefaults();
+ __sanitizer::InitializeCommonFlags();
+ return Backtrace;
+}
PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
} // namespace options
} // namespace gwp_asan
diff --git a/options.h b/options.h
index 67a6129..ae3f3d4 100644
--- a/options.h
+++ b/options.h
@@ -25,6 +25,7 @@
// 2. pointers: "%p"
// 3. strings: "%[-]([0-9]*)?(\\.\\*)?s"
// 4. chars: "%c"
+// This function must be implemented in a signal-safe manner.
// =================================== Notes ===================================
// This function has a slightly different signature than the C standard
// library's printf(). Notably, it returns 'void' rather than 'int'.
diff --git a/tests/harness.h b/tests/harness.h
index 136e566..77f7b51 100644
--- a/tests/harness.h
+++ b/tests/harness.h
@@ -9,18 +9,24 @@
#ifndef GWP_ASAN_TESTS_HARNESS_H_
#define GWP_ASAN_TESTS_HARNESS_H_
-#include "gtest/gtest.h"
+#include <stdarg.h>
-// Include sanitizer_common first as gwp_asan/guarded_pool_allocator.h
-// transiently includes definitions.h, which overwrites some of the definitions
-// in sanitizer_common.
-#include "sanitizer_common/sanitizer_common.h"
+#include "gtest/gtest.h"
#include "gwp_asan/guarded_pool_allocator.h"
#include "gwp_asan/optional/backtrace.h"
-#include "gwp_asan/optional/options_parser.h"
#include "gwp_asan/options.h"
+namespace gwp_asan {
+namespace test {
+// This printf-function getter allows other platforms (e.g. Android) to define
+// their own signal-safe Printf function. In LLVM, we use
+// `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf
+// for this purpose.
+options::Printf_t getPrintfFunction();
+}; // namespace test
+}; // namespace gwp_asan
+
class DefaultGuardedPoolAllocator : public ::testing::Test {
public:
DefaultGuardedPoolAllocator() {
@@ -28,7 +34,7 @@
Opts.setDefaults();
MaxSimultaneousAllocations = Opts.MaxSimultaneousAllocations;
- Opts.Printf = __sanitizer::Printf;
+ Opts.Printf = gwp_asan::test::getPrintfFunction();
GPA.init(Opts);
}
@@ -49,7 +55,7 @@
Opts.MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg;
MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg;
- Opts.Printf = __sanitizer::Printf;
+ Opts.Printf = gwp_asan::test::getPrintfFunction();
GPA.init(Opts);
}
@@ -62,15 +68,10 @@
class BacktraceGuardedPoolAllocator : public ::testing::Test {
public:
BacktraceGuardedPoolAllocator() {
- // Call initOptions to initialise the internal sanitizer_common flags. These
- // flags are referenced by the sanitizer_common unwinder, and if left
- // uninitialised, they'll unintentionally crash the program.
- gwp_asan::options::initOptions();
-
gwp_asan::options::Options Opts;
Opts.setDefaults();
- Opts.Printf = __sanitizer::Printf;
+ Opts.Printf = gwp_asan::test::getPrintfFunction();
Opts.Backtrace = gwp_asan::options::getBacktraceFunction();
Opts.PrintBacktrace = gwp_asan::options::getPrintBacktraceFunction();
GPA.init(Opts);
diff --git a/tests/optional/printf_sanitizer_common.cpp b/tests/optional/printf_sanitizer_common.cpp
new file mode 100644
index 0000000..e823aeb
--- /dev/null
+++ b/tests/optional/printf_sanitizer_common.cpp
@@ -0,0 +1,22 @@
+//===-- printf_sanitizer_common.cpp -----------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "gwp_asan/options.h"
+
+namespace gwp_asan {
+namespace test {
+// This printf-function getter allows other platforms (e.g. Android) to define
+// their own signal-safe Printf function. In LLVM, we use
+// `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf
+// for this purpose.
+options::Printf_t getPrintfFunction() {
+ return __sanitizer::Printf;
+}
+}; // namespace test
+}; // namespace gwp_asan