| // 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. | |
| // | |
| // WARNING: This interface is not part of the engine; it's not yet stable and | |
| // may change at any point. | |
| #ifndef THIRD_PARTY_CENTIPEDE_RUNNER_INTERFACE_H_ | |
| #define THIRD_PARTY_CENTIPEDE_RUNNER_INTERFACE_H_ | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <functional> | |
| #include <memory> | |
| #include <string> | |
| #include <vector> | |
| #include "absl/base/nullability.h" | |
| #include "absl/types/span.h" | |
| #include "./centipede/execution_metadata.h" | |
| #include "./centipede/mutation_data.h" | |
| #include "./common/defs.h" | |
| // Legacy support for the libFuzzer API, https://llvm.org/docs/LibFuzzer.html | |
| // | |
| // WARNING: The legacy support will soon be deprecated. | |
| // Consider using the FuzzTest proper or fuzztest/llvm_fuzzer_{wrapper,main}.cc. | |
| using FuzzerTestOneInputCallback = int (*)(const uint8_t* data, size_t size); | |
| using FuzzerInitializeCallback = int (*)(int* argc, char*** argv); | |
| using FuzzerCustomMutatorCallback = size_t (*)(uint8_t* data, size_t size, | |
| size_t max_size, | |
| unsigned int seed); | |
| using FuzzerCustomCrossOverCallback = size_t (*)( | |
| const uint8_t* data1, size_t size1, const uint8_t* data2, size_t size2, | |
| uint8_t* out, size_t max_out_size, unsigned int seed); | |
| // This is the header-less interface of libFuzzer, see | |
| // https://llvm.org/docs/LibFuzzer.html. | |
| extern "C" { | |
| int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); | |
| __attribute__((weak)) int LLVMFuzzerInitialize(int* absl_nonnull argc, | |
| char*** absl_nonnull argv); | |
| __attribute__((weak)) size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size, | |
| size_t max_size, | |
| unsigned int seed); | |
| __attribute__((weak)) size_t LLVMFuzzerCustomCrossOver( | |
| const uint8_t* data1, size_t size1, const uint8_t* data2, size_t size2, | |
| uint8_t* out, size_t max_out_size, unsigned int seed); | |
| } // extern "C" | |
| // https://llvm.org/docs/LibFuzzer.html#using-libfuzzer-as-a-library | |
| extern "C" int LLVMFuzzerRunDriver( | |
| int* absl_nonnull argc, char*** absl_nonnull argv, | |
| FuzzerTestOneInputCallback test_one_input_cb); | |
| // LibFuzzer API declarations end here. | |
| // Reconfigures the RSS limit to `rss_limit_mb` - 0 indicates no limit. | |
| 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); | |
| // An overridable function to get the runner flags for configuring the runner | |
| // during the initialization. The default implementation (as a weak function) | |
| // gets the flags from CENTIPEDE_RUNNER_FLAGS env var. | |
| // | |
| // It should return either a nullptr or a constant string that is valid | |
| // throughout the entire process life-time. Multiple calls should always return | |
| // the same value. | |
| extern "C" const char* absl_nullable CentipedeGetRunnerFlags(); | |
| // An overridable function to override `LLVMFuzzerMutate` behavior. | |
| extern "C" size_t CentipedeLLVMFuzzerMutateCallback(uint8_t* data, size_t size, | |
| size_t max_size); | |
| // Prepares to run a batch of test executions that ends with calling | |
| // `CentipedeEndExecutionBatch`. | |
| // | |
| // `CentipedeBeginExecutionBatch` would abort if it was previously called | |
| // without a matching `CentipedeEndExecutionBatch` call. | |
| extern "C" void CentipedeBeginExecutionBatch(); | |
| // Finalizes the current batch of test executions. It would abort if no | |
| // `CentipedeBeginExecutionBatch` was called before without a matching | |
| // `CentipedeEndExecutionBatch` call. | |
| extern "C" void CentipedeEndExecutionBatch(); | |
| // Resets the internal state of the runner to process a new input. | |
| extern "C" void CentipedePrepareProcessing(); | |
| // Finalizes the processing of an input and stores the state internally. | |
| // | |
| // For tool integration, it can be called inside `RunnerCallbacks::Execute()` to | |
| // finalize the execution early before extra cleanups. | |
| extern "C" void CentipedeFinalizeProcessing(); | |
| // Enables (if `traced != 0`) or disables (if `traced == 0`) execution feedback | |
| // tracing on the current thread. Returns the previous `traced` value, which can | |
| // be used for later restoration. | |
| extern "C" int CentipedeSetCurrentThreadTraced(int traced); | |
| // Retrieves the execution results (including coverage information) after | |
| // processing an input. This function saves the data to the provided buffer and | |
| // returns the size of the saved data. It may be called after | |
| // CentipedeFinalizeProcessing(). | |
| extern "C" size_t CentipedeGetExecutionResult(uint8_t* data, size_t capacity); | |
| // Retrieves the coverage data collected during the processing of an input. | |
| // This function saves the raw coverage data to the provided buffer and returns | |
| // the size of the saved data. It may be called after | |
| // CentipedeFinalizeProcessing(). | |
| extern "C" size_t CentipedeGetCoverageData(uint8_t* data, size_t capacity); | |
| // Set the current execution result to the opaque memory `data` with `size`. | |
| // Such data is retrieved using `CentipedeGetExecutionResult`, possibly from | |
| // another process. When `data` is `nullptr`, will set the execution result to | |
| // "empty" with no features or metadata. | |
| extern "C" void CentipedeSetExecutionResult(const uint8_t* data, size_t size); | |
| // Set the failure description for the runner to propagate further. Only the | |
| // description from the first call will be used. | |
| // | |
| // If used during executing batch inputs, the rest of the inputs would be | |
| // skipped and the batch would be considered as failed. | |
| extern "C" void CentipedeSetFailureDescription(const char* description); | |
| namespace fuzztest::internal { | |
| // Callbacks interface implemented by the fuzzer and called by the runner. | |
| // | |
| // WARNING: This interface is designed for FuzzTest/Centipede integration - | |
| // no stability is guaranteed for other usages. | |
| class RunnerCallbacks { | |
| public: | |
| // Attempts to execute the test logic using `input`, and returns false if the | |
| // input should be ignored from the corpus, true otherwise. | |
| virtual bool Execute(void* input) = 0; | |
| // Provides the (deterministically) preset seed inputs by calling | |
| // `seed_callback` on each of them. The default implementation provides no | |
| // inputs. | |
| virtual void GetPresetSeedInputs( | |
| const std::function<void(void*)>& seed_callback); | |
| // Returns a random seed input. | |
| // The default implementation returns the input deserialized from the | |
| // single-byte input {0}. | |
| virtual void* GetRandomSeedInput(); | |
| // Returns the serialized configuration from the test target. The default | |
| // implementation returns the empty string. | |
| virtual std::string GetSerializedTargetConfig(); | |
| // Returns true if and only if the test target has a custom mutator. | |
| virtual bool HasCustomMutator() const = 0; | |
| // Mutates `origin` with `origin_metadata`. Must be overridden if | |
| // `HasCustomMutator()` returns true. | |
| virtual void* Mutate(void* origin, const ExecutionMetadata& origin_metadata); | |
| // Crosses over `origin` (with `origin_metadata`) with `other` (with | |
| // `other_metadata`). The default implementation returns `Mutate(origin, | |
| // origin_metadata)` | |
| virtual void* CrossOver(void* origin, | |
| const ExecutionMetadata& origin_metadata, void* other, | |
| const ExecutionMetadata& other_metadata); | |
| // Serializes `input` as bytes into `bytes_sink`. Must emit non-empty bytes. | |
| virtual void SerializeInput( | |
| void* input, const std::function<void(ByteSpan)>& bytes_sink) = 0; | |
| // Creates and returns the input deserialized from `bytes`. | |
| virtual void* DeserializeInput(ByteSpan bytes) = 0; | |
| // Called when the runner is done with `input`. | |
| virtual void FreeInput(void* input) = 0; | |
| virtual ~RunnerCallbacks() = default; | |
| }; | |
| // Wraps legacy fuzzer callbacks into a `RunnerCallbacks` instance. | |
| std::unique_ptr<RunnerCallbacks> CreateLegacyRunnerCallbacks( | |
| FuzzerTestOneInputCallback test_one_input_cb, | |
| FuzzerCustomMutatorCallback custom_mutator_cb, | |
| FuzzerCustomCrossOverCallback custom_crossover_cb); | |
| // The main Centipede Runner function. | |
| // It performs actions prescribed by argc/argv and environment variables | |
| // and returns EXIT_SUCCESS or EXIT_FAILURE. | |
| // Normally, the runner itself calls this function (LLVMFuzzerRunDriver). | |
| // | |
| // As an *experiment* we want to allow user code to call RunnerMain(). | |
| // This is not a guaranteed public interface (yet) and may disappear w/o notice. | |
| int RunnerMain(int argc, char** argv, RunnerCallbacks& callbacks); | |
| } // namespace fuzztest::internal | |
| #endif // THIRD_PARTY_CENTIPEDE_RUNNER_INTERFACE_H_ |