| // Copyright 2025 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_DISPATCHER_H_ |
| #define THIRD_PARTY_CENTIPEDE_DISPATCHER_H_ |
| |
| // Dispatcher interface. |
| // |
| // This header needs to be C compatible. |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| // Inputs to perform mutations. |
| struct FuzzTestDispatcherInputForMutate { |
| const void* input; |
| size_t input_size; |
| const void* metadata; |
| size_t metadata_size; |
| }; |
| |
| // Callbacks to be provided by the fuzz testing framework to |
| // `FuzzTestDispatcherRun`. |
| struct FuzzTestDispatcherCallbacks { |
| // Optional callback to return an ID for the current binary. If not |
| // implemented, the controller will generate a default ID based on the binary |
| // path. |
| const char* (*get_binary_id)(); |
| // Callback to emit the list of available tests in the binary using |
| // `FuzzTestDispatcherEmitTestName`. |
| void (*list_tests)(); |
| // Callback to emit the seed inputs for a test using |
| // `FuzzTestDispatcherEmitSeed`. |
| void (*get_seeds)(); |
| // Optional callback to emit at most `num_mutants` from `inputs` with |
| // `num_inputs` entries using `FuzzTestDispatcherEmitMutant`. `shrink` != 0 |
| // means to generate smaller mutants than the inputs used for mutation. If not |
| // implemented, the controller will perform basic string-based mutations. |
| // |
| // TODO: xinhaoyuan - Reconsider mutation interface design instead of |
| // following the existing Centipede/runner protocol. |
| void (*mutate)(const struct FuzzTestDispatcherInputForMutate* inputs, |
| size_t num_inputs, size_t num_mutants, int shrink); |
| // Callback to execute `input` with `size` bytes. The callback should emit |
| // coverage feedback using `FuzzTestDispatcherEmitFeedback*` functions, and |
| // any metadata for further mutation using |
| // `FuzzTestDispatEmitExecutionMetadata`. In case the input caused a failure, |
| // the callback should emit the failure using |
| // `FuzzTestDispatcherEmitInputFailure`. |
| void (*execute)(const void* input, size_t size); |
| }; |
| |
| // Functions provided by the FuzzTest engine. |
| |
| // Returns 0 if the dispatcher mode is not enabled in the current process; 1 if |
| // the dispatcher mode is enabled; other values for unexpected errors. |
| int FuzzTestDispatcherIsEnabled(); |
| |
| // All functions below should be called only after `FuzzTestDispatcherIsEnabled` |
| // returns 1 in the current process. |
| |
| // Returns the test name under operation as an unowned, static, and |
| // null-terminated string. Returns nullptr if the current process is not |
| // operating on a specific test. |
| const char* FuzzTestDispatcherGetTestName(); |
| |
| // Give control to the FuzzTest engine to invoke `callbacks`. Returns an exit |
| // code for the current process desired by the engine. |
| int FuzzTestDispatcherRun(const struct FuzzTestDispatcherCallbacks* callbacks); |
| |
| // Emits a test name. Must be called from the `list_tests` callback. `name` must |
| // be a null-terminated string. |
| void FuzzTestDispatcherEmitTestName(const char* name); |
| |
| // Emits a seed input. Must be called from the `get_seeds` callback. `data` must |
| // not be nullptr and `size > 0` must hold. |
| void FuzzTestDispatcherEmitSeed(const void* data, size_t size); |
| |
| // Emits a mutant. Must be called from the `mutate` callback. `data` must not be |
| // nullptr and `size > 0` must hold. |
| void FuzzTestDispatcherEmitMutant(const void* data, size_t size); |
| |
| // TODO: b/437901326 - Unify the feedback emission interfaces. |
| |
| // Emits coverage feedback for the current input as an array of 32-bit features. |
| // |
| // For each 32-bit feature, the bit [31] is ignored; the 4 bits [30-27] |
| // indicate the feature domain for engine prioritization. The remaining 27 bits |
| // [26-0] represent the actual 27-bit feature ID in the domain. |
| // |
| // Must be called from the `execute` callback. `features` must not be nullptr |
| // and `num_features > 0` must hold. |
| void FuzzTestDispatcherEmitFeedbackAs32BitFeatures(const uint32_t* features, |
| size_t num_features); |
| |
| // Must only pass here the "raw" features exposed by the sancov runtime. |
| // |
| // Must be called from the `execute` callback. `features` must not be nullptr |
| // and `num_features > 0` must hold. |
| void FuzzTestDispatcherEmitFeedbackAsRawFeatures(const uint64_t* features, |
| size_t num_features); |
| |
| // Emits metadata of the current input as raw bytes. Must be called from |
| // the `execute` callback. |
| void FuzzTestDispatcherEmitExecutionMetadata(const void* metadata, size_t size); |
| |
| // Functions for emitting various types of failures. After calling any of these |
| // functions, later calls of these functions would have no effect, and the |
| // current process should exit after necessary cleanup. |
| |
| // Emits a failure caused by executing an input. Must be called within the |
| // `execute` callback. `description` should be a null-terminated string, or |
| // nullptr can be passed for an empty string; `signature` should be nullptr if |
| // and only if `signature_size == 0`. |
| void FuzzTestDispatcherEmitInputFailure(const char* description, |
| const void* signature, |
| size_t signature_size); |
| |
| // Emits a failure that should be ignored (i.e. not affecting the fuzzing |
| // workflows). `description` should be a null-terminated string, or nullptr can |
| // be passed for an empty string. |
| void FuzzTestDispatcherEmitIgnoredFailure(const char* description); |
| |
| // Emits a failure caused by the test setup. `description` should be a |
| // null-terminated string, or nullptr can be passed for an empty string. |
| void FuzzTestDispatcherEmitSetupFailure(const char* description); |
| |
| // Emits a failure due to reasons to skip the entire test. `description` should |
| // be a null-terminated string, or nullptr can be passed for an empty string. |
| void FuzzTestDispatcherEmitSkippedTestFailure(const char* description); |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif |
| |
| #endif |