From 1a8ad93118d0e333794d2e12db33d704510514da Mon Sep 17 00:00:00 2001 From: Christoph Gehrke Date: Thu, 27 Aug 2026 16:13:17 +0200 Subject: [PATCH 1/7] feat: add ASan for honggfuzz and improve for afl Fix some clippy lints on the way. Add semver-checks to CI. --- .github/workflows/ci.yml | 2 + Cargo.lock | 616 +++++++++++--------------------- Cargo.toml | 2 + examples/asan/src/main.rs | 2 +- src/bin/cargo-ziggy/build.rs | 72 ++-- src/bin/cargo-ziggy/coverage.rs | 6 +- src/bin/cargo-ziggy/fuzz.rs | 29 +- src/bin/cargo-ziggy/main.rs | 10 +- src/bin/cargo-ziggy/minimize.rs | 6 +- src/bin/cargo-ziggy/plot.rs | 2 +- src/bin/cargo-ziggy/run.rs | 1 - src/bin/cargo-ziggy/triage.rs | 10 +- tests/asan_fuzz.rs | 223 +++++++++++- 13 files changed, 499 insertions(+), 482 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95f3be4..cf7bc65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,8 @@ jobs: run: cargo fmt --check - name: Clippy run: cargo clippy --workspace --all-targets -- -D warnings + - name: Check semver + uses: obi1kenobi/cargo-semver-checks-action@v2 build_and_test: name: Rust project - latest runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 201d2b1..2c9f830 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,9 +66,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "arbitrary" @@ -96,30 +96,30 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.11.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "camino" -version = "1.2.2" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" dependencies = [ "serde_core", ] [[package]] name = "cargo-platform" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87a0c0e6148f11f01f32650a2ea02d532b2ad4e81d8bd41e6e565b5adc5e6082" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" dependencies = [ "serde", "serde_core", @@ -145,11 +145,22 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core", +] + [[package]] name = "clap" -version = "4.6.0" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ "clap_builder", "clap_derive", @@ -157,9 +168,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.0" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ "anstream", "anstyle", @@ -169,14 +180,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] @@ -193,9 +204,9 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "console" -version = "0.16.3" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" +checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" dependencies = [ "encode_unicode", "libc", @@ -203,11 +214,20 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -215,18 +235,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "derive_arbitrary" @@ -236,25 +256,25 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "either" -version = "1.15.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" [[package]] name = "encode_unicode" @@ -262,12 +282,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - [[package]] name = "errno" version = "0.3.14" @@ -280,15 +294,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "form_urlencoded" @@ -300,50 +308,46 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.3.4" +name = "futures-core" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi 5.3.0", - "wasip2", -] +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] -name = "getrandom" -version = "0.4.2" +name = "futures-task" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" -dependencies = [ - "cfg-if", - "libc", - "r-efi 6.0.0", - "wasip2", - "wasip3", -] +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] -name = "glob" -version = "0.3.3" +name = "futures-util" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] [[package]] -name = "hashbrown" -version = "0.15.5" +name = "getrandom" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ - "foldhash", + "cfg-if", + "libc", + "r-efi", + "rand_core", ] [[package]] -name = "hashbrown" -version = "0.17.0" +name = "glob" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] name = "heck" @@ -362,9 +366,9 @@ dependencies = [ [[package]] name = "honggfuzz" -version = "0.5.60" +version = "0.5.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6510a410acedd7a7683b3a45dafdc5ccf3c72d6addaa373497005964fc4e23" +checksum = "378465388ac845720910efa26a6f46f93d744debe65710b82f0e5310058c6703" dependencies = [ "arbitrary", "lazy_static", @@ -375,9 +379,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" dependencies = [ "displaydoc", "potential_utf", @@ -389,9 +393,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" dependencies = [ "displaydoc", "litemap", @@ -402,9 +406,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -416,16 +420,17 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" [[package]] name = "icu_properties" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" dependencies = [ + "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", @@ -436,15 +441,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" [[package]] name = "icu_provider" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" dependencies = [ "displaydoc", "icu_locale_core", @@ -455,12 +460,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "idna" version = "1.1.0" @@ -474,31 +473,19 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", ] -[[package]] -name = "indexmap" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" -dependencies = [ - "equivalent", - "hashbrown 0.17.0", - "serde", - "serde_core", -] - [[package]] name = "indicatif" -version = "0.18.4" +version = "0.18.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" +checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" dependencies = [ "console", "portable-atomic", @@ -521,11 +508,12 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.95" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] @@ -535,17 +523,11 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libc" -version = "0.2.184" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "linux-raw-sys" @@ -555,27 +537,21 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" - -[[package]] -name = "log" -version = "0.4.29" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memmap2" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" dependencies = [ "libc", ] @@ -599,63 +575,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] -name = "portable-atomic" -version = "1.13.1" +name = "pin-project-lite" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] -name = "potential_utf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" -dependencies = [ - "zerovec", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" +name = "portable-atomic" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] -name = "prettyplease" -version = "0.2.37" +name = "potential_utf" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" dependencies = [ - "proc-macro2", - "syn", + "zerovec", ] [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.45" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - [[package]] name = "r-efi" version = "6.0.0" @@ -664,38 +621,26 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ec095654a25171c2124e9e3393a930bddbffdc939556c914957a4c3e0a87166" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "ppv-lite86", + "chacha20", + "getrandom", "rand_core", ] [[package]] name = "rand_core" -version = "0.9.5" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -735,9 +680,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "semver" @@ -751,9 +696,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -761,29 +706,29 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -812,11 +757,17 @@ dependencies = [ "libc", ] +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "stable_deref_trait" @@ -841,9 +792,20 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.117" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" dependencies = [ "proc-macro2", "quote", @@ -858,14 +820,14 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "target-triple" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "591ef38edfb78ca4771ee32cf494cb8771944bee237a9b91fc9c1424ac4b777b" +checksum = "c3a6bfce3d99adfa72d24750a61f782f3036a81e7f86d8841ee1326deaebd171" [[package]] name = "tempfile" @@ -874,7 +836,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom", "once_cell", "rustix", "windows-sys", @@ -882,29 +844,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "thread_local" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" dependencies = [ "cfg-if", ] @@ -917,9 +879,9 @@ checksum = "3e32d019b4f7c100bcd5494e40a27119d45b71fba2b07a4684153129279a4647" [[package]] name = "tinystr" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" dependencies = [ "displaydoc", "zerovec", @@ -927,9 +889,9 @@ dependencies = [ [[package]] name = "twox-hash" -version = "2.1.2" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" +checksum = "5283634e518fe9e82c7b20520bb4bc209009fd16c82077c802f8111ecbb0117a" dependencies = [ "rand", ] @@ -946,12 +908,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "unit-prefix" version = "0.5.2" @@ -1015,29 +971,11 @@ dependencies = [ "libc", ] -[[package]] -name = "wasip2" -version = "1.0.2+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasm-bindgen" -version = "0.2.118" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" dependencies = [ "cfg-if", "once_cell", @@ -1048,9 +986,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.118" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1058,60 +996,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.118" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.118" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - [[package]] name = "web-time" version = "1.1.0" @@ -1137,99 +1041,11 @@ dependencies = [ "windows-link", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "writeable" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" [[package]] name = "xdg" @@ -1239,9 +1055,9 @@ checksum = "2fb433233f2df9344722454bc7e96465c9d03bff9d77c248f9e7523fe79585b5" [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -1256,35 +1072,15 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zerofrom" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] @@ -1297,15 +1093,15 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] [[package]] name = "zerotrie" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" dependencies = [ "displaydoc", "yoke", @@ -1314,9 +1110,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" dependencies = [ "yoke", "zerofrom", @@ -1325,13 +1121,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] @@ -1361,6 +1157,6 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index 654bfaa..ce59d1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,10 +37,12 @@ cli = [ "tempfile", "thread_local", "time-humanize", + "tokio", "twox-hash", "wait-timeout", ] coverage = [] +tokio = [] [dependencies] afl = { version = "0.18.2", default-features = false, optional = true } diff --git a/examples/asan/src/main.rs b/examples/asan/src/main.rs index 88b41e6..301f4aa 100644 --- a/examples/asan/src/main.rs +++ b/examples/asan/src/main.rs @@ -5,7 +5,7 @@ fn main() { } if data[0] == b'f' && data[1] == b'u' && data[2] == b'z' && data[3] == b'z' { let xs = [0, 1, 2, 3]; - let _y = unsafe { *xs.as_ptr().add(4) }; + let _y = std::hint::black_box(unsafe { *xs.as_ptr().add(4) }); } }); } diff --git a/src/bin/cargo-ziggy/build.rs b/src/bin/cargo-ziggy/build.rs index d3cf544..288121f 100644 --- a/src/bin/cargo-ziggy/build.rs +++ b/src/bin/cargo-ziggy/build.rs @@ -3,23 +3,6 @@ use anyhow::{Context as _, Result, bail}; use console::style; use std::{env, process}; -fn is_using_nightly_toolchain() -> bool { - let out = process::Command::new("rustc") - .arg("--version") - .output() - .expect("failed to launch rustc"); - - String::from_utf8_lossy(&out.stdout).contains("nightly") -} - -fn afl_plugins_installed(common: &Common) -> bool { - common - .cargo() - .args(["afl", "--version"]) - .output() - .is_ok_and(|out| String::from_utf8_lossy(&out.stdout).contains("with plugins")) -} - impl Build { /// Build the fuzzers pub fn build(&self, common: &Common) -> Result<(), anyhow::Error> { @@ -62,9 +45,7 @@ impl Build { &cx.bin_target, ]; - // Add the --release argument if self.release is true if self.release { - assert!(!self.asan, "cannot use --release for ASAN builds"); afl_args.push("--release"); } @@ -98,21 +79,15 @@ impl Build { // If ASAN is enabled, build both a sanitized binary and a non-sanitized binary. if self.asan { eprintln!(" {} afl (ASan)", style("Building").red().bold()); - if env::var("AFL_OPT_LEVEL").is_ok_and(|opt_level| opt_level != "0") { - eprintln!(" Warning: ignoring AFL_OPT_LEVEL and setting it to 0"); - } afl_args.push(&asan_target_str); afl_args.extend(["-Z", "build-std"]); rust_flags.push_str(" -Zsanitizer=address "); - rust_flags.push_str("-Copt-level=0"); rust_doc_flags.push_str(" -Zsanitizer=address "); let run = common .cargo() .args(afl_args) .env("AFL_QUIET", "1") - // need to specify for afl.rs so that we build with -Copt-level=0 - .env("AFL_OPT_LEVEL", "0") .env("AFLRS_REQUIRE_PLUGINS", "1") .env("AFL_LLVM_CMPLOG", "1") // for afl.rs feature "plugins" .env("RUSTFLAGS", rust_flags) @@ -130,10 +105,6 @@ impl Build { } if !self.no_honggfuzz { - assert!( - !self.asan, - "Cannot build honggfuzz with ASAN for the moment. use --no-honggfuzz" - ); eprintln!(" {} honggfuzz", style("Building").red().bold()); // Second fuzzer we build: Honggfuzz @@ -141,8 +112,7 @@ impl Build { .cargo() .args(["hfuzz", "build", "--bin", &cx.bin_target]) .env("CARGO_TARGET_DIR", cx.target_dir.join("honggfuzz")) - .env("HFUZZ_BUILD_ARGS", "--features=ziggy/honggfuzz") - .env("RUSTFLAGS", env::var("RUSTFLAGS").unwrap_or_default()) + .envs(honggfuzz_envs(self.asan)) .stdout(process::Stdio::piped()) .spawn()? .wait() @@ -158,11 +128,41 @@ impl Build { eprintln!(" {} honggfuzz", style("Finished").cyan().bold()); } - assert!( - std::env::var("AFL_LLVM_CMPGLOG").is_err(), - "Even the mighty may fall, especially on 77b2c27a59bb858045c4db442989ce8f20c8ee11" - ); - Ok(()) } } + +fn is_using_nightly_toolchain() -> bool { + Common::rustc() + .arg("--version") + .output() + .is_ok_and(|out| String::from_utf8_lossy(&out.stdout).contains("nightly")) +} + +fn afl_plugins_installed(common: &Common) -> bool { + common + .cargo() + .args(["afl", "--version"]) + .output() + .is_ok_and(|out| String::from_utf8_lossy(&out.stdout).contains("with plugins")) +} + +pub fn honggfuzz_envs(use_asan: bool) -> impl Iterator { + let mut rust_flags = String::new(); + let mut hfuzz_build_args = "--features=ziggy/honggfuzz ".to_owned(); + + if use_asan { + hfuzz_build_args.push_str("-Zbuild-std "); + rust_flags.push_str("-Zsanitizer=address "); + } + let mut rust_doc_flags = rust_flags.clone(); + rust_flags.extend(env::var("RUSTFLAGS")); + rust_doc_flags.extend(env::var("RUSTDOCFLAGS")); + + [ + ("RUSTFLAGS", rust_flags), + ("RUSTDOCFLAGS", rust_doc_flags), + ("HFUZZ_BUILD_ARGS", hfuzz_build_args), + ] + .into_iter() +} diff --git a/src/bin/cargo-ziggy/coverage.rs b/src/bin/cargo-ziggy/coverage.rs index 79bca1f..e3cdd64 100644 --- a/src/bin/cargo-ziggy/coverage.rs +++ b/src/bin/cargo-ziggy/coverage.rs @@ -18,7 +18,7 @@ impl Cover { let cx = Context::new(common, self.target.clone())?; let base_dir = cx.target_dir.join("coverage/debug"); - let coverage_target_dir = base_dir.join(format!("deps/coverage-{}", &cx.bin_target)); + let coverage_target_dir = base_dir.join(format!("deps/coverage-{}", cx.bin_target)); let cfg = Cfg::new( base_dir.join(&cx.bin_target), coverage_target_dir.join("cov-%p-%m.profraw"), @@ -32,7 +32,7 @@ impl Cover { let mut cov_dir_exists = coverage_target_dir.is_dir(); if !self.keep && cov_dir_exists { fs::remove_dir_all(&coverage_target_dir) - .with_context(|| format!("⚠️ couldn't remove {}", &coverage_target_dir))?; + .with_context(|| format!("⚠️ couldn't remove {coverage_target_dir}"))?; cov_dir_exists = false; } if !cov_dir_exists { @@ -80,7 +80,7 @@ impl Cover { eprintln!(" Generating raw profiles"); let pb = progress_bar(coverage_corpus.len() as u64); - let log_dir = self.ziggy_output.join(format!("{}/logs", &cx.bin_target)); + let log_dir = self.ziggy_output.join(format!("{}/logs", cx.bin_target)); fs::create_dir_all(&log_dir).context("output dir for logs")?; let log_file = std::sync::Mutex::new( std::fs::File::create(log_dir.join("coverage.log")).context("logfile")?, diff --git a/src/bin/cargo-ziggy/fuzz.rs b/src/bin/cargo-ziggy/fuzz.rs index bd62959..459cba7 100644 --- a/src/bin/cargo-ziggy/fuzz.rs +++ b/src/bin/cargo-ziggy/fuzz.rs @@ -147,7 +147,7 @@ impl Fuzz { // We create an initial corpus file, so that AFL++ starts up properly if corpus is empty let is_empty = fs::read_dir(&paths.corpus)?.next().is_none(); // check if corpus has some seeds if is_empty { - let mut initial_corpus = File::create(format!("{}/init", &paths.corpus))?; + let mut initial_corpus = File::create(format!("{}/init", paths.corpus))?; writeln!(&mut initial_corpus, "00000000")?; drop(initial_corpus); } @@ -296,7 +296,7 @@ impl Fuzz { if !afl_output_ok && let Ok(afl_log) = - fs::read_to_string(format!("{}/logs/afl.log", &paths.output_target)) + fs::read_to_string(format!("{}/logs/afl.log", paths.output_target)) { if afl_log.contains("ready to roll") { afl_output_ok = true; @@ -487,12 +487,12 @@ impl Fuzz { }; // We only sync to the shared corpus if Honggfuzz is also running let use_shared_corpus = match (self.no_honggfuzz, job_num) { - (false, 0) => format!("-F{}", &paths.corpus), + (false, 0) => format!("-F{}", paths.corpus), _ => String::new(), }; let use_initial_corpus_dir = match (&self.initial_corpus, job_num) { (Some(initial_corpus), 0) => { - format!("-F{}", &initial_corpus.display().to_string()) + format!("-F{}", initial_corpus.display()) } _ => String::new(), }; @@ -528,7 +528,7 @@ impl Fuzz { None => String::new(), }; let dictionary_option = match &self.dictionary { - Some(d) => format!("-x{}", &d.display().to_string()), + Some(d) => format!("-x{}", d.display()), None => String::new(), }; let mutation_option = match job_num / 5 { @@ -553,21 +553,18 @@ impl Fuzz { _ => "_DUMMY_VAR", }; let target_path = self.binary.clone().unwrap_or_else(|| { - if self.release { - cx.target_dir() - .join(format!("afl/release/{}", cx.bin_target())) - .into_std_path_buf() - } else if self.asan && job_num == 0 { + let profile = if self.release { "release" } else { "debug" }; + if self.asan && job_num == 0 { cx.target_dir() .join(format!( - "afl/{}/debug/{}", + "afl/{}/{profile}/{}", target_triple::TARGET, cx.bin_target() )) .into_std_path_buf() } else { cx.target_dir() - .join(format!("afl/debug/{}", cx.bin_target())) + .join(format!("afl/{profile}/{}", cx.bin_target())) .into_std_path_buf() } }); @@ -669,12 +666,12 @@ impl Fuzz { &format!( "{} hfuzz run {}", cx.common().cargo_path.display(), - &cx.bin_target() + cx.bin_target() ), "/dev/null", ]) - .env("HFUZZ_BUILD_ARGS", "--features=ziggy/honggfuzz") .env("CARGO_TARGET_DIR", cx.target_dir().join("honggfuzz")) + .envs(crate::build::honggfuzz_envs(self.asan)) .env( "HFUZZ_WORKSPACE", format!("{}/honggfuzz", paths.output_target), @@ -723,7 +720,7 @@ impl Fuzz { term.write_line(&format!( "\n {}", - &style("Running minimization").magenta().bold() + style("Running minimization").magenta().bold() ))?; let input_corpus = &paths.corpus_tmp; @@ -1156,7 +1153,7 @@ impl OutputPaths { s.to_str().unwrap_or_default(), format!( "{}/{}", - &self.corpus_tmp, + self.corpus_tmp, s.file_name() .unwrap_or_default() .to_str() diff --git a/src/bin/cargo-ziggy/main.rs b/src/bin/cargo-ziggy/main.rs index 790e82d..b75343d 100644 --- a/src/bin/cargo-ziggy/main.rs +++ b/src/bin/cargo-ziggy/main.rs @@ -428,7 +428,7 @@ impl Common { terminate: Arc::new(AtomicBool::new(false)), sigs_done: Some(()), cargo_path: std::env::var("CARGO") - .unwrap_or_else(|_| String::from("cargo")) + .unwrap_or_else(|_| "cargo".to_owned()) .into(), metadata: OnceLock::new(), } @@ -469,6 +469,14 @@ impl Common { cmd } + fn rustc() -> std::process::Command { + let mut cmd = std::process::Command::new( + std::env::var("RUSTC").unwrap_or_else(|_| "rustc".to_owned()), + ); + cmd.stdin(std::process::Stdio::null()); + cmd + } + /// Cached `cargo metadata` fn metadata(&self) -> Option<&cargo_metadata::Metadata> { self.metadata diff --git a/src/bin/cargo-ziggy/minimize.rs b/src/bin/cargo-ziggy/minimize.rs index 3d15313..4792086 100644 --- a/src/bin/cargo-ziggy/minimize.rs +++ b/src/bin/cargo-ziggy/minimize.rs @@ -148,7 +148,7 @@ impl Minimize { "HFUZZ_WORKSPACE", format!( "{}/{}/honggfuzz", - &self.ziggy_output.display(), + self.ziggy_output.display(), cx.bin_target() ), ) @@ -156,8 +156,8 @@ impl Minimize { "HFUZZ_RUN_ARGS", format!( "-i{} -M -o{} -t{}", - &self.input_corpus(cx.as_ref()), - &self.output_corpus(cx.as_ref()), + self.input_corpus(cx.as_ref()), + self.output_corpus(cx.as_ref()), self.timeout ), ) diff --git a/src/bin/cargo-ziggy/plot.rs b/src/bin/cargo-ziggy/plot.rs index 790ccfe..2e4b72f 100644 --- a/src/bin/cargo-ziggy/plot.rs +++ b/src/bin/cargo-ziggy/plot.rs @@ -11,7 +11,7 @@ impl Plot { "{}/{}/afl/{}/", self.ziggy_output.display(), cx.bin_target, - &self.input + self.input ); let plot_dir = self diff --git a/src/bin/cargo-ziggy/run.rs b/src/bin/cargo-ziggy/run.rs index 4908543..74fe292 100644 --- a/src/bin/cargo-ziggy/run.rs +++ b/src/bin/cargo-ziggy/run.rs @@ -28,7 +28,6 @@ impl Run { args.push(&asan_target_str); args.extend(["-Z", "build-std"]); rust_flags.push_str(" -Zsanitizer=address "); - rust_flags.push_str(" -Copt-level=0 "); rust_doc_flags.push_str(" -Zsanitizer=address "); } diff --git a/src/bin/cargo-ziggy/triage.rs b/src/bin/cargo-ziggy/triage.rs index debcd9f..2e0e23f 100644 --- a/src/bin/cargo-ziggy/triage.rs +++ b/src/bin/cargo-ziggy/triage.rs @@ -22,17 +22,11 @@ impl Triage { .replace("{target_name}", &cx.bin_target); fs::remove_dir_all(&triage_dir).ok(); - if !fs::metadata(&input_dir) - .map(|meta| meta.is_dir()) - .unwrap_or(false) - { + if !fs::metadata(&input_dir).is_ok_and(|meta| meta.is_dir()) { bail!("This option requires that at least one AFL++ instance was run!"); } - if fs::metadata(&triage_dir) - .map(|meta| meta.is_dir()) - .unwrap_or(false) - { + if fs::metadata(&triage_dir).is_ok_and(|meta| meta.is_dir()) { bail!("Please remove {triage_dir:?} first"); } diff --git a/tests/asan_fuzz.rs b/tests/asan_fuzz.rs index 6d6c6e1..f485928 100644 --- a/tests/asan_fuzz.rs +++ b/tests/asan_fuzz.rs @@ -1,5 +1,21 @@ -use std::{env, fs, path::PathBuf, process, thread, time::Duration}; +use std::{ + env, fs, + io::Write, + path::PathBuf, + process, + sync::{Mutex, MutexGuard}, + thread, + time::Duration, +}; +static EXCLUSIVE: Mutex<()> = Mutex::new(()); + +fn exclusive_guard() -> MutexGuard<'static, ()> { + EXCLUSIVE.lock().unwrap_or_else(|e| { + EXCLUSIVE.clear_poison(); + e.into_inner() + }) +} fn kill_subprocesses_recursively(pid: &str) { let subprocesses = process::Command::new("pgrep") .arg(format!("-P{pid}")) @@ -25,7 +41,8 @@ fn kill_subprocesses_recursively(pid: &str) { #[allow(clippy::zombie_processes)] #[test] -fn asan_crashes() { +fn afl_crashes() { + let _guard = exclusive_guard(); // Not optimal but seems to work fine if !env!("CARGO").contains("nightly") { println!("Not running nightly, skipping"); @@ -58,6 +75,7 @@ fn asan_crashes() { .arg("ziggy") .arg("fuzz") .arg("--asan") + .arg("--no-honggfuzz") .env("ZIGGY_OUTPUT", format!("{}", temp_dir_path.display())) .env("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "1") .env("AFL_SKIP_CPUFREQ", "1") @@ -88,3 +106,204 @@ fn asan_crashes() { != 0 ); } + +#[allow(clippy::zombie_processes)] +#[test] +fn afl_release_crashes() { + let _guard = exclusive_guard(); + // Not optimal but seems to work fine + if !env!("CARGO").contains("nightly") { + println!("Not running nightly, skipping"); + return; + } + let temp_dir = tempfile::tempdir().unwrap(); + let temp_dir_path = temp_dir.path(); + let metadata = cargo_metadata::MetadataCommand::new().exec().unwrap(); + let workspace_root: PathBuf = metadata.workspace_root.into(); + let target_directory: PathBuf = metadata.target_directory.into(); + let cargo_ziggy = target_directory.join("debug").join("cargo-ziggy"); + let fuzzer_directory = workspace_root.join("examples").join("asan"); + + // TODO Custom target path + + // cargo ziggy build + let build_status = process::Command::new(&cargo_ziggy) + .arg("ziggy") + .arg("build") + .arg("--asan") + .arg("--release") + .arg("--no-honggfuzz") + .current_dir(&fuzzer_directory) + .status() + .expect("failed to run `cargo ziggy build`"); + + assert!(build_status.success(), "`cargo ziggy build` failed"); + + // cargo ziggy fuzz --asan + let fuzzer = process::Command::new(&cargo_ziggy) + .arg("ziggy") + .arg("fuzz") + .arg("--asan") + .arg("--release") + .arg("--no-honggfuzz") + .env("ZIGGY_OUTPUT", format!("{}", temp_dir_path.display())) + .env("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "1") + .env("AFL_SKIP_CPUFREQ", "1") + .current_dir(&fuzzer_directory) + .spawn() + .expect("failed to run `cargo ziggy fuzz`"); + thread::sleep(Duration::from_secs(30)); + kill_subprocesses_recursively(&format!("{}", fuzzer.id())); + + assert!( + temp_dir_path + .join("asan-fuzz") + .join("afl") + .join("mainaflfuzzer") + .join("fuzzer_stats") + .is_file() + ); + assert!( + fs::read_dir( + temp_dir_path + .join("asan-fuzz") + .join("afl") + .join("mainaflfuzzer") + .join("crashes") + ) + .unwrap() + .count() + != 0 + ); +} + +#[allow(clippy::zombie_processes)] +#[test] +fn honggfuzz_crashes() { + let _guard = exclusive_guard(); + // Not optimal but seems to work fine + if !env!("CARGO").contains("nightly") { + println!("Not running nightly, skipping"); + return; + } + let temp_dir = tempfile::tempdir().unwrap(); + let temp_dir_path = temp_dir.path(); + let metadata = cargo_metadata::MetadataCommand::new().exec().unwrap(); + let workspace_root: PathBuf = metadata.workspace_root.into(); + let target_directory: PathBuf = metadata.target_directory.into(); + let cargo_ziggy = target_directory.join("debug").join("cargo-ziggy"); + let fuzzer_directory = workspace_root.join("examples").join("asan"); + + // cargo ziggy build + let build_status = process::Command::new(&cargo_ziggy) + .arg("ziggy") + .arg("build") + .arg("--asan") + .arg("--no-afl") + .current_dir(&fuzzer_directory) + .status() + .expect("failed to run `cargo ziggy build`"); + + assert!(build_status.success(), "`cargo ziggy build` failed"); + + // provide unlocking seed + std::fs::create_dir_all(temp_dir_path.join("asan-fuzz/corpus")).unwrap(); + let mut file = std::fs::File::create(temp_dir_path.join("asan-fuzz/corpus/unlock")).unwrap(); + file.write_all(b"fuzzer").unwrap(); + + // cargo ziggy fuzz --asan + let fuzzer = process::Command::new(&cargo_ziggy) + .arg("ziggy") + .arg("fuzz") + .arg("--asan") + .arg("--no-afl") + .env("ZIGGY_OUTPUT", format!("{}", temp_dir_path.display())) + .current_dir(&fuzzer_directory) + .spawn() + .expect("failed to run `cargo ziggy fuzz`"); + thread::sleep(Duration::from_secs(5)); + kill_subprocesses_recursively(&format!("{}", fuzzer.id())); + + assert!( + fs::read_dir(temp_dir_path.join("asan-fuzz/honggfuzz/asan-fuzz")) + .unwrap() + .filter(|entry| { + entry.as_ref().is_ok_and(|entry| { + entry + .path() + .file_name() + .and_then(std::ffi::OsStr::to_str) + .is_some_and(|n| n.starts_with("SIGABRT")) + }) + }) + .count() + != 0 + ); +} + +#[allow(clippy::zombie_processes)] +#[test] +fn honggfuzz_builds_once() { + let _guard = exclusive_guard(); + let temp_dir = tempfile::tempdir().unwrap(); + let output_dir = temp_dir.path().join("output"); + let target_dir = temp_dir.path().join("target"); + let metadata = cargo_metadata::MetadataCommand::new().exec().unwrap(); + let workspace_root: PathBuf = metadata.workspace_root.into(); + let cargo_ziggy = metadata.target_directory.join("debug/cargo-ziggy"); + let fuzzer_directory = workspace_root.join("examples/asan"); + let hfuzz_dir = output_dir.join("asan-fuzz/honggfuzz"); + + // cargo ziggy build + let build_status = process::Command::new(&cargo_ziggy) + .arg("ziggy") + .arg("build") + .arg("--no-afl") + .env("CARGO_TARGET_DIR", &target_dir) + .current_dir(&fuzzer_directory) + .status() + .expect("failed to run `cargo ziggy build`"); + assert!(build_status.success(), "`cargo ziggy build` failed"); + + let fuzzer = process::Command::new(&cargo_ziggy) + .arg("ziggy") + .arg("fuzz") + .arg("--no-afl") + .env("CARGO_TARGET_DIR", &target_dir) + .env("ZIGGY_OUTPUT", &output_dir) + .current_dir(&fuzzer_directory) + .spawn() + .expect("failed to run `cargo ziggy fuzz`"); + thread::sleep(Duration::from_secs(1)); + kill_subprocesses_recursively(&format!("{}", fuzzer.id())); + assert!(hfuzz_dir.is_dir()); + + if !env!("CARGO").contains("nightly") { + return; + } + std::fs::remove_dir_all(&hfuzz_dir).unwrap(); + let build_status = process::Command::new(&cargo_ziggy) + .arg("ziggy") + .arg("build") + .arg("--no-afl") + .arg("--asan") + .env("CARGO_TARGET_DIR", &target_dir) + .current_dir(&fuzzer_directory) + .status() + .expect("failed to run `cargo ziggy build`"); + assert!(build_status.success(), "`cargo ziggy build` failed"); + + let fuzzer = process::Command::new(&cargo_ziggy) + .arg("ziggy") + .arg("fuzz") + .arg("--no-afl") + .arg("--asan") + .env("CARGO_TARGET_DIR", &target_dir) + .env("ZIGGY_OUTPUT", &output_dir) + .current_dir(&fuzzer_directory) + .spawn() + .expect("failed to run `cargo ziggy fuzz`"); + thread::sleep(Duration::from_secs(1)); + kill_subprocesses_recursively(&format!("{}", fuzzer.id())); + assert!(hfuzz_dir.is_dir()); +} From c7c6ea0081cabc38ced64a5571dbf4f3fb4b5726 Mon Sep 17 00:00:00 2001 From: Christoph Gehrke Date: Thu, 27 Aug 2026 16:30:36 +0200 Subject: [PATCH 2/7] fix(CI): pin nightly version And enable verbose output for cargo afl config (compiling AFL++). --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf7bc65..25d7222 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: toolchain: - stable - beta - - nightly + - nightly-2026-08-01 # pin while afl.rs's AFL++ version is incompatible with llvm-23 steps: - uses: actions/checkout@v6 - run: sudo apt-get update @@ -36,7 +36,7 @@ jobs: - run: rustup component add rust-src llvm-tools - run: cargo install cargo-afl honggfuzz - name: Install LLVM matching the nightly toolchain (for AFL++ cmplog plugins) - if: ${{ matrix.toolchain == 'nightly' }} + if: ${{ startsWith(matrix.toolchain, 'nightly') }} run: | # afl.rs builds the AFL++ LLVM pass plugins against rustc's embedded # LLVM, so we need a matching `llvm-config-` on PATH. @@ -47,8 +47,8 @@ jobs: sudo ./llvm.sh "${LLVM_VERSION}" sudo apt-get install -y "llvm-${LLVM_VERSION}-dev" "libclang-${LLVM_VERSION}-dev" llvm-config-"${LLVM_VERSION}" --version - - if: ${{ matrix.toolchain == 'nightly' }} - run: cargo afl config --plugins --build + - if: ${{ startsWith(matrix.toolchain, 'nightly') }} + run: cargo afl config --plugins --build --verbose - run: cargo install --path . --verbose - if: ${{ matrix.toolchain == 'stable' }} run: diff <(awk '/^```$/ && p{exit} p; /^\$ cargo ziggy/{p=1}' README.md) <(cargo ziggy 2>&1) From 1f69eb5e96e70ea2183136514fdc13f946dfb904 Mon Sep 17 00:00:00 2001 From: Christoph Gehrke Date: Fri, 28 Aug 2026 12:36:58 +0200 Subject: [PATCH 3/7] fix: disable cmplog when not available --- src/bin/cargo-ziggy/build.rs | 3 +-- src/bin/cargo-ziggy/fuzz.rs | 14 +++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/bin/cargo-ziggy/build.rs b/src/bin/cargo-ziggy/build.rs index 288121f..ded0414 100644 --- a/src/bin/cargo-ziggy/build.rs +++ b/src/bin/cargo-ziggy/build.rs @@ -89,7 +89,6 @@ impl Build { .args(afl_args) .env("AFL_QUIET", "1") .env("AFLRS_REQUIRE_PLUGINS", "1") - .env("AFL_LLVM_CMPLOG", "1") // for afl.rs feature "plugins" .env("RUSTFLAGS", rust_flags) .env("RUSTDOCFLAGS", rust_doc_flags) .spawn()? @@ -139,7 +138,7 @@ fn is_using_nightly_toolchain() -> bool { .is_ok_and(|out| String::from_utf8_lossy(&out.stdout).contains("nightly")) } -fn afl_plugins_installed(common: &Common) -> bool { +pub fn afl_plugins_installed(common: &Common) -> bool { common .cargo() .args(["afl", "--version"]) diff --git a/src/bin/cargo-ziggy/fuzz.rs b/src/bin/cargo-ziggy/fuzz.rs index 459cba7..a6d6094 100644 --- a/src/bin/cargo-ziggy/fuzz.rs +++ b/src/bin/cargo-ziggy/fuzz.rs @@ -472,6 +472,10 @@ impl Fuzz { if afl_jobs > 0 { std::fs::create_dir_all(format!("{}/afl", paths.output_target))?; + // afl.rs needs plugins (for CMPLOG) + let maybe_cmplog = + self.binary.is_some() || crate::build::afl_plugins_installed(cx.common()); + // https://aflplus.plus/docs/fuzzing_in_depth/#c-using-multiple-cores let afl_modes = [ "explore", "fast", "coe", "lin", "quad", "exploit", "rare", "explore", "fast", @@ -511,11 +515,11 @@ impl Fuzz { _ => "", }; // Only few instances do cmplog - let cmplog_options = match job_num { - 1 => "-l2a", - 3 => "-l1", - 14 => "-l2a", - 22 => "-l3at", + let cmplog_options = match maybe_cmplog.then_some(job_num) { + Some(1) => "-l2a", + Some(3) => "-l1", + Some(14) => "-l2a", + Some(22) => "-l3at", _ => "-c-", // disable Cmplog, needs AFL++ 4.08a }; // AFL timeout is in ms so we convert the value From eae8d1bc82ea6dbc0f583daa511b9c6713049d3c Mon Sep 17 00:00:00 2001 From: Christoph Gehrke Date: Fri, 28 Aug 2026 13:38:14 +0200 Subject: [PATCH 4/7] fix: restore honggfuzz persistent mode --- src/lib.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c85009d..a28207f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,6 +91,16 @@ macro_rules! fuzz { }; } +#[cfg(feature = "honggfuzz")] +#[doc(hidden)] +pub use honggfuzz::fuzz as honggfuzz_fuzz; + +#[macro_export] #[cfg(all(feature = "honggfuzz", not(feature = "afl")))] -#[doc(inline)] -pub use honggfuzz::fuzz; +macro_rules! fuzz { + ( $($x:tt)* ) => { + loop { + $crate::honggfuzz_fuzz!($($x)*); + } + }; +} From 86fb6f524afd88a8b421c722be8377d882434cbb Mon Sep 17 00:00:00 2001 From: Christoph Gehrke Date: Fri, 28 Aug 2026 15:09:25 +0200 Subject: [PATCH 5/7] feat: parse package metadata This allows to restrict harnesses to only certain fuzzers by editing their Cargo.toml: ```toml [package.metadata.ziggy] compat = ["afl"] ``` --- Cargo.lock | 8 ++--- src/bin/cargo-ziggy/main.rs | 58 ++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c9f830..da59462 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,9 +147,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chacha20" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" dependencies = [ "cfg-if", "cpufeatures", @@ -216,9 +216,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" dependencies = [ "libc", ] diff --git a/src/bin/cargo-ziggy/main.rs b/src/bin/cargo-ziggy/main.rs index b75343d..4ed81e0 100644 --- a/src/bin/cargo-ziggy/main.rs +++ b/src/bin/cargo-ziggy/main.rs @@ -528,6 +528,25 @@ impl Common { fn resolve_bin(&self, target: Option) -> Result { target.ok_or(()).or_else(|()| self.guess_bin()) } + + fn compatible_fuzzers(&self) -> Option> { + let meta = self.metadata()?; + if meta.workspace_default_members.is_missing() { + return None; + } + + let compat: Vec<_> = meta + .workspace_default_packages() + .first()? + .metadata + .get("ziggy")? + .get("compat")? + .as_array()? + .iter() + .filter_map(|v| v.as_str().map(String::from)) + .collect(); + Some(compat) + } } fn main() -> Result<(), anyhow::Error> { @@ -535,7 +554,44 @@ fn main() -> Result<(), anyhow::Error> { common.shutdown_immediate(); common.setup_signal_handling()?; - let Cargo::Ziggy(command) = Cargo::parse(); + let Cargo::Ziggy(mut command) = Cargo::parse(); + + if let Some(compat) = common.compatible_fuzzers() { + let mut with_afl = false; + let mut with_honggfuzz = false; + for fuzzer in compat { + match fuzzer.to_lowercase().as_str() { + "afl" => { + with_afl = true; + } + "honggfuzz" => { + with_honggfuzz = true; + } + other => bail!("unknown fuzzer {other} in [package.metadata.ziggy]"), + } + } + + match &mut command { + Ziggy::Build(build) => { + build.no_afl = !with_afl; + build.no_honggfuzz = !with_honggfuzz; + } + Ziggy::Fuzz(fuzz) => { + fuzz.no_afl = !with_afl; + fuzz.no_honggfuzz = !with_honggfuzz; + } + Ziggy::Minimize(minimize) => { + minimize.engine = match (with_afl, with_honggfuzz) { + (true, true) => FuzzingEngines::All, + (true, false) => FuzzingEngines::AFLPlusPlus, + (false, true) => FuzzingEngines::Honggfuzz, + _ => bail!("harness is not compatible with any fuzzer"), + } + } + _ => {} + } + } + match command { Ziggy::Build(args) => args.build(&common).context("Failed to build the fuzzers"), Ziggy::Fuzz(mut args) => args.fuzz(&common).context("Failure running fuzzers"), From 0d69d3601d3915e8b46325dc8b6aeaaf8dfb4a63 Mon Sep 17 00:00:00 2001 From: Christoph Gehrke Date: Fri, 28 Aug 2026 16:48:12 +0200 Subject: [PATCH 6/7] Revert "fix: disable cmplog when not available" This reverts commit 1f69eb5e96e70ea2183136514fdc13f946dfb904. --- src/bin/cargo-ziggy/build.rs | 3 ++- src/bin/cargo-ziggy/fuzz.rs | 14 +++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/bin/cargo-ziggy/build.rs b/src/bin/cargo-ziggy/build.rs index ded0414..288121f 100644 --- a/src/bin/cargo-ziggy/build.rs +++ b/src/bin/cargo-ziggy/build.rs @@ -89,6 +89,7 @@ impl Build { .args(afl_args) .env("AFL_QUIET", "1") .env("AFLRS_REQUIRE_PLUGINS", "1") + .env("AFL_LLVM_CMPLOG", "1") // for afl.rs feature "plugins" .env("RUSTFLAGS", rust_flags) .env("RUSTDOCFLAGS", rust_doc_flags) .spawn()? @@ -138,7 +139,7 @@ fn is_using_nightly_toolchain() -> bool { .is_ok_and(|out| String::from_utf8_lossy(&out.stdout).contains("nightly")) } -pub fn afl_plugins_installed(common: &Common) -> bool { +fn afl_plugins_installed(common: &Common) -> bool { common .cargo() .args(["afl", "--version"]) diff --git a/src/bin/cargo-ziggy/fuzz.rs b/src/bin/cargo-ziggy/fuzz.rs index a6d6094..459cba7 100644 --- a/src/bin/cargo-ziggy/fuzz.rs +++ b/src/bin/cargo-ziggy/fuzz.rs @@ -472,10 +472,6 @@ impl Fuzz { if afl_jobs > 0 { std::fs::create_dir_all(format!("{}/afl", paths.output_target))?; - // afl.rs needs plugins (for CMPLOG) - let maybe_cmplog = - self.binary.is_some() || crate::build::afl_plugins_installed(cx.common()); - // https://aflplus.plus/docs/fuzzing_in_depth/#c-using-multiple-cores let afl_modes = [ "explore", "fast", "coe", "lin", "quad", "exploit", "rare", "explore", "fast", @@ -515,11 +511,11 @@ impl Fuzz { _ => "", }; // Only few instances do cmplog - let cmplog_options = match maybe_cmplog.then_some(job_num) { - Some(1) => "-l2a", - Some(3) => "-l1", - Some(14) => "-l2a", - Some(22) => "-l3at", + let cmplog_options = match job_num { + 1 => "-l2a", + 3 => "-l1", + 14 => "-l2a", + 22 => "-l3at", _ => "-c-", // disable Cmplog, needs AFL++ 4.08a }; // AFL timeout is in ms so we convert the value From e09a97a7f2888e22811798d2eed9d994dd43d120 Mon Sep 17 00:00:00 2001 From: Christoph Gehrke Date: Fri, 28 Aug 2026 17:06:06 +0200 Subject: [PATCH 7/7] fix: resolve issues from review --- src/bin/cargo-ziggy/main.rs | 40 +++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/bin/cargo-ziggy/main.rs b/src/bin/cargo-ziggy/main.rs index 4ed81e0..9bb3064 100644 --- a/src/bin/cargo-ziggy/main.rs +++ b/src/bin/cargo-ziggy/main.rs @@ -529,15 +529,16 @@ impl Common { target.ok_or(()).or_else(|()| self.guess_bin()) } - fn compatible_fuzzers(&self) -> Option> { + fn compatible_fuzzers(&self, bin_name: &str) -> Option> { let meta = self.metadata()?; if meta.workspace_default_members.is_missing() { return None; } - let compat: Vec<_> = meta + let compat = meta .workspace_default_packages() - .first()? + .into_iter() + .find(|p| p.targets.iter().any(|t| t.is_bin() && t.name == bin_name))? .metadata .get("ziggy")? .get("compat")? @@ -556,7 +557,17 @@ fn main() -> Result<(), anyhow::Error> { let Cargo::Ziggy(mut command) = Cargo::parse(); - if let Some(compat) = common.compatible_fuzzers() { + let bin_target = match &command { + Ziggy::Build(build) => Some(build.target.clone()), + Ziggy::Fuzz(fuzz) => Some(fuzz.target.clone()), + Ziggy::Minimize(minimize) => Some(minimize.target.clone()), + _ => None, + }; + + if let Some(bin_target) = bin_target + && let Ok(harness) = common.resolve_bin(bin_target) + && let Some(compat) = common.compatible_fuzzers(&harness) + { let mut with_afl = false; let mut with_honggfuzz = false; for fuzzer in compat { @@ -573,19 +584,28 @@ fn main() -> Result<(), anyhow::Error> { match &mut command { Ziggy::Build(build) => { - build.no_afl = !with_afl; - build.no_honggfuzz = !with_honggfuzz; + build.no_afl |= !with_afl; + build.no_honggfuzz |= !with_honggfuzz; } Ziggy::Fuzz(fuzz) => { - fuzz.no_afl = !with_afl; - fuzz.no_honggfuzz = !with_honggfuzz; + fuzz.no_afl |= !with_afl; + fuzz.no_honggfuzz |= !with_honggfuzz; } Ziggy::Minimize(minimize) => { - minimize.engine = match (with_afl, with_honggfuzz) { + let use_afl = matches!( + minimize.engine, + FuzzingEngines::AFLPlusPlus | FuzzingEngines::All + ) && with_afl; + let use_honggfuzz = matches!( + minimize.engine, + FuzzingEngines::Honggfuzz | FuzzingEngines::All + ) && with_honggfuzz; + + minimize.engine = match (use_afl, use_honggfuzz) { (true, true) => FuzzingEngines::All, (true, false) => FuzzingEngines::AFLPlusPlus, (false, true) => FuzzingEngines::Honggfuzz, - _ => bail!("harness is not compatible with any fuzzer"), + (false, false) => bail!("harness is not compatible with any requested fuzzer"), } } _ => {}