{"id":18894088,"url":"https://github.com/trailofbits/test-fuzz","last_synced_at":"2025-05-15T04:06:44.158Z","repository":{"id":38456988,"uuid":"309853076","full_name":"trailofbits/test-fuzz","owner":"trailofbits","description":"To make fuzzing Rust easy","archived":false,"fork":false,"pushed_at":"2025-05-07T19:22:39.000Z","size":1215,"stargazers_count":177,"open_issues_count":16,"forks_count":26,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-05-07T20:27:33.571Z","etag":null,"topics":["fuzzing","rust","testing"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/test-fuzz","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trailofbits.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-11-04T01:46:24.000Z","updated_at":"2025-05-07T19:22:42.000Z","dependencies_parsed_at":"2024-01-02T00:07:51.356Z","dependency_job_id":"6fd1f028-d990-460a-89ef-43285824cf83","html_url":"https://github.com/trailofbits/test-fuzz","commit_stats":{"total_commits":949,"total_committers":6,"mean_commits":"158.16666666666666","dds":0.0547945205479452,"last_synced_commit":"c13df7aa2eb08286bee02db52b0dd63cd542c179"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Ftest-fuzz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Ftest-fuzz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Ftest-fuzz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Ftest-fuzz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trailofbits","download_url":"https://codeload.github.com/trailofbits/test-fuzz/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270646,"owners_count":22042859,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fuzzing","rust","testing"],"created_at":"2024-11-08T08:17:46.205Z","updated_at":"2025-05-15T04:06:39.134Z","avatar_url":"https://github.com/trailofbits.png","language":"Rust","funding_links":[],"categories":["Dynamic Checkers"],"sub_categories":[],"readme":"# test-fuzz\n\n`test-fuzz` is a Cargo subcommand and a collection of Rust macros to automate certain tasks related to fuzzing with [`afl.rs`], including:\n\n- generating a fuzzing corpus\n- implementing a fuzzing harness\n\n`test-fuzz` accomplishes these (in part) using Rust's testing facilities. For example, to generate a fuzzing corpus, `test-fuzz` records a target's arguments each time it is called during an invocation of `cargo test`. Similarly, `test-fuzz` implements a fuzzing harness as an additional test in a `cargo-test`-generated binary. This tight integration with Rust's testing facilities is what motivates the name **`test`**`-fuzz`.\n\n**Contents**\n\n1. [Installation]\n2. [Overview]\n3. [Components]\n   - [`test_fuzz` macro]\n   - [`test_fuzz_impl` macro]\n   - [`cargo test-fuzz` command]\n   - [Convenience functions and macros]\n4. [`test-fuzz` package features]\n5. [Auto-generated corpus files]\n6. [Environment variables]\n7. [Limitations]\n8. [Tips and tricks]\n9. [Semantic versioning policy]\n10. [License]\n\n## Installation\n\nInstall `cargo-test-fuzz` and [`afl.rs`] with the following command:\n\n```sh\ncargo install cargo-test-fuzz cargo-afl\n```\n\n## Overview\n\nFuzzing with `test-fuzz` is essentially three steps:\\*\n\n1. **Identify a fuzz target**:\n   - Add the following `dependencies` to the target crate's `Cargo.toml` file:\n     ```toml\n     serde = \"*\"\n     test-fuzz = \"*\"\n     ```\n   - Precede the target function with the [`test_fuzz`] macro:\n     ```rust\n     #[test_fuzz::test_fuzz]\n     fn foo(...) {\n         ...\n     }\n     ```\n2. **Generate a corpus** by running `cargo test`:\n   ```\n   cargo test\n   ```\n3. **Fuzz your target** by running [`cargo test-fuzz`]:\n   ```\n   cargo test-fuzz foo\n   ```\n\n\\* An additional, preliminary step may be necessary following a reboot:\n\n```sh\ncargo afl system-config\n```\n\nNote that the above command runs `sudo` internally. Hence, you may be prompted to enter your password.\n\n## Components\n\n### `test_fuzz` macro\n\nPreceding a function with the `test_fuzz` macro indicates that the function is a fuzz target.\n\nThe primary effects of the `test_fuzz` macro are:\n\n- Add instrumentation to the target to serialize its arguments and write them to a corpus file each time the target is called. The instrumentation is guarded by `#[cfg(test)]` so that corpus files are generated only when running tests (however, see [`enable_in_production`] below).\n- Add a test to read and deserialize arguments from standard input and apply the target to them. The test checks an environment variable, set by [`cargo test-fuzz`], so that the test does not block trying to read from standard input during a normal invocation of `cargo test`. The test is enclosed in a module to reduce the likelihood of a name collision. Currently, the name of the module is `target_fuzz`, where `target` is the name of the target (however, see [`rename`] below).\n\n#### Arguments\n\n##### `bounds = \"where_predicates\"`\n\nImpose `where_predicates` (e.g., trait bounds) on the struct used to serialize/deserialize arguments. This may be necessary, e.g., if a target's argument type is an associated type. For an example, see [associated_type.rs] in this repository.\n\n##### `generic_args = \"parameters\"`\n\nUse `parameters` as the target's type parameters when fuzzing. Example:\n\n```rust\n#[test_fuzz(generic_args = \"String\")]\nfn foo\u003cT: Clone + Debug + Serialize\u003e(x: \u0026T) {\n    ...\n}\n```\n\nNote: The target's arguments must be serializable for **every** instantiation of its type parameters. But the target's arguments are required to be deserializable only when the target is instantiated with `parameters`.\n\n##### `impl_generic_args = \"parameters\"`\n\nUse `parameters` as the target's `Self` type parameters when fuzzing. Example:\n\n```rust\n#[test_fuzz_impl]\nimpl\u003cT: Clone + Debug + Serialize\u003e for Foo {\n    #[test_fuzz(impl_generic_args = \"String\")]\n    fn bar(\u0026self, x: \u0026T) {\n        ...\n    }\n}\n```\n\nNote: The target's arguments must be serializable for **every** instantiation of its `Self` type parameters. But the target's arguments are required to be deserializable only when the target's `Self` is instantiated with `parameters`.\n\n##### `convert = \"X, Y\"`\n\nWhen serializing the target's arguments, convert values of type `X` to type `Y` using `Y`'s implementation of `From\u003cX\u003e`, or of type `\u0026X` to type `Y` using `Y`'s implementation of the non-standard trait `test_fuzz::FromRef\u003cX\u003e`. When deserializing, convert those values back to type `X` using `Y`'s implementation of the non-standard trait `test_fuzz::Into\u003cX\u003e`.\n\nThat is, use of `convert = \"X, Y\"` must be accompanied by certain implementations. If `X` implements [`Clone`], then `Y` may implement the following:\n\n```rust\nimpl From\u003cX\u003e for Y {\n    fn from(x: X) -\u003e Self {\n        ...\n    }\n}\n```\n\nIf `X` does not implement [`Clone`], then `Y` must implement the following:\n\n```rust\nimpl test_fuzz::FromRef\u003cX\u003e for Y {\n    fn from_ref(x: \u0026X) -\u003e Self {\n        ...\n    }\n}\n```\n\nAdditionally, `Y` must implement the following (regardless of whether `X` implements [`Clone`]):\n\n```rust\nimpl test_fuzz::Into\u003cX\u003e for Y {\n    fn into(self) -\u003e X {\n        ...\n    }\n}\n```\n\nThe definition of `test_fuzz::Into` is identical to that of [`std::convert::Into`]. The reason for using a non-standard trait is to avoid conflicts that could arise from blanket implementations of standard traits.\n\n##### `enable_in_production`\n\nGenerate corpus files when not running tests, provided the environment variable [`TEST_FUZZ_WRITE`] is set. The default is to generate corpus files only when running tests, regardless of whether [`TEST_FUZZ_WRITE`] is set. When running a target from outside its package directory, set [`TEST_FUZZ_MANIFEST_PATH`] to the path of the package's `Cargo.toml` file.\n\n**WARNING**: Setting `enable_in_production` could introduce a denial-of-service vector. For example, setting this option for a function that is called many times with different arguments could fill up the disk. The check of [`TEST_FUZZ_WRITE`] is meant to provide some defense against this possibility. Nonetheless, consider this option carefully before using it.\n\n##### `execute_with = \"function\"`\n\nRather than call the target directly:\n\n- construct a closure of type `FnOnce() -\u003e R`, where `R` is the target's return type, so that calling the closure calls the target;\n- call `function` with the closure.\n\nCalling the target in this way allows `function` to set up the call's environment. This can be useful, e.g., for fuzzing [Substrate externalities].\n\n##### `no_auto_generate`\n\nDo not try to [auto-generate corpus files] for the target.\n\n##### `only_generic_args`\n\nRecord the target's generic args when running tests, but do not generate corpus files and do not implement a fuzzing harness. This can be useful when the target is a generic function, but it is unclear what type parameters should be used for fuzzing.\n\nThe intended workflow is: enable `only_generic_args`, then run `cargo test` followed by `cargo test-fuzz --display generic-args`. One of the resulting generic args might be usable as `generic_args`'s `parameters`. Similarly, generic args resulting from `cargo test-fuzz --display impl-generic-args` might be usable as `impl_generic_args`'s `parameters`.\n\nNote, however, that just because a target was called with certain parameters during tests, it does not imply the target's arguments are serializable/deserializable when those parameters are used. The results of `--display generic-args`/`--display impl-generic-args` are merely suggestive.\n\n##### `rename = \"name\"`\n\nTreat the target as though its name is `name` when adding a module to the enclosing scope. Expansion of the `test_fuzz` macro adds a module definition to the enclosing scope. By default, the module is named as follows:\n\n- If the target does not appear in an `impl` block, the module is named `target_fuzz__`, where `target` is the name of the target.\n- If the target appears in an `impl` block, the module is named `path_target_fuzz__`, where `path` is the path of the `impl`'s `Self` type converted to snake case and joined with `_`.\n\nHowever, use of this option causes the module to instead be named `name_fuzz__`. Example:\n\n```rust\n#[test_fuzz(rename = \"bar\")]\nfn foo() {}\n\n// Without the use of `rename`, a name collision and compile error would result.\nmod foo_fuzz__ {}\n```\n\n#### Serde field attributes on function arguments\n\nThe `test_fuzz` macro allows [Serde field attributes] to be applied to function arguments. This provides another tool for dealing with difficult types.\n\nThe following is an example. Traits `serde::Serialize` and `serde::Deserialize` cannot be derived for `Context` because it contains a `Mutex`. However, `Context` implements `Default`. So applying `#[serde(skip)]` to the `Context` argument causes it to be skipped when serializing, and to take its default value when deserializing.\n\n```rust\nuse std::sync::Mutex;\n\n// Traits `serde::Serialize` and `serde::Deserialize` cannot be derived for `Context` because it\n// contains a `Mutex`.\n#[derive(Default)]\nstruct Context {\n    lock: Mutex\u003c()\u003e,\n}\n\nimpl Clone for Context {\n    fn clone(\u0026self) -\u003e Self {\n        Self {\n            lock: Mutex::new(()),\n        }\n    }\n}\n\n#[test_fuzz::test_fuzz]\nfn target(#[serde(skip)] context: Context, x: i32) {\n    assert!(x \u003e= 0);\n}\n```\n\nNote that when Serde field attributes are applied to an argument, the `test_fuzz` macro performs no other [conversions] on the argument.\n\n### `test_fuzz_impl` macro\n\nWhenever the [`test_fuzz`] macro is used in an `impl` block,\nthe `impl` must be preceded with the `test_fuzz_impl` macro. Example:\n\n```rust\n#[test_fuzz_impl]\nimpl Foo {\n    #[test_fuzz]\n    fn bar(\u0026self, x: \u0026str) {\n        ...\n    }\n}\n```\n\nThe reason for this requirement is as follows. Expansion of the [`test_fuzz`] macro adds a module definition to the enclosing scope. However, a module definition cannot appear inside an `impl` block. Preceding the `impl` with the `test_fuzz_impl` macro causes the module to be added outside the `impl` block.\n\nIf you see an error like the following, it likely means a use of the `test_fuzz_impl` macro is missing:\n\n```\nerror: module is not supported in `trait`s or `impl`s\n```\n\n`test_fuzz_impl` currently has no options.\n\n### `cargo test-fuzz` command\n\nThe `cargo test-fuzz` command is used to interact with fuzz targets, and to manipulate their corpora, crashes, hangs, and work queues. Example invocations include:\n\n1. List fuzz targets\n   ```\n   cargo test-fuzz --list\n   ```\n2. Display target `foo`'s corpus\n   ```\n   cargo test-fuzz foo --display corpus\n   ```\n3. Fuzz target `foo`\n   ```\n   cargo test-fuzz foo\n   ```\n4. Replay crashes found for target `foo`\n   ```\n   cargo test-fuzz foo --replay crashes\n   ```\n\n#### Usage\n\n```\nUsage: cargo test-fuzz [OPTIONS] [TARGETNAME] [-- \u003cARGS\u003e...]\n\nArguments:\n  [TARGETNAME]  String that fuzz target's name must contain\n  [ARGS]...     Arguments for the fuzzer\n\nOptions:\n      --backtrace                 Display backtraces\n      --consolidate               Move one target's crashes, hangs, and work queue to its corpus; to\n                                  consolidate all targets, use --consolidate-all\n      --cpus \u003cN\u003e                  Fuzz using at most \u003cN\u003e cpus; default is all but one\n      --display \u003cOBJECT\u003e          Display corpus, crashes, generic args, `impl` generic args, hangs,\n                                  or work queue. By default, an uninstrumented fuzz target is used.\n                                  To display with instrumentation, append `-instrumented` to\n                                  \u003cOBJECT\u003e, e.g., --display corpus-instrumented.\n      --exact                     Target name is an exact name rather than a substring\n      --exit-code                 Exit with 0 if the time limit was reached, 1 for other\n                                  programmatic aborts, and 2 if an error occurred; implies --no-ui,\n                                  does not imply --run-until-crash or --max-total-time \u003cSECONDS\u003e\n      --features \u003cFEATURES\u003e       Space or comma separated list of features to activate\n      --list                      List fuzz targets\n      --manifest-path \u003cPATH\u003e      Path to Cargo.toml\n      --max-total-time \u003cSECONDS\u003e  Fuzz at most \u003cSECONDS\u003e of time (equivalent to -- -V \u003cSECONDS\u003e)\n      --no-default-features       Do not activate the `default` feature\n      --no-run                    Compile, but don't fuzz\n      --no-ui                     Disable user interface\n  -p, --package \u003cPACKAGE\u003e         Package containing fuzz target\n      --persistent                Enable persistent mode fuzzing\n      --pretty                    Pretty-print debug output when displaying/replaying\n      --release                   Build in release mode\n      --replay \u003cOBJECT\u003e           Replay corpus, crashes, hangs, or work queue. By default, an\n                                  uninstrumented fuzz target is used. To replay with instrumentation\n                                  append `-instrumented` to \u003cOBJECT\u003e, e.g., --replay\n                                  corpus-instrumented.\n      --reset                     Clear fuzzing data for one target, but leave corpus intact; to\n                                  reset all targets, use --reset-all\n      --resume                    Resume target's last fuzzing session\n      --run-until-crash           Stop fuzzing once a crash is found\n      --slice \u003cSECONDS\u003e           If there are not sufficiently many cpus to fuzz all targets\n                                  simultaneously, fuzz them in intervals of \u003cSECONDS\u003e [default:\n                                  1200]\n      --test \u003cNAME\u003e               Integration test containing fuzz target\n      --timeout \u003cTIMEOUT\u003e         Number of seconds to consider a hang when fuzzing or replaying\n                                  (equivalent to -- -t \u003cTIMEOUT * 1000\u003e when fuzzing)\n      --verbose                   Show build output when displaying/replaying\n  -h, --help                      Print help\n  -V, --version                   Print version\n\nTry `cargo afl fuzz --help` to see additional fuzzer options.\n```\n\nWhen using the `--display` option, any output written to stderr by the target is shown. This includes output from `eprintln!` statements, as well as from debugging macros like `dbg!`. This can be useful for understanding what's happening in your code when processing specific inputs.\n\nThe `--display` and `--replay` options can be passed together, allowing you to both view and replay corpus entries in a single command, for example:\n\n```\ncargo test-fuzz foo --display corpus --replay corpus\n```\n\n### Convenience functions and macros\n\n**Warning:** These utilties are excluded from semantic versioning and may be removed in future versions of `test-fuzz`.\n\n#### `dont_care!`\n\nThe `dont_care!` macro can be used to implement `serde::Serialize`/`serde::Deserialize` for types that are easy to construct and whose values you do not care to record. Intuitively, `dont_care!($ty, $expr)` says:\n\n- Skip values of type `$ty` when serializing.\n- Initialize values of type `$ty` with `$expr` when deserializing.\n\nMore specifically, `dont_care!($ty, $expr)` expands to the following:\n\n```rust\nimpl serde::Serialize for $ty {\n    fn serialize\u003cS\u003e(\u0026self, serializer: S) -\u003e std::result::Result\u003cS::Ok, S::Error\u003e\n    where\n        S: serde::Serializer,\n    {\n        ().serialize(serializer)\n    }\n}\n\nimpl\u003c'de\u003e serde::Deserialize\u003c'de\u003e for $ty {\n    fn deserialize\u003cD\u003e(deserializer: D) -\u003e std::result::Result\u003cSelf, D::Error\u003e\n    where\n        D: serde::Deserializer\u003c'de\u003e,\n    {\n        \u003c()\u003e::deserialize(deserializer).map(|_| $expr)\n    }\n}\n```\n\nIf `$ty` is a unit struct, then `$expr` can be omitted. That is, `dont_care!($ty)` is equivalent to `dont_care!($ty, $ty)`.\n\n#### `leak!`\n\nThe `leak!` macro can help to serialize target arguments that are references and whose types implement the [`ToOwned`] trait. It is meant to be used with the [`convert`] option.\n\nSpecifically, an invocation of the following form declares a type `LeakedX`, and implements the `From` and `test_fuzz::Into` traits for it:\n\n```rust\nleak!(X, LeakedX);\n```\n\nOne can then use `LeakedX` with the `convert` option as follows:\n\n```rust\n#[test_fuzz::test_fuzz(convert = \"\u0026X, LeakedX\")\n```\n\nAn example where `X` is [`Path`] appears in [conversion.rs] in this repository.\n\nMore generally, an invocation of the form `leak!($ty, $ident)` expands to the following:\n\n```rust\n#[derive(Clone, std::fmt::Debug, serde::Deserialize, serde::Serialize)]\nstruct $ident(\u003c$ty as ToOwned\u003e::Owned);\n\nimpl From\u003c\u0026$ty\u003e for $ident {\n    fn from(ty: \u0026$ty) -\u003e Self {\n        Self(ty.to_owned())\n    }\n}\n\nimpl test_fuzz::Into\u003c\u0026$ty\u003e for $ident {\n    fn into(self) -\u003e \u0026'static $ty {\n        Box::leak(Box::new(self.0))\n    }\n}\n```\n\n#### `serialize_ref` / `deserialize_ref`\n\n`serialize_ref` and `deserialize_ref` function similar to `leak!`, but they are meant to be used wth Serde's [`serialize_with`] and [`deserialize_with`] field attributes (respectively).\n\n```rust\nfn serialize_ref\u003cS, T\u003e(x: \u0026\u0026T, serializer: S) -\u003e Result\u003cS::Ok, S::Error\u003e\nwhere\n    S: serde::Serializer,\n    T: serde::Serialize,\n{\n    \u003cT as serde::Serialize\u003e::serialize(*x, serializer)\n}\n\nfn deserialize_ref\u003c'de, D, T\u003e(deserializer: D) -\u003e Result\u003c\u0026'static T, D::Error\u003e\nwhere\n    D: serde::Deserializer\u003c'de\u003e,\n    T: serde::de::DeserializeOwned + std::fmt::Debug,\n{\n    let x = \u003cT as serde::de::Deserialize\u003e::deserialize(deserializer)?;\n    Ok(Box::leak(Box::new(x)))\n}\n```\n\n#### `serialize_ref_mut` / `deserialize_ref_mut`\n\n`serialize_ref_mut` and `deserialize_ref_mut` are similar to `serialize_ref` and `deserialize_ref` (respectively), expect they operate on mutable references instead of immutable ones.\n\n## `test-fuzz` package features\n\nThe features in this section apply to the `test-fuzz` package as a whole. Enable them in `test-fuzz`'s dependency specification as described in the [The Cargo Book]. For example, to enable the `cast_checks` feature, use:\n\n```toml\ntest-fuzz = { version = \"*\", features = [\"cast_checks\"] }\n```\n\nThe `test-fuzz` package currently supports the following features:\n\n### `cast_checks`\n\nUse [`cast_checks`] to automatically check target functions for invalid casts.\n\nNote that this feature enables `cast_checks` only for functions annotated with the [`test_fuzz` macro], not for the functions they call.\n\n### Serde formats\n\n`test-fuzz` can serialize target arguments in multiple Serde formats. The following are the features used to select a format.\n\n- `serde_bincode` - [Bincode] (default)\n\n- `serde_postcard` - [Postcard]\n\n## Auto-generated corpus files\n\n`cargo-test-fuzz` can auto-generate values for types that implement certain traits. If all of a target's argument types implement such traits, `cargo-test-fuzz` can auto-generate corpus files for the target.\n\nThe traits that `cargo-test-fuzz` currently supports and the values generated for them are as follows:\n\n| Trait(s)                          | Value(s)                                                           |\n| --------------------------------- | ------------------------------------------------------------------ |\n| `Bounded`                         | `T::min_value()`, `T::max_value()`                                 |\n| `Bounded + Add + One`             | `T::min_value() + T::one()`                                        |\n| `Bounded + Add + Div + Two`       | `T::min_value() / T::two() + T::max_value() / T::two()`            |\n| `Bounded + Add + Div + Two + One` | `T::min_value() / T::two() + T::max_value() / T::two() + T::one()` |\n| `Bounded + Sub + One`             | `T::max_value() - T::one()`                                        |\n| `Default`                         | `T::default()`                                                     |\n\n**Key**\n\n- `Add` - [`core::ops::Add`]\n- `Bounded` - [`num_traits::bounds::Bounded`]\n- `Default` - [`std::default::Default`]\n- `Div` - [`core::ops::Div`]\n- `One` - [`num_traits::One`]\n- `Sub` - [`core::ops::Sub`]\n- `Two` - `test_fuzz::runtime::traits::Two` (essentially `Add + One`)\n\n## Environment variables\n\n### `TEST_FUZZ_LOG`\n\nDuring macro expansion:\n\n- If `TEST_FUZZ_LOG` is set to `1`, write all instrumented fuzz targets and module definitions to standard output.\n- If `TEST_FUZZ_LOG` is set to a crate name, write that crate's instrumented fuzz targets and module definitions to standard output.\n\nThis can be useful for debugging.\n\n### `TEST_FUZZ_MANIFEST_PATH`\n\nWhen running a target from outside its package directory, find the package's `Cargo.toml` file at this location. One may need to set this environment variable when [`enable_in_production`] is used.\n\n### `TEST_FUZZ_WRITE`\n\nGenerate corpus files when not running tests for those targets for which [`enable_in_production`] is set.\n\n## Limitations\n\n### Clonable arguments\n\nA target's arguments must implement the [`Clone`] trait. The reason for this requirement is that the arguments are needed in two places: in a `test-fuzz`-internal function that writes corpus files, and in the body of the target function. To resolve this conflict, the arguments are cloned before being passed to the former.\n\n### Serializable / deserializable arguments\n\nIn general, a target's arguments must implement the [`serde::Serialize`] and [`serde::Deserialize`] traits, e.g., by [deriving them]. We say \"in general\" because `test-fuzz` knows how to handle certain special cases that wouldn't normally be serializable/deserializable. For example, an argument of type `\u0026str` is converted to `String` when serializing, and back to a `\u0026str` when deserializing. See also [`generic_args`] and [`impl_generic_args`] above.\n\n### Global variables\n\nThe fuzzing harnesses that `test-fuzz` implements do not initialize global variables. While [`execute_with`] provides some remedy, it is not a complete solution. In general, fuzzing a function that relies on global variables requires ad-hoc methods.\n\n### [`convert`] and [`generic_args`] / [`impl_generic_args`]\n\nThese options are incompatible in the following sense. If a fuzz target's argument type is a type parameter, [`convert`] will try to match the type parameter, not the type to which the parameter is set. Supporting the latter would seem to require simulating type substitution as the compiler would perform it. However, this is not currently implemented.\n\n## Tips and tricks\n\n- `#[cfg(test)]` [is not enabled] for integration tests. If your target is tested only by integration tests, then consider using [`enable_in_production`] and [`TEST_FUZZ_WRITE`] to generate a corpus. (Note the warning accompanying [`enable_in_production`], however.)\n\n- If you know the package in which your target resides, passing `-p \u003cpackage\u003e` to `cargo test`/[`cargo test-fuzz`] can significantly reduce build times. Similarly, if you know your target is called from only one integration test, passing `--test \u003cname\u003e` can reduce build times.\n\n- Rust [won't allow you to] implement `serde::Serialize` for other repositories' types. But you may be able to [patch] other repositories to make their types serializable. Also, [`cargo-clone`] can be useful for grabbing dependencies' repositories.\n\n- [Serde attributes] can be helpful in implementing `serde::Serialize`/`serde::Deserialize` for difficult types.\n\n## Semantic versioning policy\n\nWe reserve the right to change the format of corpora, crashes, hangs, and work queues, and to consider such changes non-breaking.\n\n## License\n\n`test-fuzz` is licensed and distributed under the AGPLv3 license with the [Macros and Inline Functions Exception]. In plain language, using the [`test_fuzz` macro], the [`test_fuzz_impl` macro], or `test-fuzz`'s [convenience functions and macros] in your software does not require it to be covered by the AGPLv3 license.\n\n[Auto-generated corpus files]: #auto-generated-corpus-files\n[Bincode]: https://github.com/bincode-org/bincode\n[Components]: #components\n[Convenience functions and macros]: #convenience-functions-and-macros\n[Environment variables]: #environment-variables\n[Installation]: #installation\n[License]: #license\n[Limitations]: #limitations\n[Macros and Inline Functions Exception]: https://spdx.org/licenses/mif-exception.html\n[Overview]: #overview\n[Postcard]: https://github.com/jamesmunns/postcard\n[Serde attributes]: https://serde.rs/attributes.html\n[Serde field attributes]: https://serde.rs/field-attrs.html\n[Substrate externalities]: https://substrate.dev/docs/en/knowledgebase/runtime/tests#mock-runtime-storage\n[The Cargo Book]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#choosing-features\n[Tips and tricks]: #tips-and-tricks\n[`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html\n[`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html\n[`TEST_FUZZ_MANIFEST_PATH`]: #test_fuzz_manifest_path\n[`TEST_FUZZ_WRITE`]: #test_fuzz_write\n[`ToOwned`]: https://doc.rust-lang.org/std/borrow/trait.ToOwned.html\n[`afl.rs`]: https://github.com/rust-fuzz/afl.rs\n[`cargo test-fuzz` command]: #cargo-test-fuzz-command\n[`cargo test-fuzz`]: #cargo-test-fuzz-command\n[`cargo-clone`]: https://github.com/JanLikar/cargo-clone\n[`cast_checks`]: https://github.com/trailofbits/cast_checks\n[`convert`]: #convert--x-y\n[`core::ops::Add`]: https://doc.rust-lang.org/beta/core/ops/trait.Add.html\n[`core::ops::Div`]: https://doc.rust-lang.org/beta/core/ops/trait.Div.html\n[`core::ops::Sub`]: https://doc.rust-lang.org/beta/core/ops/trait.Sub.html\n[`deserialize_with`]: https://serde.rs/field-attrs.html#deserialize_with\n[`enable_in_production`]: #enable_in_production\n[`execute_with`]: #execute_with--function\n[`generic_args`]: #generic_args--parameters\n[`impl_generic_args`]: #impl_generic_args--parameters\n[`num_traits::One`]: https://docs.rs/num-traits/0.2.14/num_traits/identities/trait.One.html\n[`num_traits::bounds::Bounded`]: https://docs.rs/num-traits/0.2.14/num_traits/bounds/trait.Bounded.html\n[`proc_macro_span`]: https://github.com/rust-lang/rust/issues/54725\n[`rename`]: #rename--name\n[`serde::Deserialize`]: https://docs.serde.rs/serde/trait.Deserialize.html\n[`serde::Serialize`]: https://docs.serde.rs/serde/trait.Serialize.html\n[`serialize_with`]: https://serde.rs/field-attrs.html#serialize_with\n[`std::convert::Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html\n[`std::default::Default`]: https://doc.rust-lang.org/std/default/trait.Default.html\n[`test-fuzz` package features]: #test-fuzz-package-features\n[`test_fuzz_impl` macro]: #test_fuzz_impl-macro\n[`test_fuzz` macro]: #test_fuzz-macro\n[`test_fuzz`]: #test_fuzz-macro\n[associated_type.rs]: https://github.com/trailofbits/test-fuzz/blob/master/examples/tests/associated_type.rs#L26\n[auto-generate corpus files]: #auto-generated-corpus-files\n[conversion.rs]: https://github.com/trailofbits/test-fuzz/blob/master/examples/tests/conversion.rs#L5\n[conversions]: #serializable--deserializable-arguments\n[deriving them]: https://serde.rs/derive.html\n[is not enabled]: https://github.com/rust-lang/rust/issues/45599#issuecomment-460488107\n[patch]: https://doc.rust-lang.org/edition-guide/rust-2018/cargo-and-crates-io/replacing-dependencies-with-patch.html\n[won't allow you to]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Ftest-fuzz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrailofbits%2Ftest-fuzz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Ftest-fuzz/lists"}