blob: 7eac41606115eb31a620e94bc511957db6afb807 [file] [log] [blame] [edit]
// Copyright 2022 The Centipede Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_CENTIPEDE_RUNNER_H_
#define THIRD_PARTY_CENTIPEDE_RUNNER_H_
#include <pthread.h> // NOLINT: use pthread to avoid extra dependencies.
#include <time.h>
#include <atomic>
#include <cstdint>
#include "./centipede/byte_array_mutator.h"
#include "./centipede/dispatcher_flag_helper.h"
#include "./centipede/knobs.h"
#include "./centipede/runner_interface.h"
#include "./centipede/runner_result.h"
#include "./centipede/runner_utils.h"
namespace fuzztest::internal {
// Flags derived from CENTIPEDE_RUNNER_FLAGS.
struct RunTimeFlags {
std::atomic<uint64_t> timeout_per_input;
uint64_t timeout_per_batch;
std::atomic<uint64_t> rss_limit_mb;
uint64_t crossover_level;
uint64_t ignore_timeout_reports : 1;
uint64_t max_len;
std::atomic<uint64_t> stack_limit_kb;
};
// One global object of this type is created by the runner at start up.
// All data members will be initialized to zero, unless they have initializers.
// Accesses to the subobjects should be fast, so we are trying to avoid
// extra memory references where possible.
//
// This class has a non-trivial destructor to work with targets that do not use
// the runner or LLVM fuzzer API at all.
//
// TODO(kcc): use a CTOR with absl::kConstInit (will require refactoring).
struct GlobalRunnerState {
// Used by LLVMFuzzerMutate and initialized in main().
ByteArrayMutator *byte_array_mutator = nullptr;
Knobs knobs;
GlobalRunnerState();
// Performs necessary cleanup on process termination.
void OnTermination();
DispatcherFlagHelper flag_helper =
DispatcherFlagHelper(CentipedeGetRunnerFlags());
// Note that this field reflects the initial runner flags. But some
// flags can change later (if wrapped with std::atomic).
RunTimeFlags run_time_flags = {
/*timeout_per_input=*/flag_helper.HasIntFlag(":timeout_per_input=", 0),
/*timeout_per_batch=*/flag_helper.HasIntFlag(":timeout_per_batch=", 0),
/*rss_limit_mb=*/flag_helper.HasIntFlag(":rss_limit_mb=", 0),
/*crossover_level=*/flag_helper.HasIntFlag(":crossover_level=", 50),
/*ignore_timeout_reports=*/
flag_helper.HasFlag(":ignore_timeout_reports:"),
/*max_len=*/flag_helper.HasIntFlag(":max_len=", 4000),
/*stack_limit_kb=*/flag_helper.HasIntFlag(":stack_limit_kb=", 0),
};
// The path to a file where the runner may write the description of failure.
const char *failure_description_path =
flag_helper.GetStringFlag(":failure_description_path=");
const char* persistent_mode_socket_path =
flag_helper.GetStringFlag(":persistent_mode_socket=");
int persistent_mode_socket = 0;
pthread_mutex_t execution_result_override_mu = PTHREAD_MUTEX_INITIALIZER;
// If not nullptr, it points to a batch result with either zero or one
// execution. When an execution result present, it will be passed as the
// execution result of the current test input. The object is owned and cleaned
// up by the state, protected by execution_result_override_mu, and set by
// `CentipedeSetExecutionResult()`.
BatchResult *execution_result_override;
// Execution stats for the currently executed input.
ExecutionResult::Stats stats;
// CentipedeRunnerMain() sets this to true.
bool centipede_runner_main_executed = false;
// Timeout-related machinery.
// Starts the watchdog thread that terminates the runner if any of the
// rss/time limits are exceeded.
void StartWatchdogThread();
// Resets the per-input timer. Call this before executing every input.
void ResetTimers();
// Per-input timer. Initially, zero. ResetInputTimer() sets it to the current
// time.
std::atomic<time_t> input_start_time;
// Per-batch timer. Initially, zero. ResetInputTimer() sets it to the current
// time before the first input and never resets it.
std::atomic<time_t> batch_start_time;
// The Watchdog thread sets this to true.
std::atomic<bool> watchdog_thread_started;
};
extern ExplicitLifetime<GlobalRunnerState> state;
} // namespace fuzztest::internal
#endif // THIRD_PARTY_CENTIPEDE_RUNNER_H_