diff --git a/centipede/batch_fuzz_example/customized_centipede_test.sh b/centipede/batch_fuzz_example/customized_centipede_test.sh index 4d3e2064a..40fe7885b 100755 --- a/centipede/batch_fuzz_example/customized_centipede_test.sh +++ b/centipede/batch_fuzz_example/customized_centipede_test.sh @@ -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" diff --git a/centipede/centipede_callbacks.cc b/centipede/centipede_callbacks.cc index 819e8000c..4eb484daa 100644 --- a/centipede/centipede_callbacks.cc +++ b/centipede/centipede_callbacks.cc @@ -112,8 +112,8 @@ std::string CentipedeCallbacks::ConstructRunnerFlags( std::string_view extra_flags, bool disable_coverage) { std::vector 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), diff --git a/centipede/runner.cc b/centipede/runner.cc index d998350b5..e6223d861 100644 --- a/centipede/runner.cc +++ b/centipede/runner.cc @@ -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; @@ -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(), }}, @@ -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(); } @@ -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, @@ -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; @@ -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; } } @@ -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(); @@ -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 @@ -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() { @@ -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); } } diff --git a/centipede/runner.h b/centipede/runner.h index 8e4ff8eff..089068d8f 100644 --- a/centipede/runner.h +++ b/centipede/runner.h @@ -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 timeout_per_input; - uint64_t timeout_per_batch; + std::atomic timeout_per_input_ms; + uint64_t timeout_per_batch_ms; std::atomic stack_limit_kb; std::atomic rss_limit_mb; uint64_t crossover_level; @@ -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), @@ -339,10 +339,10 @@ struct GlobalRunnerState { // Per-input timer. Initially, zero. ResetInputTimer() sets it to the current // time. - std::atomic input_start_time; + std::atomic 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 batch_start_time; + std::atomic batch_start_time_ms; // The Watchdog thread sets this to true. std::atomic watchdog_thread_started; diff --git a/centipede/runner_interface.h b/centipede/runner_interface.h index f12691dd8..5b6fe1edd 100644 --- a/centipede/runner_interface.h +++ b/centipede/runner_interface.h @@ -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) diff --git a/centipede/testing/runner_test.sh b/centipede/testing/runner_test.sh index c98acc2ab..35de1a136 100755 --- a/centipede/testing/runner_test.sh +++ b/centipede/testing/runner_test.sh @@ -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)) diff --git a/fuzztest/internal/centipede_adaptor.cc b/fuzztest/internal/centipede_adaptor.cc index 7eb0e8785..54290eeff 100644 --- a/fuzztest/internal/centipede_adaptor.cc +++ b/fuzztest/internal/centipede_adaptor.cc @@ -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); } }