Skip to content

Commit

Permalink
#Centipede Add address-sanitized puzzles into the test workflow.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 574999311
  • Loading branch information
xinhaoyuan authored and copybara-github committed Nov 2, 2023
1 parent 5b1b232 commit 79af048
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 81 deletions.
1 change: 0 additions & 1 deletion centipede/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,6 @@ RUNNER_SOURCES_NO_MAIN = [
"runner_interceptors.cc",
"runner_interface.h",
"runner_sancov.cc",
"runner_sanitizer.cc",
"shared_memory_blob_sequence.cc",
"shared_memory_blob_sequence.h",
]
Expand Down
2 changes: 1 addition & 1 deletion centipede/puzzles/puzzle.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def puzzle(name):
data = [
":" + name,
name + ".cc",
"@com_google_fuzztest//centipede",
"@com_google_fuzztest//centipede:centipede_uninstrumented",
"@com_google_fuzztest//centipede:test_util_sh",
],
)
2 changes: 1 addition & 1 deletion centipede/puzzles/run_puzzle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ ls -la "$(dirname "$0")"
source "$(dirname "$0")/../test_util.sh"

readonly centipede_dir="$(centipede::get_centipede_test_srcdir)"
centipede::maybe_set_var_to_executable_path centipede "${centipede_dir}/centipede"
centipede::maybe_set_var_to_executable_path centipede "${centipede_dir}/centipede_uninstrumented"
readonly centipede

readonly target_name="$(basename "$0")"
Expand Down
2 changes: 2 additions & 0 deletions centipede/run_test_workflow.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ bazel test "${BAZEL_ARGS[@]}" --local_test_jobs=1 --test_output=streamed \
centipede:all &&
bazel test "${BAZEL_ARGS[@]}" centipede/testing:instrumentation_test centipede/testing:runner_test &&
bazel test "${BAZEL_ARGS[@]}" centipede/puzzles:all
bazel test "${BAZEL_ARGS[@]}" --linkopt=-fsanitize=address --copt=-fsanitize=address centipede/puzzles:all

declare -ri exit_code=$?
set -e

Expand Down
7 changes: 4 additions & 3 deletions centipede/runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -908,9 +908,10 @@ extern void ForkServerCallMeVeryEarly();
// * linker sees them and decides to drop runner_sancov.o.
extern void RunnerSancov();
[[maybe_unused]] auto fake_reference_for_runner_sancov = &RunnerSancov;
// Same for runner_sanitizer.cc.
extern void RunnerSanitizer();
[[maybe_unused]] auto fake_reference_for_runner_sanitizer = &RunnerSanitizer;
// Same for runner_interceptor.cc.
extern void RunnerInterceptor();
[[maybe_unused]] auto fake_reference_for_runner_interceptor =
&RunnerInterceptor;

GlobalRunnerState::GlobalRunnerState() {
// TODO(kcc): move some code from CentipedeRunnerMain() here so that it works
Expand Down
68 changes: 44 additions & 24 deletions centipede/runner_interceptors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,7 @@
// limitations under the License.

// Function interceptors for Centipede.
// Interceptors are disabled under ASAN/TSAN/MSAN because those sanitizers
// have their own conflicting interceptors.
// The typical usage of sanitizers with Centipede is via the --extra_binaries
// flag, where the sanitized binary does not produce coverage output and thus
// doesn't need (most of?) interceptors.
#if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \
!defined(MEMORY_SANITIZER)

#include <dlfcn.h> // for dlsym()
#include <pthread.h>

Expand Down Expand Up @@ -77,19 +71,49 @@ int NormalizeCmpResult(int result) {

} // namespace

// Initialize original function pointers at the module startup. This may still
// be too late, since the functions may be used before this module is
// initialized. So, the interceptor may not assume that X_orig != nullptr for
// function X.
static auto memcmp_orig =
FuncAddr<int (*)(const void *s1, const void *s2, size_t n)>("memcmp");
static auto strcmp_orig =
FuncAddr<int (*)(const char *s1, const char *s2)>("strcmp");

// TODO(kcc): as we implement more functions like memcmp_fallback and
// length_of_common_prefix, move them into a separate module and unittest.
namespace centipede {
void RunnerInterceptor() {} // to be referenced in runner.cc
} // namespace centipede

// Fallback for the case memcmp_orig is null.
// A sanitizer-compatible way to intercept functions that are potentially
// intercepted by sanitizers, in which case the symbol __interceptor_X would be
// defined for intercepted function X. So we always forward an intercepted call
// to the sanitizer interceptor if it exists, and fall back to the next
// definition following dlsym.
//
// We define the X_orig pointers that are statically initialized to GetOrig_X()
// with the aforementioned logic to fill the pointers early, but they might
// still be too late. So the Centipede interceptors might need to handle the
// nullptr case and/or use REAL(X), which calls GetOrig_X() when needed. Also
// see compiler-rt/lib/interception/interception.h in the llvm-project source
// code.
//
// Note that since LLVM 17 it allows three interceptions (from the original
// binary, an external tool, and a sanitizer) to co-exist under a new scheme,
// while it is still compatible with the old way used here.
#define SANITIZER_INTERCEPTOR_NAME(orig_func_name) \
__interceptor_##orig_func_name
#define DECLARE_CENTIPEDE_ORIG_FUNC(ret_type, orig_func_name, args) \
extern "C" __attribute__((weak)) \
ret_type(SANITIZER_INTERCEPTOR_NAME(orig_func_name)) args; \
static decltype(&SANITIZER_INTERCEPTOR_NAME( \
orig_func_name)) GetOrig_##orig_func_name() { \
if (auto p = &SANITIZER_INTERCEPTOR_NAME(orig_func_name)) return p; \
return FuncAddr<decltype(&SANITIZER_INTERCEPTOR_NAME(orig_func_name))>( \
#orig_func_name); \
} \
static ret_type(*orig_func_name##_orig) args = GetOrig_##orig_func_name()
#define REAL(orig_func_name) \
(orig_func_name##_orig ? orig_func_name##_orig : GetOrig_##orig_func_name())

DECLARE_CENTIPEDE_ORIG_FUNC(int, memcmp,
(const void *s1, const void *s2, size_t n));
DECLARE_CENTIPEDE_ORIG_FUNC(int, strcmp, (const char *s1, const char *s2));
DECLARE_CENTIPEDE_ORIG_FUNC(int, pthread_create,
(pthread_t * thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg));

// Fallback for the case *cmp_orig is null.
// Will be executed several times at process startup, if at all.
static int memcmp_fallback(const void *s1, const void *s2, size_t n) {
const auto *p1 = static_cast<const uint8_t *>(s1);
Expand Down Expand Up @@ -131,12 +155,8 @@ extern "C" int strcmp(const char *s1, const char *s2) {
// Calls real pthread_create, but wraps the start_routine() in MyThreadStart.
extern "C" int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg) {
static auto pthread_create_orig =
FuncAddr<int (*)(pthread_t *, const pthread_attr_t *, void *(*)(void *),
void *)>("pthread_create");
// Wrap the arguments. Will be deleted in MyThreadStart.
auto *wrapped_args = new ThreadCreateArgs{start_routine, arg};
// Run the actual pthread_create.
return pthread_create_orig(thread, attr, MyThreadStart, wrapped_args);
return REAL(pthread_create)(thread, attr, MyThreadStart, wrapped_args);
}
#endif // not ASAN/TSAN/MSAN
50 changes: 0 additions & 50 deletions centipede/runner_sanitizer.cc

This file was deleted.

2 changes: 1 addition & 1 deletion centipede/testing/build_defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ affect all its transitive dependencies as well.
# Change the flags from the default ones to sancov:
# https://clang.llvm.org/docs/SanitizerCoverage.html.
def _sancov_transition_impl(settings, attr):
features_to_strip = ["asan", "tsan", "msan"]
features_to_strip = ["tsan", "msan"]
filtered_features = [
x
for x in settings["//command_line_option:features"]
Expand Down

0 comments on commit 79af048

Please sign in to comment.