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
4 changes: 2 additions & 2 deletions centipede/batch_fuzz_example/customized_centipede_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ echo -e "\n=== OOM test with CENTIPEDE_RUNNER_FLAGS=${CENTIPEDE_RUNNER_FLAGS}\n"
fuzztest::internal::test_replaying_target \
batch_fuzz 'RSS limit exceeded: [0-9][0-9]* > 1024' "oom"

export CENTIPEDE_RUNNER_FLAGS=":timeout_per_input=1:"
export CENTIPEDE_RUNNER_FLAGS=":timeout_per_input_ms=1000:"
echo -e "\n=== Timeout test with CENTIPEDE_RUNNER_FLAGS=${CENTIPEDE_RUNNER_FLAGS}\n"
fuzztest::internal::test_replaying_target \
batch_fuzz 'Per-input timeout exceeded: [0-9][0-9]* > 1' "slp"
batch_fuzz 'Per-input timeout exceeded: [0-9][0-9]* > 1000' "slp"

echo "PASS"
4 changes: 2 additions & 2 deletions centipede/centipede_callbacks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ std::string CentipedeCallbacks::ConstructRunnerFlags(
std::string_view extra_flags, bool disable_coverage) {
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("timeout_per_input_ms=", env_.timeout_per_input * 1000),
absl::StrCat("timeout_per_batch_ms=", env_.timeout_per_batch * 1000),
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
67 changes: 34 additions & 33 deletions centipede/runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ static uint64_t TimeInUsec() {
}

static void CheckWatchdogLimits() {
const uint64_t curr_time = time(nullptr);
const uint64_t curr_time_ms = TimeInUsec() / 1000;
struct Resource {
const char *what;
const char *units;
Expand All @@ -194,23 +194,23 @@ static void CheckWatchdogLimits() {
bool ignore_report;
const char *failure;
};
const uint64_t input_start_time = state.input_start_time;
const uint64_t batch_start_time = state.batch_start_time;
if (input_start_time == 0 || batch_start_time == 0) return;
const uint64_t input_start_time_ms = state.input_start_time_ms;
const uint64_t batch_start_time_ms = state.batch_start_time_ms;
if (input_start_time_ms == 0 || batch_start_time_ms == 0) return;
const Resource resources[] = {
{Resource{
/*what=*/"Per-input timeout",
/*units=*/"sec",
/*value=*/curr_time - input_start_time,
/*limit=*/state.run_time_flags.timeout_per_input,
/*units=*/"ms",
/*value=*/curr_time_ms - input_start_time_ms,
/*limit=*/state.run_time_flags.timeout_per_input_ms,
/*ignore_report=*/state.run_time_flags.ignore_timeout_reports != 0,
/*failure=*/kExecutionFailurePerInputTimeout.data(),
}},
{Resource{
/*what=*/"Per-batch timeout",
/*units=*/"sec",
/*value=*/curr_time - batch_start_time,
/*limit=*/state.run_time_flags.timeout_per_batch,
/*units=*/"ms",
/*value=*/curr_time_ms - batch_start_time_ms,
/*limit=*/state.run_time_flags.timeout_per_batch_ms,
/*ignore_report=*/state.run_time_flags.ignore_timeout_reports != 0,
/*failure=*/kExecutionFailurePerBatchTimeout.data(),
}},
Expand Down Expand Up @@ -270,7 +270,7 @@ static void CheckWatchdogLimits() {
sleep(1);

// No calls to ResetInputTimer() yet: input execution hasn't started.
if (state.input_start_time == 0) continue;
if (state.input_start_time_ms == 0) continue;

CheckWatchdogLimits();
}
Expand All @@ -282,7 +282,7 @@ __attribute__((noinline)) void CheckStackLimit(uintptr_t sp) {
// Check for the stack limit only if sp is inside the stack region.
if (stack_limit > 0 && tls.stack_region_low &&
tls.top_frame_sp - sp > stack_limit) {
const bool test_not_running = state.input_start_time == 0;
const bool test_not_running = state.input_start_time_ms == 0;
if (test_not_running) return;
if (stack_limit_exceeded.test_and_set()) return;
fprintf(stderr,
Expand All @@ -308,11 +308,11 @@ void GlobalRunnerState::CleanUpDetachedTls() {

void GlobalRunnerState::StartWatchdogThread() {
fprintf(stderr,
"Starting watchdog thread: timeout_per_input: %" PRIu64
" sec; timeout_per_batch: %" PRIu64 " sec; rss_limit_mb: %" PRIu64
" MB; stack_limit_kb: %" PRIu64 " KB\n",
state.run_time_flags.timeout_per_input.load(),
state.run_time_flags.timeout_per_batch,
"Starting watchdog thread: timeout_per_input_ms: %" PRIu64
"; timeout_per_batch_ms: %" PRIu64 "; rss_limit_mb: %" PRIu64
"; stack_limit_kb: %" PRIu64 "\n",
state.run_time_flags.timeout_per_input_ms.load(),
state.run_time_flags.timeout_per_batch_ms,
state.run_time_flags.rss_limit_mb.load(),
state.run_time_flags.stack_limit_kb.load());
pthread_t watchdog_thread;
Expand All @@ -325,12 +325,12 @@ void GlobalRunnerState::StartWatchdogThread() {
}

void GlobalRunnerState::ResetTimers() {
const auto curr_time = time(nullptr);
input_start_time = curr_time;
// batch_start_time is set only once -- just before the first input of the
const auto curr_time_ms = TimeInUsec() / 1000;
input_start_time_ms = curr_time_ms;
// batch_start_time_ms is set only once -- just before the first input of the
// batch is about to start running.
if (batch_start_time == 0) {
batch_start_time = curr_time;
if (batch_start_time_ms == 0) {
batch_start_time_ms = curr_time_ms;
}
}

Expand Down Expand Up @@ -627,7 +627,7 @@ static void RunOneInput(const uint8_t *data, size_t size,
int target_return_value = callbacks.Execute({data, size}) ? 0 : -1;
state.stats.exec_time_usec = UsecSinceLast();
CheckWatchdogLimits();
if (fuzztest::internal::state.input_start_time.exchange(0) != 0) {
if (fuzztest::internal::state.input_start_time_ms.exchange(0) != 0) {
PostProcessCoverage(target_return_value);
}
state.stats.post_time_usec = UsecSinceLast();
Expand Down Expand Up @@ -1207,13 +1207,14 @@ extern "C" void CentipedeSetStackLimit(size_t stack_limit_kb) {
fuzztest::internal::state.run_time_flags.stack_limit_kb = stack_limit_kb;
}

extern "C" void CentipedeSetTimeoutPerInput(uint64_t timeout_per_input) {
fprintf(stderr,
"CentipedeSetTimeoutPerInput: changing timeout_per_input to %" PRIu64
"\n",
timeout_per_input);
fuzztest::internal::state.run_time_flags.timeout_per_input =
timeout_per_input;
extern "C" void CentipedeSetTimeoutPerInput(uint64_t timeout_per_input_ms) {
fprintf(
stderr,
"CentipedeSetTimeoutPerInput: changing timeout_per_input_ms to %" PRIu64
"\n",
timeout_per_input_ms);
fuzztest::internal::state.run_time_flags.timeout_per_input_ms =
timeout_per_input_ms;
}

extern "C" __attribute__((weak)) const char *absl_nullable
Expand Down Expand Up @@ -1244,8 +1245,8 @@ extern "C" void CentipedeEndExecutionBatch() {
_exit(EXIT_FAILURE);
}
in_execution_batch = false;
fuzztest::internal::state.input_start_time = 0;
fuzztest::internal::state.batch_start_time = 0;
fuzztest::internal::state.input_start_time_ms = 0;
fuzztest::internal::state.batch_start_time_ms = 0;
}

extern "C" void CentipedePrepareProcessing() {
Expand All @@ -1255,7 +1256,7 @@ extern "C" void CentipedePrepareProcessing() {

extern "C" void CentipedeFinalizeProcessing() {
fuzztest::internal::CheckWatchdogLimits();
if (fuzztest::internal::state.input_start_time.exchange(0) != 0) {
if (fuzztest::internal::state.input_start_time_ms.exchange(0) != 0) {
fuzztest::internal::PostProcessCoverage(/*target_return_value=*/0);
}
}
Expand Down
12 changes: 6 additions & 6 deletions centipede/runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ struct RunTimeFlags {
uint64_t callstack_level : 8;
uint64_t use_counter_features : 1;
uint64_t use_auto_dictionary : 1;
std::atomic<uint64_t> timeout_per_input;
uint64_t timeout_per_batch;
std::atomic<uint64_t> timeout_per_input_ms;
uint64_t timeout_per_batch_ms;
std::atomic<uint64_t> stack_limit_kb;
std::atomic<uint64_t> rss_limit_mb;
uint64_t crossover_level;
Expand Down Expand Up @@ -171,8 +171,8 @@ struct GlobalRunnerState {
/*callstack_level=*/HasIntFlag(":callstack_level=", 0),
/*use_counter_features=*/HasFlag(":use_counter_features:"),
/*use_auto_dictionary=*/HasFlag(":use_auto_dictionary:"),
/*timeout_per_input=*/HasIntFlag(":timeout_per_input=", 0),
/*timeout_per_batch=*/HasIntFlag(":timeout_per_batch=", 0),
/*timeout_per_input_ms=*/HasIntFlag(":timeout_per_input_ms=", 0),
/*timeout_per_batch_ms=*/HasIntFlag(":timeout_per_batch_ms=", 0),
/*stack_limit_kb=*/HasIntFlag(":stack_limit_kb=", 0),
/*rss_limit_mb=*/HasIntFlag(":rss_limit_mb=", 0),
/*crossover_level=*/HasIntFlag(":crossover_level=", 50),
Expand Down Expand Up @@ -339,10 +339,10 @@ struct GlobalRunnerState {

// Per-input timer. Initially, zero. ResetInputTimer() sets it to the current
// time.
std::atomic<time_t> input_start_time;
std::atomic<time_t> input_start_time_ms;
// 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;
std::atomic<time_t> batch_start_time_ms;

// The Watchdog thread sets this to true.
std::atomic<bool> watchdog_thread_started;
Expand Down
4 changes: 2 additions & 2 deletions centipede/runner_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ extern "C" void CentipedeSetRssLimit(size_t rss_limit_mb);
// Reconfigures the stack limit to `stack_limit_kb` - 0 indicates no limit.
extern "C" void CentipedeSetStackLimit(size_t stack_limit_kb);

// Reconfigures `timeout_per_input` accordingly in seconds - 0 means no timeout.
extern "C" void CentipedeSetTimeoutPerInput(uint64_t timeout_per_input);
// Reconfigures input timeout to `timeout_per_input_ms` - 0 means no timeout.
extern "C" void CentipedeSetTimeoutPerInput(uint64_t timeout_per_input_ms);

// An overridable function to get the runner flags for configuring the runner
// during the initialization. The default implementation (as a weak function)
Expand Down
8 changes: 4 additions & 4 deletions centipede/testing/runner_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@ CENTIPEDE_RUNNER_FLAGS=":rss_limit_mb=4096:" $target "${oom}" \
CENTIPEDE_RUNNER_FLAGS=":rss_limit_mb=8192:" $target "${oom}" # must pass

echo ======== Check timeout
CENTIPEDE_RUNNER_FLAGS=":timeout_per_input=567:" "${target}" \
2>&1 | grep "timeout_per_input: 567"
CENTIPEDE_RUNNER_FLAGS=":timeout_per_input_ms=567000:" "${target}" \
2>&1 | grep "timeout_per_input_ms: 567"

CENTIPEDE_RUNNER_FLAGS=":timeout_per_input=2:" "${target}" "${slo}" \
CENTIPEDE_RUNNER_FLAGS=":timeout_per_input_ms=2000:" "${target}" "${slo}" \
2>&1 | grep "Per-input timeout exceeded"

{
CENTIPEDE_RUNNER_FLAGS=":ignore_timeout_reports:timeout_per_input=2:" "${target}" "${slo}";
CENTIPEDE_RUNNER_FLAGS=":ignore_timeout_reports:timeout_per_input_ms=2000:" "${target}" "${slo}";
echo "$?" > "${TEST_TMPDIR}/ignore_timeout_reports_exit_code";
} 2>&1 | grep "Per-input timeout exceeded" | grep "exiting without reporting as an error"
((`cat "${TEST_TMPDIR}/ignore_timeout_reports_exit_code"` == 0))
Expand Down
3 changes: 2 additions & 1 deletion fuzztest/internal/centipede_adaptor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,8 @@ void PopulateTestLimitsToCentipedeRunner(const Configuration& configuration) {
absl::FPrintF(GetStderr(),
"[.] Per-input time limit set to: %" PRId64 "s\n",
time_limit_seconds);
CentipedeSetTimeoutPerInput(time_limit_seconds);
CentipedeSetTimeoutPerInput(/*timeout_per_input_ms=*/time_limit_seconds *
1000);
}
}

Expand Down