diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6b08eaf..f847a17 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,26 +21,26 @@ jobs: os: windows-latest host_target: x86_64-pc-windows-msvc steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - name: Install latest nightly - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - target: ${{ matrix.host_target }} - override: true + - name: Install latest nightly + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + target: ${{ matrix.host_target }} + override: true - - name: build - uses: actions-rs/cargo@v1 - with: - command: build - args: --target=${{ matrix.host_target }} --release + - name: build + uses: actions-rs/cargo@v1 + with: + command: build + args: --target=${{ matrix.host_target }} --release - - name: test - uses: actions-rs/cargo@v1 - with: - command: test - args: --release + - name: test + uses: actions-rs/cargo@v1 + with: + command: test + args: --release fmt: name: check formatting @@ -57,4 +57,4 @@ jobs: uses: actions-rs/cargo@v1 with: command: fmt - args: --all -- --check \ No newline at end of file + args: --all -- --check diff --git a/.github/workflows/just-ci.yml b/.github/workflows/just-ci.yml new file mode 100644 index 0000000..4db7109 --- /dev/null +++ b/.github/workflows/just-ci.yml @@ -0,0 +1,33 @@ +name: Just CI + +on: + push: + branches: ["main", "master"] + pull_request: + branches: ["main", "master"] + +jobs: + just-test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Rust Nightly + uses: dtolnay/rust-toolchain@nightly + with: + components: clippy, rustfmt + + - name: Install tools + uses: taiki-e/install-action@v2 + with: + tool: just,taplo + + - name: Run just fmt-check + run: just fmt-check + + - name: Run just clippy + run: just clippy + + - name: Run just test + run: just test diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bf2d5f..728f076 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,47 +1,40 @@ -## 0.5.3 (2020-11-09) -* Fix some general bugs with resizing `Vec` +## 0.5.3 (2020-11-09) +- Fix some general bugs with resizing `Vec` -## 0.5.2 (2020-07-07) +## 0.5.2 (2020-07-07) #### Features -* **mutations:** add support for Box ([d6a2cc76](https://github.com/microsoft/lain/commit/d6a2cc76a3bffdb9719c9a385be33f4e29f70769)) - - +- **mutations:** add support for Box ([d6a2cc76](https://github.com/microsoft/lain/commit/d6a2cc76a3bffdb9719c9a385be33f4e29f70769)) -## 0.5.1 (2020-06-18) +## 0.5.1 (2020-06-18) #### Bug Fixes -* **mutations:** - * change how/when fixups are performed ([f51644e1](https://github.com/microsoft/lain/commit/f51644e1bd86f46586a7b24e26183082f6b33a94)) - * revert 1d79b7e0 which inlined generated mutations ([bf7ed1e7](https://github.com/microsoft/lain/commit/bf7ed1e77de5f29bc37ac06a2016b01734478545)) -* **serialization:** revert 2076d121 which inlined generated serde code ([917c1baa](https://github.com/microsoft/lain/commit/917c1baa7d4a54c5faf404542e7ac3609741ebba)) - - +- **mutations:** + - change how/when fixups are performed ([f51644e1](https://github.com/microsoft/lain/commit/f51644e1bd86f46586a7b24e26183082f6b33a94)) + - revert 1d79b7e0 which inlined generated mutations ([bf7ed1e7](https://github.com/microsoft/lain/commit/bf7ed1e77de5f29bc37ac06a2016b01734478545)) +- **serialization:** revert 2076d121 which inlined generated serde code ([917c1baa](https://github.com/microsoft/lain/commit/917c1baa7d4a54c5faf404542e7ac3609741ebba)) -## 0.5 (2020-06-16) +## 0.5 (2020-06-16) #### Bug Fixes -* **constraints:** Mutating now strictly respects max size constraint ([2e487784](https://github.com/microsoft/lain/commit/2e4877845d9a02df736944dbe09e56f3daf86cab)) -* **mutations:** - * ignore_chance should now be working for enum variants ([a97cb173](https://github.com/microsoft/lain/commit/a97cb173f4b20f6f1923279d007a9fe9538c94fb)) - * partially fix regression where ignore_chance did not work for enum variants ([e8d23ae2](https://github.com/microsoft/lain/commit/e8d23ae2768292a89e015b3faf73eee4bc9ca3af)) +- **constraints:** Mutating now strictly respects max size constraint ([2e487784](https://github.com/microsoft/lain/commit/2e4877845d9a02df736944dbe09e56f3daf86cab)) +- **mutations:** + - ignore_chance should now be working for enum variants ([a97cb173](https://github.com/microsoft/lain/commit/a97cb173f4b20f6f1923279d007a9fe9538c94fb)) + - partially fix regression where ignore_chance did not work for enum variants ([e8d23ae2](https://github.com/microsoft/lain/commit/e8d23ae2768292a89e015b3faf73eee4bc9ca3af)) #### Performance -* **mutations:** hint to inline struct fuzzing functions ([1d79b7e0](https://github.com/microsoft/lain/commit/1d79b7e0732f6a3ef39e302e50fd5f79640cd143)) -* **serialization:** inline generated serialization code ([2076d121](https://github.com/microsoft/lain/commit/2076d121caaab15300163e284a706a55b42553c6)) - - - +- **mutations:** hint to inline struct fuzzing functions ([1d79b7e0](https://github.com/microsoft/lain/commit/1d79b7e0732f6a3ef39e302e50fd5f79640cd143)) +- **serialization:** inline generated serialization code ([2076d121](https://github.com/microsoft/lain/commit/2076d121caaab15300163e284a706a55b42553c6)) diff --git a/Cargo.lock b/Cargo.lock index 27598f3..075f719 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,27 +3,46 @@ version = 4 [[package]] -name = "atty" -version = "0.2.14" +name = "aho-corasick" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ - "hermit-abi", - "libc", - "winapi", + "memchr", ] [[package]] -name = "autocfg" -version = "1.3.0" +name = "alloca" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] [[package]] -name = "bitflags" -version = "1.3.2" +name = "anes" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bitflags" @@ -39,11 +58,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cast" -version = "0.2.7" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ - "rustc_version", + "find-msvc-tools", + "shlex", ] [[package]] @@ -53,102 +79,128 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "clap" -version = "2.34.0" +name = "chacha20" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ - "bitflags 1.3.2", - "textwrap", - "unicode-width", + "cfg-if", + "cpufeatures", + "rand_core", ] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "ciborium" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ - "bitflags 1.3.2", + "ciborium-io", + "ciborium-ll", + "serde", ] [[package]] -name = "criterion" -version = "0.2.11" +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0363053954f3e679645fc443321ca128b7b950a6fe288cf5f9335cc22ee58394" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ - "atty", - "cast", - "clap", - "csv", - "itertools", - "lazy_static", - "libc", - "num-traits", - "rand_core 0.3.1", - "rand_os", - "rand_xoshiro", - "rayon", - "rayon-core", - "serde", - "serde_derive", - "serde_json", - "walkdir", + "ciborium-io", + "half", ] [[package]] -name = "crossbeam-deque" -version = "0.8.6" +name = "clap" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", + "clap_builder", ] [[package]] -name = "crossbeam-epoch" -version = "0.9.18" +name = "clap_builder" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "crossbeam-utils", + "anstyle", + "clap_lex", ] [[package]] -name = "crossbeam-utils" -version = "0.8.21" +name = "clap_lex" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] -name = "csv" -version = "1.3.1" +name = "cpufeatures" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ - "csv-core", - "itoa", - "ryu", + "libc", +] + +[[package]] +name = "criterion" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3" +dependencies = [ + "alloca", + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools", + "num-traits", + "oorandom", + "page_size", + "regex", "serde", + "serde_json", + "tinytemplate", + "walkdir", ] [[package]] -name = "csv-core" -version = "0.1.11" +name = "criterion-plot" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +checksum = "d8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29ea" dependencies = [ - "memchr", + "cast", + "itertools", ] +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "either" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "field-offset" version = "0.3.6" @@ -160,37 +212,86 @@ dependencies = [ ] [[package]] -name = "fuchsia-cprng" -version = "0.1.1" +name = "find-msvc-tools" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "getrandom" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "wasi", - "windows-targets", + "r-efi", + "rand_core", + "wasip2", + "wasip3", ] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "half" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ - "libc", + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[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 = "itertools" -version = "0.8.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -235,17 +336,23 @@ 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.154" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "log" -version = "0.4.25" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" @@ -301,9 +408,9 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ - "proc-macro2 1.0.93", - "quote 1.0.38", - "syn 2.0.96", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -346,6 +453,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "paste" version = "1.0.15" @@ -353,10 +476,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "ppv-lite86" -version = "0.2.17" +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2 1.0.106", + "syn 2.0.117", +] [[package]] name = "proc-macro2" @@ -364,14 +491,14 @@ version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -387,111 +514,64 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.38" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ - "proc-macro2 1.0.93", + "proc-macro2 1.0.106", ] [[package]] -name = "rand" -version = "0.9.0" +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" -dependencies = [ - "rand_chacha", - "rand_core 0.9.0", - "zerocopy", -] +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.0", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rand_core" -version = "0.9.0" +name = "rand" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ + "chacha20", "getrandom", - "zerocopy", + "rand_core", ] [[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_xoshiro" -version = "0.1.0" +name = "rand_core" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" -dependencies = [ - "byteorder", - "rand_core 0.3.1", -] +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] -name = "rayon" -version = "1.10.0" +name = "regex" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ - "either", - "rayon-core", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "rayon-core" -version = "1.12.1" +name = "regex-automata" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ - "crossbeam-deque", - "crossbeam-utils", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] -name = "rdrand" -version = "0.4.0" +name = "regex-syntax" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rustc_version" @@ -525,22 +605,32 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ - "proc-macro2 1.0.93", - "quote 1.0.38", - "syn 2.0.96", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -554,6 +644,12 @@ dependencies = [ "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "syn" version = "0.15.44" @@ -562,17 +658,17 @@ checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" dependencies = [ "proc-macro2 0.4.30", "quote 0.6.13", - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] name = "syn" -version = "2.0.96" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ - "proc-macro2 1.0.93", - "quote 1.0.38", + "proc-macro2 1.0.106", + "quote 1.0.45", "unicode-ident", ] @@ -585,12 +681,13 @@ dependencies = [ ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "tinytemplate" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ - "unicode-width", + "serde", + "serde_json", ] [[package]] @@ -600,16 +697,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-width" -version = "0.1.14" +name = "unicode-xid" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.1.0" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "walkdir" @@ -622,12 +719,55 @@ dependencies = [ ] [[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" +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 = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", +] + +[[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]] @@ -735,30 +875,109 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] -name = "wit-bindgen-rt" -version = "0.33.0" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" dependencies = [ - "bitflags 2.8.0", + "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 2.0.117", + "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 1.0.106", + "quote 1.0.45", + "syn 2.0.117", + "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 0.2.6", + "wasmparser", ] [[package]] name = "zerocopy" -version = "0.8.14" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.14" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ - "proc-macro2 1.0.93", - "quote 1.0.38", - "syn 2.0.96", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] diff --git a/Cargo.toml b/Cargo.toml index 18ce4cd..0f9d415 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,8 @@ [workspace] -members = [ - 'testsuite', - 'lain', - 'lain_derive', -] +members = ['testsuite', 'lain', 'lain_derive'] [workspace.package] -version = "0.5.7" +version = "0.5.7" authors = ["Lain Devs", "AFLplusplus"] edition = "2018" homepage = "https://github.com/AFLplusplus/lain" diff --git a/Justfile b/Justfile new file mode 100644 index 0000000..83f2668 --- /dev/null +++ b/Justfile @@ -0,0 +1,74 @@ +# Default recipe to list all available tasks +default: + @just --list + +# Run all tests (clippy, unit tests, and example fuzzer verification) +@test duration="5": clippy test-unit (test-fuzzer duration) + +# Check code formatting and lints +clippy: + cargo clippy --workspace --all-targets -- -D warnings + +# Format codebase (Rust, TOML, YAML, Markdown, Justfile) +fmt: + cargo fmt --all + taplo format + npx prettier --write "**/*.yml" "**/*.yaml" "**/*.md" + just --fmt --unstable + +# Check codebase formatting (Rust, TOML, YAML, Markdown, Justfile) +fmt-check: + cargo fmt --all -- --check + taplo format --check + npx prettier --check "**/*.yml" "**/*.yaml" "**/*.md" + just --fmt --check --unstable + +# Run unit tests across the workspace +test-unit: + cargo test --workspace + +# Build the example target server +build-target: + cd examples/example_target && make + +# Build the example fuzzer +build-fuzzer: + cd examples/example_fuzzer && cargo build + +# Run the example fuzzer for a specified duration to ensure it runs successfully without crashing +@test-fuzzer duration="5": build-target build-fuzzer + #!/usr/bin/env bash + set -euo pipefail + + echo "Starting example target server..." + ./examples/example_target/server & + SERVER_PID=$! + + # Ensure server is cleaned up on exit + trap 'kill $SERVER_PID 2>/dev/null || true' EXIT + + # Wait for server to start listening + sleep 1 + + echo "Running example fuzzer for {{ duration }} seconds..." + # Run the fuzzer binary directly to avoid cargo overhead and accurately capture PID + ./examples/target/debug/example_fuzzer & + FUZZER_PID=$! + + # Sleep for the specified duration + sleep {{ duration }} + + echo "Checking if fuzzer is still running..." + if kill -0 $FUZZER_PID 2>/dev/null; then + echo "Fuzzer is running fine. Stopping it gracefully..." + kill -INT $FUZZER_PID + wait $FUZZER_PID || true + echo "Fuzzer ran successfully for {{ duration }} seconds." + else + echo "Error: Fuzzer crashed or stopped prematurely!" + # Check if server crashed + if ! kill -0 $SERVER_PID 2>/dev/null; then + echo "Error: Server crashed!" + fi + exit 1 + fi diff --git a/examples/Cargo.lock b/examples/Cargo.lock index f9f813a..83dbcd3 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -1,392 +1,690 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + [[package]] name = "autocfg" -version = "0.1.4" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" -version = "1.1.0" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "block2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] [[package]] name = "byteorder" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "c2-chacha" -version = "0.2.2" +name = "cfg-if" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cpufeatures", + "rand_core", ] [[package]] -name = "cc" -version = "1.0.37" +name = "cpufeatures" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] [[package]] -name = "cfg-if" -version = "0.1.9" +name = "ctrlc" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" +dependencies = [ + "dispatch2", + "nix", + "windows-sys", +] [[package]] -name = "ctrlc" -version = "3.1.3" +name = "dispatch2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "block2", + "libc", + "objc2", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "example_fuzzer" version = "0.1.0" dependencies = [ - "ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lain 0.2.0", + "ctrlc", + "lain", ] [[package]] name = "field-offset" -version = "0.1.1" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "getrandom" -version = "0.1.6" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core", + "wasip2", + "wasip3", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[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 = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + [[package]] name = "lain" -version = "0.2.0" +version = "0.5.7" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lain_derive 0.2.0", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "field-offset", + "lain_derive", + "lazy_static", + "log", + "num", + "num-derive", + "num-traits", + "paste", + "rand", ] [[package]] name = "lain_derive" -version = "0.2.0" +version = "0.5.7" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "log", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.39", ] [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "spin 0.5.0 (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.59" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "log" -version = "0.4.7" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] -name = "mashup" -version = "0.1.9" +name = "memchr" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] -name = "mashup-impl" -version = "0.1.9" +name = "memoffset" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", ] [[package]] name = "nix" -version = "0.14.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", ] [[package]] name = "num" -version = "0.2.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", ] [[package]] name = "num-bigint" -version = "0.2.2" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer", + "num-traits", ] [[package]] name = "num-complex" -version = "0.2.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits", ] [[package]] name = "num-derive" -version = "0.2.5" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "num-integer" -version = "0.1.41" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits", ] [[package]] name = "num-iter" -version = "0.1.39" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "num-integer", + "num-traits", ] [[package]] name = "num-rational" -version = "0.2.2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint", + "num-integer", + "num-traits", ] [[package]] name = "num-traits" -version = "0.2.8" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "objc2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "objc2-encode", ] [[package]] -name = "ppv-lite86" -version = "0.2.5" +name = "objc2-encode" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] -name = "proc-macro-hack" -version = "0.4.1" +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ - "proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.106", + "syn 2.0.117", ] [[package]] -name = "proc-macro-hack-impl" -version = "0.4.1" +name = "proc-macro2" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] [[package]] name = "proc-macro2" -version = "0.4.30" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-ident", ] [[package]] name = "quote" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", ] [[package]] -name = "rand" -version = "0.7.0" +name = "quote" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.106", ] [[package]] -name = "rand_chacha" -version = "0.2.0" +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chacha20", + "getrandom", + "rand_core", ] [[package]] name = "rand_core" -version = "0.5.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", ] [[package]] -name = "rand_hc" -version = "0.2.0" +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_core", ] [[package]] -name = "rand_pcg" -version = "0.2.0" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive", ] [[package]] -name = "spin" -version = "0.5.0" +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] [[package]] name = "syn" version = "0.15.39" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", ] +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2 1.0.106", + "quote 1.0.45", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] -name = "void" -version = "1.0.2" +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[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-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 = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +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 2.0.117", + "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 1.0.106", + "quote 1.0.45", + "syn 2.0.117", + "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 = "winapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" -"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7dfd2d8b4c82121dfdff120f818e09fc4380b0b7e17a742081a89b94853e87f" -"checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68" -"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3262021842bf00fe07dbd6cf34ff25c99d7a7ebef8deea84db72be3ea3bb0aff" -"checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3" -"checksum mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f2d82b34c7fb11bb41719465c060589e291d505ca4735ea30016a91f6fc79c3b" -"checksum mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "aa607bfb674b4efb310512527d64266b065de3f894fc52f84efcbf7eaa5965fb" -"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" -"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" -"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" -"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" -"checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" -"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" -"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" -"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" -"checksum rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e193067942ef6f485a349a113329140d0ab9e2168ce92274499bb0e9a4190d9d" -"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6" -"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" -"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +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 0.2.6", + "wasmparser", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 59f1606..5eeb174 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -1,4 +1,2 @@ [workspace] -members = [ - 'example_fuzzer', -] +members = ['example_fuzzer'] diff --git a/examples/example_fuzzer/src/main.rs b/examples/example_fuzzer/src/main.rs index 8dbaa7e..ece3c01 100644 --- a/examples/example_fuzzer/src/main.rs +++ b/examples/example_fuzzer/src/main.rs @@ -80,7 +80,10 @@ fn main() { fn fuzzer_routine(mutator: &mut Mutator, thread_context: &mut FuzzerThreadContext, _global_context: Option>>) -> Result<(), ()> { // TODO: we have overhead here of re-estabilishing the connection every time - let mut stream = TcpStream::connect("127.0.0.1:8080").expect("server isn't running. possible crash?"); + let mut stream = match TcpStream::connect("127.0.0.1:8080") { + Ok(s) => s, + Err(_) => return Err(()), + }; let packet = match thread_context.last_packet { Some(ref mut last_packet) => { @@ -88,7 +91,7 @@ fn fuzzer_routine(mutator: &mut Mutator, thread_context: &mut FuzzerT last_packet } _ => { - mutator.begin_new_corpus(); + mutator.random_flags(); thread_context.last_packet = Some(PacketData::new_fuzzed(mutator, None)); thread_context.last_packet.as_mut().unwrap() @@ -100,10 +103,12 @@ fn fuzzer_routine(mutator: &mut Mutator, thread_context: &mut FuzzerT println!("Sending packet: {:?}", packet); - stream.write(&serialized_data).expect("failed to write data"); + if stream.write(&serialized_data).is_err() { + return Err(()); + } let mut response_data = Vec::new(); - stream.read(&mut response_data); + let _ = stream.read(&mut response_data); thread_context.thread_packet_iterations += 1; diff --git a/examples/example_target/main.c b/examples/example_target/main.c index 6133cb7..c70f520 100644 --- a/examples/example_target/main.c +++ b/examples/example_target/main.c @@ -84,15 +84,14 @@ int main(int argc, char **argv) { switch (datagram->type) { case data_read: LOG("got a data read packet\n"); - if (saved_data != NULL && datagram->offset + datagram->length <= saved_data_length) { - write(connfd, packet_buffer + datagram->offset, datagram->length); + if (saved_data != NULL && datagram->offset + datagram->length >= datagram->offset && datagram->offset + datagram->length <= saved_data_length) { + write(connfd, saved_data + datagram->offset, datagram->length); } break; case data_write: LOG("got a data write packet\n"); - // NOTE: Who cares about checking the offset? Nobody would ever provide bad data - if (saved_data != NULL && datagram->length <= saved_data_length) { + if (saved_data != NULL && datagram->offset + datagram->length >= datagram->offset && datagram->offset + datagram->length <= saved_data_length) { memcpy(saved_data + datagram->offset, datagram->data, datagram->length); } break; diff --git a/lain/Cargo.toml b/lain/Cargo.toml index b311082..3b01884 100644 --- a/lain/Cargo.toml +++ b/lain/Cargo.toml @@ -9,16 +9,16 @@ keywords.workspace = true license.workspace = true [dependencies] -rand = { version = "0.9", features = ["small_rng"] } +rand = { version = "0.10.1" } byteorder = "1.5.0" paste = "1.0.15" lain_derive = { version = "0.5.7", path = "../lain_derive" } -log = "0.4" +log = "0.4.29" num-traits = "0.2.19" num-derive = "0.4.2" num = "0.4.3" lazy_static = "1.5.0" -serde = { version = "1.0.217", optional = true, features = ["derive"] } +serde = { version = "1.0.228", optional = true, features = ["derive"] } field-offset = "0.3.6" [features] diff --git a/lain/src/buffer.rs b/lain/src/buffer.rs index f717845..3417cd5 100644 --- a/lain/src/buffer.rs +++ b/lain/src/buffer.rs @@ -36,46 +36,31 @@ where } } -macro_rules! impl_serialized_size_array { - ( $($size:expr),* ) => { - $( - impl SerializedSize for [T; $size] - where T: SerializedSize { - #[inline] - fn serialized_size(&self) -> usize { - trace!("using default serialized_size for array"); - if $size == 0 { - return 0; - } - - let size = self - .iter() - .map(SerializedSize::serialized_size) - .fold(0, |sum, i| sum + i); +impl SerializedSize for [T; SIZE] +where + T: SerializedSize, +{ + #[inline] + fn serialized_size(&self) -> usize { + trace!("using default serialized_size for array"); + if SIZE == 0 { + return 0; + } - size - } + self.iter().map(SerializedSize::serialized_size).sum() + } - #[inline] - fn min_nonzero_elements_size() -> usize { - T::min_nonzero_elements_size() * $size - } + #[inline] + fn min_nonzero_elements_size() -> usize { + T::min_nonzero_elements_size() * SIZE + } - #[inline] - fn max_default_object_size() -> usize { - T::max_default_object_size() * $size - } - } - )* + #[inline] + fn max_default_object_size() -> usize { + T::max_default_object_size() * SIZE } } -impl_serialized_size_array!( - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 -); - impl SerializedSize for Vec where T: SerializedSize, @@ -415,10 +400,10 @@ where #[inline] fn serialized_size(&self) -> usize { if let Some(ref inner) = self { - inner.serialized_size(); + inner.serialized_size() + } else { + 0 } - - 0 } #[inline] diff --git a/lain/src/dangerous_numbers.rs b/lain/src/dangerous_numbers.rs index dc29801..e7d9102 100644 --- a/lain/src/dangerous_numbers.rs +++ b/lain/src/dangerous_numbers.rs @@ -1,4 +1,4 @@ -use crate::rand::Rng; +use crate::rand::{Rng, RngExt}; use crate::traits::*; static DANGEROUS_NUMBERS_U8: &[u8] = &[ diff --git a/lain/src/driver.rs b/lain/src/driver.rs index 34d5424..830684b 100644 --- a/lain/src/driver.rs +++ b/lain/src/driver.rs @@ -1,6 +1,6 @@ use crate::mutator::Mutator; use rand::rngs::StdRng; -use rand::{Rng, SeedableRng}; +use rand::{RngExt, SeedableRng}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::{Arc, RwLock}; use std::thread; diff --git a/lain/src/lib.rs b/lain/src/lib.rs index c2184a2..19048cc 100644 --- a/lain/src/lib.rs +++ b/lain/src/lib.rs @@ -4,6 +4,7 @@ //! Please consider this crate in "beta" and subject to breaking changes for minor version releases for pre-1.0. #![feature(specialization)] +#![allow(dead_code, unused_variables, incomplete_features)] extern crate num; extern crate num_derive; @@ -58,7 +59,7 @@ pub fn hexdump(data: &[u8]) -> String { } } - if data.len() % 16 != 0 { + if !data.len().is_multiple_of(16) { for _i in 0..16 - (data.len() % 16) { ret += " "; } diff --git a/lain/src/mutatable.rs b/lain/src/mutatable.rs index 37670b7..d68f7dd 100644 --- a/lain/src/mutatable.rs +++ b/lain/src/mutatable.rs @@ -32,6 +32,74 @@ enum VecResizeType { Shrink, } +/// Performs robust, structural resizing on character sequences. +/// Supports stochastic splicing, raw element injection, and multi-mode shrinkage. +fn advanced_resize(vec: &mut Vec, mutator: &mut Mutator, mut gen: F) +where + T: Clone, + F: FnMut(&mut Mutator) -> T, +{ + if vec.is_empty() || mutator.gen_chance(0.5) { + // Growing + if vec.is_empty() || mutator.gen_chance(0.5) { + let grow_by = mutator.random_range(1, 16); + for _ in 0..grow_by { + vec.push(gen(mutator)); + } + } else { + let start = mutator.random_range(0, vec.len()); + let end = mutator.random_range(start, vec.len() + 1); + let chunk = vec[start..end].to_vec(); + let insert_at = mutator.random_range(0, vec.len() + 1); + vec.splice(insert_at..insert_at, chunk); + } + } else if !vec.is_empty() { + // Shrinking + if mutator.gen_chance(0.5) { + let start = mutator.random_range(0, vec.len()); + let end = mutator.random_range(start, vec.len() + 1); + vec.drain(start..end); + } else { + let remove_count = mutator.random_range(1, vec.len() + 1); + if mutator.gen_chance(0.5) { + vec.drain(0..remove_count); + } else { + vec.truncate(vec.len() - remove_count); + } + } + } +} + +/// Encapsulates entire character fuzzing process for structural string buffers. +fn mutate_char_vec(vec: &mut Vec, mutator: &mut Mutator, mut gen: F) +where + T: Clone, + F: FnMut(&mut Mutator) -> T, +{ + const CHANCE_TO_RESIZE: f64 = 0.01; + const CHANCE_TO_RESIZE_EMPTY: f64 = 0.33; + + let should_resize = if vec.is_empty() { + mutator.gen_chance(CHANCE_TO_RESIZE_EMPTY) + } else { + mutator.gen_chance(CHANCE_TO_RESIZE) + }; + + if should_resize { + advanced_resize(vec, mutator, &mut gen); + return; + } + + if vec.is_empty() { + return; + } + + let num_mutations = mutator.random_range(1, vec.len()); + for idx in index::sample(&mut mutator.rng, vec.len(), num_mutations).iter() { + vec[idx] = gen(mutator); + } +} + /// Grows a `Vec`. /// This will randomly select to grow by a factor of 1/4, 1/2, 3/4, or a fixed number of bytes /// in the range of [1, 8]. Elements may be added randomly to the beginning or end of the the vec @@ -539,12 +607,7 @@ impl Mutatable for AsciiString { _constraints: Option<&Constraints>, ) { trace!("performing mutation on an AsciiString"); - - // TODO: Implement logic for resizing? - let num_mutations = mutator.random_range(1, self.inner.len()); - for idx in index::sample(&mut mutator.rng, self.inner.len(), num_mutations).iter() { - self.inner[idx] = AsciiChar::new_fuzzed(mutator, None); - } + mutate_char_vec(&mut self.inner, mutator, |m| AsciiChar::new_fuzzed(m, None)); } } @@ -557,12 +620,22 @@ impl Mutatable for Utf8String { _constraints: Option<&Constraints>, ) { trace!("performing mutation on a Utf8String"); + mutate_char_vec(&mut self.inner, mutator, |m| Utf8Char::new_fuzzed(m, None)); + } +} - // TODO: Implement logic for resizing? - let num_mutations = mutator.random_range(1, self.inner.len()); - for idx in index::sample(&mut mutator.rng, self.inner.len(), num_mutations).iter() { - self.inner[idx] = Utf8Char::new_fuzzed(mutator, None); - } +impl Mutatable for String { + type RangeType = usize; + + fn mutate( + &mut self, + mutator: &mut Mutator, + _constraints: Option<&Constraints>, + ) { + trace!("performing mutation on a String"); + let mut chars: Vec = self.chars().collect(); + mutate_char_vec(&mut chars, mutator, |m| char::new_fuzzed(m, None)); + *self = chars.into_iter().collect(); } } @@ -643,18 +716,41 @@ impl Mutatable for i64 { } } -impl Mutatable for [T; 0] -where - T: Mutatable, -{ - type RangeType = u8; +impl Mutatable for f32 { + type RangeType = f32; + #[inline(always)] fn mutate( &mut self, - _mutator: &mut Mutator, + mutator: &mut Mutator, _constraints: Option<&Constraints>, ) { - // nop + if mutator.gen_chance(0.01) { + *self = f32::select_dangerous_number(&mut mutator.rng); + return; + } + let mut val = self.to_bits(); + mutator.mutate(&mut val); + *self = f32::from_bits(val); + } +} + +impl Mutatable for f64 { + type RangeType = f64; + + #[inline(always)] + fn mutate( + &mut self, + mutator: &mut Mutator, + _constraints: Option<&Constraints>, + ) { + if mutator.gen_chance(0.01) { + *self = f64::select_dangerous_number(&mut mutator.rng); + return; + } + let mut val = self.to_bits(); + mutator.mutate(&mut val); + *self = f64::from_bits(val); } } @@ -730,28 +826,20 @@ where } } -macro_rules! impl_mutatable_array { - ( $($size:expr),* ) => { - $( - impl Mutatable for [T; $size] - where - T: Mutatable + SerializedSize, - T::RangeType: Clone, - { - type RangeType = T::RangeType; +impl Mutatable for [T; SIZE] +where + T: Mutatable + SerializedSize, + T::RangeType: Clone, +{ + type RangeType = T::RangeType; - #[inline(always)] - fn mutate(&mut self, mutator: &mut Mutator, constraints: Option<&Constraints>) { - // Treat this as a slice - self[..].mutate(mutator, constraints); - } - } - )* + #[inline(always)] + fn mutate( + &mut self, + mutator: &mut Mutator, + constraints: Option<&Constraints>, + ) { + // Treat this as a slice + self[..].mutate(mutator, constraints); } } - -impl_mutatable_array!( - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 -); diff --git a/lain/src/mutator.rs b/lain/src/mutator.rs index 863abae..809a086 100644 --- a/lain/src/mutator.rs +++ b/lain/src/mutator.rs @@ -1,5 +1,5 @@ use rand::seq::SliceRandom; -use rand::Rng; +use rand::{Rng, RngExt}; use crate::rand::distr::uniform::{SampleBorrow, SampleUniform}; use crate::traits::*; @@ -163,9 +163,11 @@ impl Mutator { let (bit_indices, _) = potential_bit_indices[0..num_bits as usize] .partial_shuffle(&mut self.rng, num_bits as usize); + let mut mask = 0u64; for idx in bit_indices { - *num = (*num) ^ num::cast(1u64 << *idx).unwrap() + mask |= 1u64 << *idx; } + *num = (*num) ^ num::cast(mask).unwrap(); } /// Perform a simple arithmetic operation on the number (+ or -) diff --git a/lain/src/new_fuzzed.rs b/lain/src/new_fuzzed.rs index 68b7c6b..c028b61 100644 --- a/lain/src/new_fuzzed.rs +++ b/lain/src/new_fuzzed.rs @@ -1,6 +1,6 @@ use crate::mutator::Mutator; -use crate::rand::Rng; +use crate::rand::{Rng, RngExt}; use crate::traits::*; use crate::types::*; use num_traits::Bounded; @@ -81,11 +81,11 @@ where min = 0; } - if constraints.max.is_some() - && mutator.gen_chance(crate::mutator::CHANCE_TO_IGNORE_MIN_MAX) - { - if let Some(new_max) = constraints.max.unwrap().checked_mul(2) { - max = new_max; + if let Some(current_max) = constraints.max { + if mutator.gen_chance(crate::mutator::CHANCE_TO_IGNORE_MIN_MAX) { + if let Some(new_max) = current_max.checked_mul(2) { + max = new_max; + } } } } @@ -191,11 +191,11 @@ where min = 0; } - if constraints.max.is_some() - && mutator.gen_chance(crate::mutator::CHANCE_TO_IGNORE_MIN_MAX) - { - // we just hope this doesn't overflow. - max = constraints.max.unwrap() * 2; + if let Some(current_max) = constraints.max { + if mutator.gen_chance(crate::mutator::CHANCE_TO_IGNORE_MIN_MAX) { + // we just hope this doesn't overflow. + max = current_max * 2; + } } } @@ -294,46 +294,6 @@ where } } -// TODO: Uncomment once const generics are more stable -// impl NewFuzzed for [T; SIZE] -// where T: NewFuzzed + Clone { -// type RangeType = usize; - -// fn new_fuzzed(mutator: &mut Mutator, constraints: Option<&Constraints>) -> [T; SIZE] { -// if constraints.is_some() { -// warn!("Constraints passed to new_fuzzed on fixed-size array do nothing"); -// } - -// let mut output: MaybeUninit<[T; SIZE]> = MaybeUninit::uninit(); -// let arr_ptr = output.as_mut_ptr() as *mut T; - -// let mut idx = 0; -// let mut element: T = T::new_fuzzed(mutator, None); -// while idx < SIZE { -// arr_ptr.add(idx).write(element.clone()); - -// idx += 1; -// if SIZE - idx > 0 { -// if mutator.gen_chance(crate::mutator::CHANCE_TO_REPEAT_ARRAY_VALUE) { -// let repeat_end_idx = mutator.random_range(idx, SIZE); -// while idx < repeat_end_idx { -// arr_ptr.add(idx).write(element.clone()); -// idx += 1; -// } - -// if SIZE - idx > 0 { -// element = T::new_fuzzed(mutator, None); -// } -// } else { -// element = T::new_fuzzed(mutator, None); -// } -// } -// } - -// unsafe { output.assume_init() } -// } -// } - impl NewFuzzed for UnsafeEnum where T: NewFuzzed, @@ -361,6 +321,68 @@ where } } +impl NewFuzzed for String { + type RangeType = usize; + + fn new_fuzzed( + mutator: &mut Mutator, + constraints: Option<&Constraints>, + ) -> Self { + let min: Self::RangeType; + let max: Self::RangeType; + let weight: Weighted; + let mut output: String; + + trace!( + "Generating random String with constraints: {:#?}", + constraints + ); + + // if no min/max were supplied, we'll take a conservative approach + match constraints { + Some(constraints) => { + min = constraints.min.unwrap_or(0); + max = constraints.max.unwrap_or(256); + weight = constraints.weighted; + } + None => { + min = 0; + max = 256; + weight = Weighted::None; + } + } + + let string_length = mutator.gen_weighted_range(min, max, weight); + + output = String::with_capacity(string_length); + + let mut idx = 0; + let mut chr = char::new_fuzzed(mutator, None); + + while idx < string_length { + output.push(chr); + + idx += 1; + if string_length - idx > 0 { + if mutator.gen_chance(crate::mutator::CHANCE_TO_REPEAT_ARRAY_VALUE) { + let repeat_end_idx = mutator.random_range(idx, string_length); + while idx < repeat_end_idx { + output.push(chr); + idx += 1; + } + if string_length - idx > 0 { + chr = char::new_fuzzed(mutator, None); + } + } else { + chr = char::new_fuzzed(mutator, None); + } + } + } + + output + } +} + impl NewFuzzed for Utf8String { type RangeType = usize; @@ -408,9 +430,9 @@ impl NewFuzzed for Utf8String { if string_length - idx > 0 { if mutator.gen_chance(crate::mutator::CHANCE_TO_REPEAT_ARRAY_VALUE) { let repeat_end_idx = mutator.random_range(idx, string_length); - while idx < repeat_end_idx { - output.inner.push(chr.clone()); - idx += 1; + if repeat_end_idx > idx { + output.inner.resize(repeat_end_idx, chr.clone()); + idx = repeat_end_idx; } if string_length - idx > 0 { chr = Utf8Char::new_fuzzed(mutator, None); @@ -472,9 +494,9 @@ impl NewFuzzed for AsciiString { if string_length - idx > 0 { if mutator.gen_chance(crate::mutator::CHANCE_TO_REPEAT_ARRAY_VALUE) { let repeat_end_idx = mutator.random_range(idx, string_length); - while idx < repeat_end_idx { - output.inner.push(chr.clone()); - idx += 1; + if repeat_end_idx > idx { + output.inner.resize(repeat_end_idx, chr.clone()); + idx = repeat_end_idx; } if string_length - idx > 0 { chr = AsciiChar::new_fuzzed(mutator, None); @@ -749,91 +771,135 @@ macro_rules! impl_new_fuzzed { // BUG: f32/f64 generate a number between 0/1 when no constraints are supplied, // otherwise they generate an *integer* between min/max. -impl_new_fuzzed!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64); +impl_new_fuzzed!(u8, i8, u16, i16, u32, i32, u64, i64); -impl NewFuzzed for [T; 0] -where - T: NewFuzzed + Clone, -{ - type RangeType = usize; +// Static safe float boundary limits to prevent division/calc overhead at runtime +const DEFAULT_F32_MIN: f32 = -1.692947e38; +const DEFAULT_F32_MAX: f32 = 1.692947e38; +const DEFAULT_F64_MIN: f64 = -8.94374693961351e307; +const DEFAULT_F64_MAX: f64 = 8.94374693961351e307; +impl NewFuzzed for f32 { + type RangeType = f32; + + #[inline(always)] fn new_fuzzed( - _mutator: &mut Mutator, - _constraints: Option<&Constraints>, - ) -> [T; 0] { - // no-op - [] + mutator: &mut Mutator, + constraints: Option<&Constraints>, + ) -> Self { + if mutator.gen_chance(0.10) { + return f32::select_dangerous_number(&mut mutator.rng); + } + if let Some(constraints) = constraints { + let min = constraints.min.unwrap_or(DEFAULT_F32_MIN); + let max = constraints.max.unwrap_or(DEFAULT_F32_MAX); + if min >= max { + return min; + } + return mutator.gen_weighted_range(min, max, constraints.weighted); + } + + // Unconstrained Smart Mode Strategy + let mode = mutator.rng.random_range(0..100); + match mode { + 0..=49 => { + // 50%: Float-specific standardized high-fidelity programmatic ranges + mutator.gen_weighted_range(-100000.0, 100000.0, Weighted::None) + } + 50..=74 => { + // 25%: Unadulterated bitwise float noise (exponents, extreme fractions) + f32::from_bits(mutator.rng.random::()) + } + _ => { + // 25%: Pure corner boundaries (1.0, 0.0, -1.0, MIN_POSITIVE) + [1.0, 0.0, -1.0, f32::MIN_POSITIVE] + .choose(&mut mutator.rng) + .unwrap() + .to_owned() + } + } } } -macro_rules! impl_new_fuzzed_array { - ( $($size:expr),* ) => { - $( - impl NewFuzzed for [T; $size] - where T: NewFuzzed + Clone + SerializedSize { - type RangeType = usize; - - fn new_fuzzed(mutator: &mut Mutator, constraints: Option<&Constraints>) -> [T; $size] { - let per_item_max_size: Option = constraints.and_then(|c| c.max_size.as_ref().and_then(|size| Some(*size / $size))); +impl NewFuzzed for f64 { + type RangeType = f64; - let mut output: MaybeUninit<[T; $size]> = MaybeUninit::uninit(); - let arr_ptr = output.as_mut_ptr() as *mut T; + #[inline(always)] + fn new_fuzzed( + mutator: &mut Mutator, + constraints: Option<&Constraints>, + ) -> Self { + if mutator.gen_chance(0.10) { + return f64::select_dangerous_number(&mut mutator.rng); + } + if let Some(constraints) = constraints { + let min = constraints.min.unwrap_or(DEFAULT_F64_MIN); + let max = constraints.max.unwrap_or(DEFAULT_F64_MAX); + if min >= max { + return min; + } + return mutator.gen_weighted_range(min, max, constraints.weighted); + } - let constraints = per_item_max_size.as_ref().map(|size| { - let mut constraints = Constraints::new(); - constraints.max_size(*size); - constraints.set_base_size_accounted_for(); + let mode = mutator.rng.random_range(0..100); + match mode { + 0..=49 => mutator.gen_weighted_range(-100000.0, 100000.0, Weighted::None), + 50..=74 => f64::from_bits(mutator.rng.random::()), + _ => [1.0, 0.0, -1.0, f64::MIN_POSITIVE] + .choose(&mut mutator.rng) + .unwrap() + .to_owned(), + } + } +} - constraints - }); +impl NewFuzzed for [T; SIZE] +where + T: NewFuzzed + Clone + SerializedSize, +{ + type RangeType = usize; - let mut idx = 0; - let mut element: T = T::new_fuzzed(mutator, constraints.as_ref()); + fn new_fuzzed( + mutator: &mut Mutator, + constraints: Option<&Constraints>, + ) -> [T; SIZE] { + let per_item_max_size: Option = constraints.and_then(|c| { + c.max_size + .as_ref() + .map(|size| size.checked_div(SIZE).unwrap_or(0)) + }); - while idx < $size { - unsafe { - arr_ptr.add(idx).write(element.clone()); - } + let mut output: MaybeUninit<[T; SIZE]> = MaybeUninit::uninit(); + let arr_ptr = output.as_mut_ptr() as *mut T; - idx += 1; - if $size - idx > 0 { - if mutator.gen_chance(crate::mutator::CHANCE_TO_REPEAT_ARRAY_VALUE) { - let repeat_end_idx = mutator.random_range(idx, $size); - while idx < repeat_end_idx { - unsafe { - arr_ptr.add(idx).write(element.clone()); - } - idx += 1; - } - } else { - let constraints = per_item_max_size.as_ref().map(|size| { - let mut constraints = Constraints::new(); - constraints.max_size(*size); - constraints.set_base_size_accounted_for(); + let constraints = per_item_max_size.as_ref().map(|size| { + let mut constraints = Constraints::new(); + constraints.max_size(*size); + constraints.set_base_size_accounted_for(); - constraints - }); + constraints + }); - element = T::new_fuzzed(mutator, constraints.as_ref()); - } - } - } + let mut idx = 0; + if SIZE > 0 { + let mut element: T = T::new_fuzzed(mutator, constraints.as_ref()); - unsafe { output.assume_init() } + while idx < SIZE { + unsafe { + arr_ptr.add(idx).write(element.clone()); } - } - - impl NewFuzzed for [T; $size] - where T: NewFuzzed + SerializedSize { - default type RangeType = usize; - - default fn new_fuzzed(mutator: &mut Mutator, constraints: Option<&Constraints>) -> [T; $size] { - let per_item_max_size: Option = constraints.and_then(|c| c.max_size.as_ref().and_then(|size| Some(*size / $size))); - - let mut output: MaybeUninit<[T; $size]> = MaybeUninit::uninit(); - let arr_ptr = output.as_mut_ptr() as *mut T; - for i in 0..$size { + idx += 1; + if SIZE - idx > 0 { + if mutator.gen_chance(crate::mutator::CHANCE_TO_REPEAT_ARRAY_VALUE) { + let repeat_end_idx = mutator.random_range(idx, SIZE); + while idx < repeat_end_idx { + unsafe { + arr_ptr.add(idx).write(element.clone()); + } + idx += 1; + } + } else { let constraints = per_item_max_size.as_ref().map(|size| { let mut constraints = Constraints::new(); constraints.max_size(*size); @@ -841,25 +907,54 @@ macro_rules! impl_new_fuzzed_array { constraints }); - let element = T::new_fuzzed(mutator, constraints.as_ref()); - unsafe { - arr_ptr.offset(i).write(element); - } + element = T::new_fuzzed(mutator, constraints.as_ref()); } - - unsafe { output.assume_init() } } } - )* + } + + unsafe { output.assume_init() } } } -impl_new_fuzzed_array!( - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 -); +impl NewFuzzed for [T; SIZE] +where + T: NewFuzzed + SerializedSize, +{ + default type RangeType = usize; + + default fn new_fuzzed( + mutator: &mut Mutator, + constraints: Option<&Constraints>, + ) -> [T; SIZE] { + let per_item_max_size: Option = constraints.and_then(|c| { + c.max_size + .as_ref() + .map(|size| size.checked_div(SIZE).unwrap_or(0)) + }); + + let mut output: MaybeUninit<[T; SIZE]> = MaybeUninit::uninit(); + let arr_ptr = output.as_mut_ptr() as *mut T; + + for i in 0..SIZE { + let constraints = per_item_max_size.as_ref().map(|size| { + let mut constraints = Constraints::new(); + constraints.max_size(*size); + constraints.set_base_size_accounted_for(); + + constraints + }); + let element = T::new_fuzzed(mutator, constraints.as_ref()); + + unsafe { + arr_ptr.add(i).write(element); + } + } + + unsafe { output.assume_init() } + } +} impl NewFuzzed for *mut std::ffi::c_void { type RangeType = usize; diff --git a/lain_derive/Cargo.toml b/lain_derive/Cargo.toml index 6fe4da2..eed994e 100644 --- a/lain_derive/Cargo.toml +++ b/lain_derive/Cargo.toml @@ -13,7 +13,7 @@ syn = { version = "0.15", features = ["extra-traits"] } quote = "0.6" proc-macro2 = "0.4" byteorder = "1.5.0" -log = "0.4.25" +log = "0.4.29" [lib] proc-macro = true diff --git a/lain_derive/src/internals/attr.rs b/lain_derive/src/internals/attr.rs index bc341bf..946f348 100644 --- a/lain_derive/src/internals/attr.rs +++ b/lain_derive/src/internals/attr.rs @@ -124,7 +124,7 @@ impl Container { self.min_serialized_size } - pub fn lain_path(&self) -> Cow { + pub fn lain_path(&self) -> Cow<'_, syn::Path> { Cow::Owned(parse_quote!(_lain)) } } diff --git a/lain_derive/src/lib.rs b/lain_derive/src/lib.rs index 4f3ba0f..89ecca3 100644 --- a/lain_derive/src/lib.rs +++ b/lain_derive/src/lib.rs @@ -1,5 +1,6 @@ // required for using the quote!{} macro for large invocations #![recursion_limit = "256"] +#![allow(dead_code)] extern crate proc_macro; extern crate proc_macro2; diff --git a/lain_derive/src/mutations.rs b/lain_derive/src/mutations.rs index d5561a0..0cac0ab 100644 --- a/lain_derive/src/mutations.rs +++ b/lain_derive/src/mutations.rs @@ -217,14 +217,10 @@ fn mutatable_unit_enum_visitor( let variants = variants .iter() - .filter_map(|variant| { - //if variant.attrs.ignore() { - // None - //} else { + .map(|variant| { let variant_ident = &variant.ident; weights.push(variant.attrs.weight().unwrap_or(1)); - Some(quote! {#cont_ident::#variant_ident}) - //} + quote! {#cont_ident::#variant_ident} }) .collect(); @@ -234,13 +230,10 @@ fn mutatable_unit_enum_visitor( fn mutatable_enum_visitor(variants: &[Variant], cont_ident: &syn::Ident) -> Vec { let match_arms = variants .iter() - .filter_map(|variant| { - // if variant.attrs.ignore() { - // return None; - // } - + .map(|variant| { let variant_ident = &variant.ident; let full_ident = quote! {#cont_ident::#variant_ident}; + let is_struct = variant.style == crate::internals::ast::Style::Struct; let mut field_identifiers = vec![]; let field_mutators: Vec = variant @@ -249,19 +242,35 @@ fn mutatable_enum_visitor(variants: &[Variant], cont_ident: &syn::Ident) -> Vec< .map(|field| { let (value_ident, _field_ident_string, initializer) = field_mutator(field, "__field", true); - field_identifiers.push(quote_spanned! { field.member.span() => #value_ident }); - initializer + if is_struct { + let member = &field.member; + field_identifiers.push(quote_spanned! { field.original.span() => #member: ref mut #value_ident }); + } else { + field_identifiers.push(quote_spanned! { field.original.span() => ref mut #value_ident }); + } + + if field.attrs.ignore() { + TokenStream::new() + } else { + initializer + } }) .collect(); - let match_arm = quote! { - #full_ident(#(ref mut #field_identifiers,)*) => { - #(#field_mutators)* + if is_struct { + quote! { + #full_ident { #(#field_identifiers,)* } => { + #(#field_mutators)* + } } - }; - - Some(match_arm) + } else { + quote! { + #full_ident(#(#field_identifiers,)*) => { + #(#field_mutators)* + } + } + } }) .collect(); @@ -764,10 +773,23 @@ fn new_fuzzed_enum_visitor( // using the same code for both code paths generates an error // when mixing enum variants with and without fields because // of the function call syntax + let is_struct = variant.style == crate::internals::ast::Style::Struct; let initializer = if field_initializers.is_empty() { quote! { let mut value = #full_ident; } + } else if is_struct { + let mut struct_fields = vec![]; + for (field, ident) in variant.fields.iter().zip(field_identifiers.iter()) { + let member = &field.member; + struct_fields.push(quote! { #member: #ident }); + } + quote! { + #(#field_initializers)* + + _lain::log::trace!("Initializing {}", #full_ident_string); + let mut value = #full_ident { #(#struct_fields,)* }; + } } else { quote! { #(#field_initializers)* diff --git a/lain_derive/src/serialize.rs b/lain_derive/src/serialize.rs index 7ae2253..c1d21aa 100644 --- a/lain_derive/src/serialize.rs +++ b/lain_derive/src/serialize.rs @@ -318,9 +318,23 @@ fn binary_serialize_enum_visitor( }) .collect(); - let match_arm = quote! { - #full_ident(#(ref #field_identifiers,)*) => { - #(#field_serializers)* + let is_struct = variant.style == crate::internals::ast::Style::Struct; + let match_arm = if is_struct { + let mut struct_fields = vec![]; + for (field, ident) in variant.fields.iter().zip(field_identifiers.iter()) { + let member = &field.member; + struct_fields.push(quote! { #member: ref #ident }); + } + quote! { + #full_ident { #(#struct_fields,)* } => { + #(#field_serializers)* + } + } + } else { + quote! { + #full_ident(#(ref #field_identifiers,)*) => { + #(#field_serializers)* + } } }; @@ -585,9 +599,23 @@ fn serialized_size_enum_visitor( match visitor_type { SerializedSizeVisitorType::SerializedSize | SerializedSizeVisitorType::MinEnumVariantSize => { - quote_spanned! { variant.original.span() => - #full_ident(#(ref #field_identifiers,)*) => { - 0 #(+#field_sizes)* + let is_struct = variant.style == crate::internals::ast::Style::Struct; + if is_struct { + let mut struct_fields = vec![]; + for (field, ident) in variant.fields.iter().zip(field_identifiers.iter()) { + let member = &field.member; + struct_fields.push(quote! { #member: ref #ident }); + } + quote_spanned! { variant.original.span() => + #full_ident { #(#struct_fields,)* } => { + 0 #(+#field_sizes)* + } + } + } else { + quote_spanned! { variant.original.span() => + #full_ident(#(ref #field_identifiers,)*) => { + 0 #(+#field_sizes)* + } } } } diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..18ca692 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,27 @@ +{ + "name": "lain", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "prettier": "^3.8.3" + } + }, + "node_modules/prettier": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3e5346a --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "prettier": "^3.8.3" + } +} diff --git a/testsuite/Cargo.toml b/testsuite/Cargo.toml index 5074fc2..0d134cc 100644 --- a/testsuite/Cargo.toml +++ b/testsuite/Cargo.toml @@ -11,7 +11,7 @@ lain = { path = "../lain" } # this brings in a LOT of dependencies (like 110)... maybe avoid [dev-dependencies.criterion] -version = "0.2" +version = "0.8.2" # disabling default features brings packages down from 120 to 108 (at the time of writing) # wtf man default-features = false diff --git a/testsuite/benches/benchmark_generating_fuzzed_struct.rs b/testsuite/benches/benchmark_generating_fuzzed_struct.rs index 031b2dd..9fa6c08 100644 --- a/testsuite/benches/benchmark_generating_fuzzed_struct.rs +++ b/testsuite/benches/benchmark_generating_fuzzed_struct.rs @@ -1,9 +1,10 @@ -#![feature(specialization)] +#![allow(incomplete_features)] extern crate criterion; extern crate lain; use criterion::*; +use std::hint::black_box; use lain::prelude::*; use lain::rand::SeedableRng; @@ -49,54 +50,51 @@ fn bench_new_fuzzed_1000(c: &mut Criterion) { let struct_size = std::mem::size_of::(); let function_name = format!("bench_new_fuzzed struct of size 0x{:X}", struct_size); - c.bench( - function_name.as_ref(), - Benchmark::new("fuzz", move |b| { - let mut mutator = Mutator::new(lain::rand::rngs::SmallRng::from_seed([0u8; 32])); - b.iter(|| { - let s = NestedStruct::new_fuzzed(&mut mutator, None); - black_box(s); - }); - }) - .throughput(Throughput::Bytes(struct_size as u32)), - ); + let mut group = c.benchmark_group(&function_name); + group.throughput(Throughput::Bytes(struct_size as u64)); + group.bench_function("fuzz", |b| { + let mut mutator = Mutator::new(lain::rand::rngs::SmallRng::from_seed([0u8; 32])); + b.iter(|| { + let s = NestedStruct::new_fuzzed(&mut mutator, None); + black_box(s); + }); + }); + group.finish(); } fn bench_in_place_mutation(c: &mut Criterion) { let struct_size = std::mem::size_of::(); let function_name = format!("bench_in_place_mutation struct of size 0x{:X}", struct_size); - c.bench( - function_name.as_ref(), - Benchmark::new("fuzz", move |b| { - let mut mutator = Mutator::new(lain::rand::rngs::SmallRng::from_seed([0u8; 32])); - let s = NestedStruct::new_fuzzed(&mut mutator, None); - b.iter(|| { - let mut s = s.clone(); - let state = mutator.get_corpus_state(); - s.mutate(&mut mutator, None); - black_box(&s); - mutator.set_corpus_state(state); - }); - }) - .throughput(Throughput::Bytes(struct_size as u32)), - ); + let mut group = c.benchmark_group(&function_name); + group.throughput(Throughput::Bytes(struct_size as u64)); + group.bench_function("fuzz", |b| { + let mut mutator = Mutator::new(lain::rand::rngs::SmallRng::from_seed([0u8; 32])); + let s = NestedStruct::new_fuzzed(&mut mutator, None); + b.iter(|| { + let mut s = s.clone(); + let state = mutator.get_corpus_state(); + s.mutate(&mut mutator, None); + black_box(&s); + mutator.set_corpus_state(state); + }); + }); + group.finish(); } fn bench_default_1000(c: &mut Criterion) { let struct_size = std::mem::size_of::(); let function_name = format!("bench_default_1000 struct of size 0x{:X}", struct_size); - c.bench( - function_name.as_ref(), - Benchmark::new("fuzz", move |b| { - b.iter(|| { - let s = NestedStruct::default(); - black_box(s); - }); - }) - .throughput(Throughput::Bytes(struct_size as u32)), - ); + let mut group = c.benchmark_group(&function_name); + group.throughput(Throughput::Bytes(struct_size as u64)); + group.bench_function("fuzz", |b| { + b.iter(|| { + let s = NestedStruct::default(); + black_box(s); + }); + }); + group.finish(); } criterion_group!( diff --git a/testsuite/benches/benchmark_serialization_throughput.rs b/testsuite/benches/benchmark_serialization_throughput.rs index 95cd50b..5e7507d 100644 --- a/testsuite/benches/benchmark_serialization_throughput.rs +++ b/testsuite/benches/benchmark_serialization_throughput.rs @@ -1,11 +1,10 @@ -#![feature(specialization)] +#![allow(incomplete_features)] -#[macro_use] extern crate criterion; -#[macro_use] extern crate lain; use criterion::*; +use std::hint::black_box; use lain::byteorder::BigEndian; use lain::prelude::*; @@ -73,18 +72,17 @@ fn bench_serialize_1000(c: &mut Criterion) { ..Default::default() }; - c.bench( - function_name.as_ref(), - Benchmark::new("serialize", move |b| { - let mut buffer = Vec::with_capacity(struct_size); - b.iter(|| { - parent.binary_serialize::<_, BigEndian>(&mut buffer); - black_box(&buffer); - buffer.clear(); - }); - }) - .throughput(Throughput::Bytes(struct_size as u32)), - ); + let mut group = c.benchmark_group(&function_name); + group.throughput(Throughput::Bytes(struct_size as u64)); + group.bench_function("serialize", |b| { + let mut buffer = Vec::with_capacity(struct_size); + b.iter(|| { + parent.binary_serialize::<_, BigEndian>(&mut buffer); + black_box(&buffer); + buffer.clear(); + }); + }); + group.finish(); } criterion_group!(benches, bench_serialize_1000); diff --git a/testsuite/src/lib.rs b/testsuite/src/lib.rs index ebe75fc..ebd12cb 100644 --- a/testsuite/src/lib.rs +++ b/testsuite/src/lib.rs @@ -1,4 +1,10 @@ #![feature(min_specialization)] +#![allow( + clippy::erasing_op, + clippy::identity_op, + clippy::assign_op_pattern, + dead_code +)] extern crate lain; @@ -164,12 +170,12 @@ mod test { // no assert or anything here since the concern is whether or not // the rng had bounds that cause a panic - assert!(initialized_struct.bool_field == true || initialized_struct.bool_field == false); + let _ = initialized_struct.bool_field; } #[test] fn test_ignored_fields() { - #[derive(NewFuzzed, BinarySerialize, Clone)] + #[derive(NewFuzzed, BinarySerialize, Clone, Mutatable)] struct IgnoredFieldsStruct { #[lain(ignore)] ignored: u8, @@ -177,9 +183,34 @@ mod test { let mut mutator = get_mutator(); - let initialized_struct = IgnoredFieldsStruct::new_fuzzed(&mut mutator, None); + let mut initialized_struct = IgnoredFieldsStruct::new_fuzzed(&mut mutator, None); assert_eq!(initialized_struct.ignored, 0); + + initialized_struct.mutate(&mut mutator, None); + assert_eq!(initialized_struct.ignored, 0); + } + + #[test] + fn test_ignored_fields_enum() { + #[derive(NewFuzzed, BinarySerialize, Clone, Mutatable, PartialEq, Debug)] + enum IgnoredFieldsEnum { + Variant1(#[lain(ignore)] u8), + } + + let mut mutator = get_mutator(); + + let mut initialized_enum = IgnoredFieldsEnum::new_fuzzed(&mut mutator, None); + + match &initialized_enum { + IgnoredFieldsEnum::Variant1(ignored) => assert_eq!(*ignored, 0), + } + + initialized_enum.mutate(&mut mutator, None); + + match &initialized_enum { + IgnoredFieldsEnum::Variant1(ignored) => assert_eq!(*ignored, 0), + } } #[test] @@ -440,23 +471,19 @@ mod test { #[test] fn mutating_string() { - // TODO: Fix mutation methods - - // let mut my_string = String::from("Hello, world"); - // let mut mutator = get_mutator(); + let mut my_string = String::from("Hello, world"); + let mut mutator = get_mutator(); - // my_string.mutate(&mut mutator); + my_string.mutate(&mut mutator, None); - // assert!(my_string != "Hello, world"); + assert!(my_string != "Hello, world"); } #[test] fn string_serialized_size() { - // TODO: FIx - - // let my_string = String::from("Hello, world"); + let my_string = String::from("Hello, world"); - // assert!(my_string.serialized_size() == my_string.as_bytes().len()); + assert!(my_string.serialized_size() == my_string.len()); } #[test] @@ -468,7 +495,7 @@ mod test { #[test] fn driver_can_reproduce_mutations() { - use lain::rand::Rng; + use lain::rand::RngExt; use std::sync::{Arc, RwLock}; #[derive(Debug, Default, NewFuzzed, Mutatable, Clone, PartialEq, BinarySerialize)] @@ -592,6 +619,20 @@ mod test { println!("{:?}", ascii_str); } + #[test] + fn test_large_array_mutation_support() { + #[derive(NewFuzzed, Mutatable, BinarySerialize)] + struct StructWithHugeArray { + pub huge: [u8; 128], + } + + let mut mutator = get_mutator(); + let mut instance = StructWithHugeArray::new_fuzzed(&mut mutator, None); + + assert_eq!(instance.huge.serialized_size(), 128); + instance.mutate(&mut mutator, None); + } + #[test] fn test_max_size_constraint_seems_to_work() { #[derive(NewFuzzed, BinarySerialize)] @@ -977,6 +1018,67 @@ mod test { } } + #[test] + fn test_string_mutation_resizes_eventually() { + let mut mutator = get_mutator(); + let mut s = String::from("Hello, world"); + let original_len = s.len(); + let mut grew = false; + let mut shrank = false; + + // 1% chance per mutation, running 5000 iterations should guarantee hitting both. + for _ in 0..5000 { + s.mutate(&mut mutator, None); + if s.len() > original_len { + grew = true; + } + if s.len() < original_len { + shrank = true; + } + if grew && shrank { + break; + } + } + + assert!(grew, "string never grew in size during aggressive mutation"); + assert!( + shrank, + "string never shrank in size during aggressive mutation" + ); + } + + #[test] + fn test_float_behavior() { + let mut mutator = get_mutator(); + + let mut has_nan = false; + let mut has_inf = false; + let mut has_neg_inf = false; + let mut has_regular = false; + + // 5000 iterations to confidently hit all branches of the new Smart Mode + for _ in 0..5000 { + let val = f32::new_fuzzed(&mut mutator, None); + if val.is_nan() { + has_nan = true; + } else if val == f32::INFINITY { + has_inf = true; + } else if val == f32::NEG_INFINITY { + has_neg_inf = true; + } else if val.is_normal() { + has_regular = true; + } + } + + assert!(has_nan, "Fuzzer failed to generate f32::NAN"); + assert!(has_inf, "Fuzzer failed to generate f32::INFINITY"); + assert!(has_neg_inf, "Fuzzer failed to generate f32::NEG_INFINITY"); + assert!( + has_regular, + "Fuzzer failed to generate standard normal floats" + ); + } + fn compare_slices(expected: &[u8], actual: &[u8]) { assert_eq!(actual.len(), expected.len());