Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 44 additions & 39 deletions centipede/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -975,38 +975,6 @@ cc_library(
],
)

cc_library(
name = "engine_worker",
srcs = [
"engine_worker.cc",
"runner_utils.cc",
"runner_utils.h",
],
hdrs = ["engine_worker_abi.h"],
deps = [
":engine_abi",
":execution_metadata",
":feature",
":runner_request",
":runner_result",
":shared_memory_blob_sequence",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/random",
"@abseil-cpp//absl/random:bit_gen_ref",
"@com_google_fuzztest//common:defs",
],
)

cc_library(
name = "engine_controller_with_subprocess",
srcs = ["engine_controller_with_subprocess.cc"],
hdrs = ["engine_controller_abi.h"],
deps = [
"@com_google_fuzztest//centipede:engine_abi",
"@com_google_fuzztest//fuzztest/internal:escaping",
],
)

# The runner library is special:
# * It must not be instrumented with asan, sancov, etc.
# * It must not have heavy dependencies, and ideally not at all.
Expand All @@ -1027,8 +995,6 @@ RUNNER_SOURCES_NO_MAIN = [
"runner_dl_info.cc",
"runner_dl_info.h",
"runner_interface.h",
"runner_utils.cc",
"runner_utils.h",
"sancov_callbacks.cc",
"sancov_interceptors.cc",
"sancov_object_array.cc",
Expand Down Expand Up @@ -1076,11 +1042,12 @@ RUNNER_DEPS = [
":knobs",
":mutation_data",
":rolling_hash",
":engine_abi",
":runner_cmp_trace",
":runner_fork_server",
":runner_request",
":runner_result",
":runner_utils",
":engine_abi",
":engine_worker",
":shared_memory_blob_sequence",
"@com_google_fuzztest//common:defs",
"@abseil-cpp//absl/base:core_headers",
Expand All @@ -1089,6 +1056,45 @@ RUNNER_DEPS = [
"@abseil-cpp//absl/types:span",
]

cc_library(
name = "runner_utils",
srcs = ["runner_utils.cc"],
hdrs = ["runner_utils.h"],
copts = RUNNER_COPTS,
deps = ["@abseil-cpp//absl/base:nullability"],
)

cc_library(
name = "engine_worker",
srcs = [
"engine_worker.cc",
],
hdrs = ["engine_worker_abi.h"],
copts = RUNNER_COPTS,
deps = [
":engine_abi",
":execution_metadata",
":feature",
":runner_fork_server",
":runner_request",
":runner_result",
":runner_utils",
":shared_memory_blob_sequence",
"@abseil-cpp//absl/base:nullability",
"@com_google_fuzztest//common:defs",
],
)

cc_library(
name = "engine_controller_with_subprocess",
srcs = ["engine_controller_with_subprocess.cc"],
hdrs = ["engine_controller_abi.h"],
deps = [
"@com_google_fuzztest//centipede:engine_abi",
"@com_google_fuzztest//fuzztest/internal:escaping",
],
)

# A fuzz target needs to link with this library in order to run with Centipede.
# The fuzz target must provide its own main().
#
Expand Down Expand Up @@ -1217,8 +1223,6 @@ cc_library(
"reverse_pc_table.h",
"runner_dl_info.cc",
"runner_dl_info.h",
"runner_utils.cc",
"runner_utils.h",
"sancov_callbacks.cc",
"sancov_interceptors.cc",
"sancov_object_array.cc",
Expand All @@ -1240,6 +1244,7 @@ cc_library(
":foreach_nonzero",
":int_utils",
":runner_cmp_trace",
":runner_utils",
"@abseil-cpp//absl/base:core_headers",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/numeric:bits",
Expand Down Expand Up @@ -1957,7 +1962,7 @@ cc_test(
timeout = "long",
srcs = ["centipede_test.cc"],
data = [
"@com_google_fuzztest//centipede",
":centipede",
"@com_google_fuzztest//centipede/testing:abort_fuzz_target",
"@com_google_fuzztest//centipede/testing:async_failing_target",
"@com_google_fuzztest//centipede/testing:expensive_startup_fuzz_target",
Expand Down
64 changes: 45 additions & 19 deletions centipede/centipede_callbacks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <algorithm>
#include <cerrno>
#include <cmath>
#include <cstddef>
#include <cstdlib>
#include <cstring>
Expand Down Expand Up @@ -194,8 +195,11 @@ class CentipedeCallbacks::PersistentModeServer {
int poll_ret = -1;
do {
poll_fd = {fd, static_cast<short>(event)};
const int poll_timeout_ms = static_cast<int>(absl::ToInt64Milliseconds(
std::max(deadline - absl::Now(), kPollMinimalTimeout)));
const int poll_timeout_ms =
deadline == absl::InfiniteFuture()
? -1
: static_cast<int>(std::ceil(absl::ToDoubleMilliseconds(
std::max(deadline - absl::Now(), kPollMinimalTimeout))));
poll_ret = poll(&poll_fd, 1, poll_timeout_ms);
} while (poll_ret < 0 && errno == EINTR);
if (poll_ret == 1 && (poll_fd.revents & (event | POLLHUP)) == event) {
Expand Down Expand Up @@ -343,7 +347,6 @@ std::string CentipedeCallbacks::ConstructRunnerFlags(
std::vector<std::string> flags = {
"CENTIPEDE_RUNNER_FLAGS=",
absl::StrCat("timeout_per_input=", env_.timeout_per_input),
absl::StrCat("timeout_per_batch=", env_.timeout_per_batch),
absl::StrCat("address_space_limit_mb=", env_.address_space_limit_mb),
absl::StrCat("rss_limit_mb=", env_.rss_limit_mb),
absl::StrCat("stack_limit_kb=", env_.stack_limit_kb),
Expand Down Expand Up @@ -499,9 +502,33 @@ int CentipedeCallbacks::RunBatchForBinary(std::string_view binary) {
if (!should_clean_up) return exit_code;
FUZZTEST_LOG(ERROR) << "Cleaning up the batch execution with timeout: "
<< env_.runner_cleanup_timeout;
auto RemoveCommand = [&] {
// We need to save any execution log before the destruction of the command.
std::error_code ec;
std::filesystem::rename(last_execute_log_path_, saved_execute_log_path_,
ec);
if (ec) {
FUZZTEST_LOG(ERROR) << "Failed to save the execution log "
<< last_execute_log_path_ << " to "
<< saved_execute_log_path_ << "(" << ec.message()
<< "). Left with an empty log ...";
(void)std::filesystem::remove(saved_execute_log_path_, ec);
}
last_execute_log_path_ = saved_execute_log_path_;
command_contexts_.erase(
std::find_if(command_contexts_.begin(), command_contexts_.end(),
[=](const auto& command_context) {
return command_context->cmd.path() == binary;
}));
};
const auto cleanup_deadline = absl::Now() + env_.runner_cleanup_timeout;
if (cmd.is_executing() && command_context.persistent_mode_server != nullptr &&
command_context.persistent_mode_server->in_batch()) {
const auto ret = cmd.Wait(absl::Now());
if (ret.has_value()) {
RemoveCommand();
return *ret;
}
// Give a chance for the batch to gracefully stop. If succeeded, we can keep
// the Command.
cmd.RequestStop();
Expand All @@ -518,22 +545,7 @@ int CentipedeCallbacks::RunBatchForBinary(std::string_view binary) {
FUZZTEST_LOG(ERROR) << "Failed to wait for the batch execution cleanup.";
return EXIT_FAILURE;
}();
// We need to save any execution log before the destruction of the command.
std::error_code ec;
std::filesystem::rename(last_execute_log_path_, saved_execute_log_path_, ec);
if (ec) {
FUZZTEST_LOG(ERROR) << "Failed to save the execution log "
<< last_execute_log_path_ << " to "
<< saved_execute_log_path_ << "(" << ec.message()
<< "). Left with an empty log ...";
(void)std::filesystem::remove(saved_execute_log_path_, ec);
}
last_execute_log_path_ = saved_execute_log_path_;
command_contexts_.erase(
std::find_if(command_contexts_.begin(), command_contexts_.end(),
[=](const auto& command_context) {
return command_context->cmd.path() == binary;
}));
RemoveCommand();
return exit_code;
}

Expand Down Expand Up @@ -565,8 +577,12 @@ int CentipedeCallbacks::ExecuteCentipedeSancovBinaryWithShmem(
}

// Run.
const auto batch_start_time = absl::Now();
const int exit_code = RunBatchForBinary(binary);
inputs_blobseq_.ReleaseSharedMemory(); // Inputs are already consumed.
const bool batch_timed_out =
env_.timeout_per_batch > 0 &&
absl::Now() - batch_start_time > absl::Seconds(env_.timeout_per_batch);

// Get results.
batch_result.exit_code() = exit_code;
Expand All @@ -591,6 +607,16 @@ int CentipedeCallbacks::ExecuteCentipedeSancovBinaryWithShmem(

if (env_.print_runner_log) PrintExecutionLog();

if (batch_timed_out) {
FUZZTEST_LOG(INFO)
<< "Batch timeout detected. Replacing the original exit code: "
<< exit_code
<< ", failure description: " << batch_result.failure_description();
batch_result.failure_description() = kExecutionFailurePerBatchTimeout;
batch_result.exit_code() = EXIT_FAILURE;
return EXIT_FAILURE;
}

// TODO: b/467103298 - Handle failures when the exit code is zero, e.g., when
// the target exits via `std::_Exit(0)`.
if (exit_code != EXIT_SUCCESS) {
Expand Down
Loading
Loading