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
5 changes: 3 additions & 2 deletions centipede/centipede_callbacks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,9 @@ CentipedeCallbacks::GetOrCreateCommandContextForBinary(
}
std::vector<std::string> env_diff = env_.env_diff_for_binaries;
env_diff.push_back(ConstructRunnerFlags(
absl::StrCat(":shmem:test=", env_.test_name, ":arg1=",
inputs_blobseq_.path(), ":arg2=", outputs_blobseq_.path(),
absl::StrCat(":shmem_size_mb=", env_.shmem_size_mb,
":test=", env_.test_name, ":arg1=", inputs_blobseq_.path(),
":arg2=", outputs_blobseq_.path(),
":failure_description_path=", failure_description_path_,
":failure_signature_path=", failure_signature_path_,
persistent_mode_server == nullptr
Expand Down
25 changes: 21 additions & 4 deletions centipede/engine_worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ constexpr std::string_view kWorkerPersistentModeSocketPathFlagHeader =
"persistent_mode_socket="; // TODO: Use better flag names when
// standardizing the protocol.
constexpr std::string_view kWorkerCrossOverLevel = "crossover_level=";
constexpr std::string_view kWorkerShmemSizeMbFlagHeader = "shmem_size_mb=";

struct WorkerState {
std::atomic<bool> has_failure_output = false;
Expand Down Expand Up @@ -407,28 +408,44 @@ __attribute__((constructor(200))) void WorkerInitEarly() {
LogLnSync{});
}

size_t GetShmemSize() {
static auto result = []() -> size_t {
const char* shmem_size_mb_str = GetWorkerFlag(kWorkerShmemSizeMbFlagHeader);
if (shmem_size_mb_str != nullptr) {
const int parsed =
atoi(shmem_size_mb_str); // NOLINT: can't use strto64, etc.
if (parsed < 0) return 0;
return static_cast<size_t>(parsed) << 20;
}
return 0;
}();
return result;
}

BlobSequence* GetInputsBlobSequence() {
static auto result = []() -> BlobSequence* {
if (!HasWorkerSwitchFlag("shmem")) {
const size_t shmem_size = GetShmemSize();
if (shmem_size == 0) {
return nullptr;
}
const char* input_path =
GetWorkerFlag(kWorkerInputsBlobSequencePathFlagHeader);
WorkerCheck(input_path != nullptr, "inputs blob sequence is missing");
return new SharedMemoryBlobSequence(input_path);
return new SharedMemoryBlobSequence(input_path, shmem_size);
}();
return result;
}

BlobSequence* GetOutputsBlobSequence() {
static auto result = []() -> BlobSequence* {
if (!HasWorkerSwitchFlag("shmem")) {
const size_t shmem_size = GetShmemSize();
if (shmem_size == 0) {
return nullptr;
}
const char* output_path =
GetWorkerFlag(kWorkerOutputsBlobSequencePathFlagHeader);
WorkerCheck(output_path != nullptr, "outputs blob sequence is missing");
return new SharedMemoryBlobSequence(output_path);
return new SharedMemoryBlobSequence(output_path, shmem_size);
}();
return result;
}
Expand Down
2 changes: 2 additions & 0 deletions centipede/minimize_crash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ void MinimizeCrash(ByteSpan crashy_input, const Environment& env,
auto callbacks = scoped_callback.callbacks();

FUZZTEST_LOG(INFO) << "MinimizeCrash: trying the original crashy input";
CreateLocalDirRemovedAtExit(TemporaryLocalDirPath());

BatchResult batch_result;
ByteArray original_crashy_input(crashy_input.begin(), crashy_input.end());
Expand All @@ -163,6 +164,7 @@ void MinimizeCrash(ByteSpan crashy_input, const Environment& env,
ThreadPool threads{static_cast<int>(env.num_threads)};
for (size_t i = 0; i < env.num_threads; ++i) {
threads.Schedule([&env, &callbacks_factory, &queue, &stop_condition]() {
CreateLocalDirRemovedAtExit(TemporaryLocalDirPath());
MinimizeCrash(env, callbacks_factory, queue, stop_condition);
});
}
Expand Down
19 changes: 11 additions & 8 deletions centipede/runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -902,9 +902,10 @@ void GlobalRunnerState::OnTermination() {
// This means, the binary is standalone with its own main(), and we need to
// report the coverage now.
if (!state->centipede_runner_main_executed &&
flag_helper.HasFlag(":shmem:")) {
sancov_state->shmem_size_mb != 0) {
PostProcessSancov(); // TODO(xinhaoyuan): do we know our exit status?
SharedMemoryBlobSequence outputs_blobseq(sancov_state->arg2);
SharedMemoryBlobSequence outputs_blobseq(sancov_state->arg2,
sancov_state->shmem_size_mb << 20);
StartSendingOutputsToEngine(outputs_blobseq);
FinishSendingOutputsToEngine(outputs_blobseq);
}
Expand Down Expand Up @@ -987,9 +988,9 @@ static int HandlePersistentMode(RunnerCallbacks& callbacks,
return EXIT_SUCCESS;
}

// If HasFlag(:shmem:), state->arg1 and state->arg2 are the names
// of in/out shared memory locations.
// Read inputs and write outputs via shared memory.
// If sancov_state->shmem_size_mb is non-zero, state->arg1 and state->arg2 are
// the names of in/out shared memory locations.
// Read inputs and write outputs via shared memory.
//
// Default: Execute ReadOneInputExecuteItAndDumpCoverage() for all inputs.//
//
Expand All @@ -1013,10 +1014,12 @@ int RunnerMain(int argc, char** argv, RunnerCallbacks& callbacks) {
}

// Inputs / outputs from shmem.
if (state->flag_helper.HasFlag(":shmem:")) {
if (sancov_state->shmem_size_mb != 0) {
if (!sancov_state->arg1 || !sancov_state->arg2) return EXIT_FAILURE;
SharedMemoryBlobSequence inputs_blobseq(sancov_state->arg1);
SharedMemoryBlobSequence outputs_blobseq(sancov_state->arg2);
SharedMemoryBlobSequence inputs_blobseq(sancov_state->arg1,
sancov_state->shmem_size_mb << 20);
SharedMemoryBlobSequence outputs_blobseq(sancov_state->arg2,
sancov_state->shmem_size_mb << 20);
// Persistent mode loop.
if (state->persistent_mode_socket > 0) {
return HandlePersistentMode(callbacks, inputs_blobseq, outputs_blobseq);
Expand Down
2 changes: 2 additions & 0 deletions centipede/sancov_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ struct SancovState {
const char *arg1 = flag_helper.GetStringFlag(":arg1=");
const char *arg2 = flag_helper.GetStringFlag(":arg2=");
const char *arg3 = flag_helper.GetStringFlag(":arg3=");
const size_t shmem_size_mb =
static_cast<size_t>(flag_helper.HasIntFlag(":shmem_size_mb=", 0));

SancovFlags flags = {
/*path_level=*/std::min(ThreadLocalSancovState::kBoundedPathLength,
Expand Down
8 changes: 4 additions & 4 deletions centipede/shared_memory_blob_sequence.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,10 @@ SharedMemoryBlobSequence::SharedMemoryBlobSequence(const char *name,
MmapData();
}

SharedMemoryBlobSequence::SharedMemoryBlobSequence(const char *path) {
SharedMemoryBlobSequence::SharedMemoryBlobSequence(const char* path,
size_t size) {
ErrorOnFailure(size < sizeof(Blob::size), "Size too small");
size_ = size;
// This is a quick way to tell shm-allocated paths from memfd paths without
// requiring the caller to specify.
if (strncmp(path, "/proc/", 6) == 0) {
Expand All @@ -146,9 +149,6 @@ SharedMemoryBlobSequence::SharedMemoryBlobSequence(const char *path) {
ErrorOnFailure(fd_ < 0, "open() failed");
strncpy(path_, path, PATH_MAX);
ErrorOnFailure(path_[PATH_MAX - 1] != 0, "path length exceeds PATH_MAX.");
struct stat statbuf = {};
ErrorOnFailure(fstat(fd_, &statbuf), "fstat() failed");
size_ = statbuf.st_size;
MmapData();
}

Expand Down
6 changes: 3 additions & 3 deletions centipede/shared_memory_blob_sequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class BlobSequence {
//
// void Child() {
// // Open an existing blob sequence.
// SharedMemoryBlobSequence child("/foo");
// SharedMemoryBlobSequence child("/foo", 1000);
//
// // Read the data written by parent.
// while (true) {
Expand All @@ -155,9 +155,9 @@ class SharedMemoryBlobSequence : public BlobSequence {
// memfd_create(2).
SharedMemoryBlobSequence(const char *name, size_t size, bool use_posix_shmem);

// Opens an existing shared blob sequence with the file `path`.
// Opens an existing shared blob sequence with the file `path` and `size`.
// Aborts on any failure.
explicit SharedMemoryBlobSequence(const char *path);
SharedMemoryBlobSequence(const char* path, size_t size);

// Releases all resources.
~SharedMemoryBlobSequence();
Expand Down
6 changes: 3 additions & 3 deletions centipede/shared_memory_blob_sequence_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ TEST_P(SharedMemoryBlobSequenceTest, ParentChild) {
EXPECT_TRUE(parent.Write(BlobFromVec(kTestData2, 456)));

// Child created.
SharedMemoryBlobSequence child(parent.path());
SharedMemoryBlobSequence child(parent.path(), 1000);
// Child reads data.
auto blob1 = child.Read();
EXPECT_EQ(kTestData1, Vec(blob1));
Expand Down Expand Up @@ -141,14 +141,14 @@ TEST_P(SharedMemoryBlobSequenceTest, CheckForResourceLeaks) {
for (int iter = 0; iter < kNumIters; iter++) {
SharedMemoryBlobSequence parent(ShmemName().c_str(), kBlobSize, GetParam());
parent.Write(BlobFromVec({1, 2, 3}));
SharedMemoryBlobSequence child(parent.path());
SharedMemoryBlobSequence child(parent.path(), kBlobSize);
EXPECT_EQ(child.Read().size, 3);
}
// Create a parent blob, then create and destroy lots of child blobs.
SharedMemoryBlobSequence parent(ShmemName().c_str(), kBlobSize, GetParam());
parent.Write(BlobFromVec({1, 2, 3, 4}));
for (int iter = 0; iter < kNumIters; iter++) {
SharedMemoryBlobSequence child(parent.path());
SharedMemoryBlobSequence child(parent.path(), kBlobSize);
EXPECT_EQ(child.Read().size, 4);
}
}
Expand Down
Loading