From 41cd56fa549879e39e8c793d1eb7d0239a993a39 Mon Sep 17 00:00:00 2001 From: jutty Date: Sun, 5 Apr 2026 15:30:53 -0300 Subject: [PATCH 1/6] Experiment with proptest --- .gitignore | 1 + .justfile | 10 + Cargo.lock | 841 +++++++++++++++++++++++++++++ Cargo.toml | 6 +- proptest-regressions/os/debian.txt | 8 + proptest-regressions/state.txt | 7 + rust-toolchain.toml | 2 + src/os/debian.rs | 290 ++++++++-- src/state.rs | 16 + 9 files changed, 1130 insertions(+), 51 deletions(-) create mode 100644 proptest-regressions/os/debian.txt create mode 100644 proptest-regressions/state.txt create mode 100644 rust-toolchain.toml diff --git a/.gitignore b/.gitignore index ea8c4bf..cffdf3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +mutants.out diff --git a/.justfile b/.justfile index c06b4db..1068505 100644 --- a/.justfile +++ b/.justfile @@ -2,3 +2,13 @@ watch command="run" args="": DEBUG=${DEBUG:-} watchexec -c -w src -- cargo {{ command }} {{ args }} alias w := watch + +[script] +verify: + for solver in cadical bitwuzla cvc5 kissat minisat z3; do + printf '\n => trying solver %s\n\n' $solver; sleep 1 + timeout 20m \ + cargo kani --solver $solver \ + && return + done + diff --git a/Cargo.lock b/Cargo.lock index c3ccd82..404961a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,847 @@ # 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 = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "blake3" +version = "1.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures", +] + +[[package]] +name = "cc" +version = "1.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1f" + +[[package]] +name = "filetime" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" +dependencies = [ + "cfg-if", + "libc", + "libredox", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[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.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[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.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] +name = "libredox" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +dependencies = [ + "bitflags", + "libc", + "plain", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[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", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +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 = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tar" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tori" version = "0.8.0" +dependencies = [ + "blake3", + "proptest", + "serde", + "tar", + "toml", + "zstd", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[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.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-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 = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 2bcacbf..0e2cd89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,16 @@ homepage = "https://tori.jutty.dev/" documentation = "https://tori.jutty.dev/docs/" edition = "2024" -rust-version = "1.94.0" +rust-version = "1.93.0" + +[dev-dependencies] +proptest = "1.0.0" [lints.rust] nonstandard-style = "warn" future-incompatible = "warn" keyword-idents = "warn" +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(kani)'] } [lints.clippy] allow_attributes = "warn" diff --git a/proptest-regressions/os/debian.txt b/proptest-regressions/os/debian.txt new file mode 100644 index 0000000..4d5e141 --- /dev/null +++ b/proptest-regressions/os/debian.txt @@ -0,0 +1,8 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 0e5ef021926f939a8f9ec6a567268b6c3a819fcdf37876eeacb224f4af5c6e14 # shrinks to package_1 = "aAa-a-A-_aA0", package_2 = "a00aAA0-a__0", package_3 = "", package_4 = "oꙀΩ", package_5 = "aᵸΎ", package_6 = "aaꙀ῝" +cc 1ecd871d0e22c01c131bf5f011756cf5fb5e02d480488512175269af52d40c20 # shrinks to package_1 = "-", package_2 = "_", package_3 = "_", package_4 = "a\u{487}ῖ", package_5 = "aᲀὈ", package_6 = "aꙀ𐆠" diff --git a/proptest-regressions/state.txt b/proptest-regressions/state.txt new file mode 100644 index 0000000..c23822d --- /dev/null +++ b/proptest-regressions/state.txt @@ -0,0 +1,7 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 65cb746d9ef96f86b1b9571680e8b00a26b5a6c88c55c0cd57b34494c41d4073 # shrinks to s1 = "\"" diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/src/os/debian.rs b/src/os/debian.rs index 4eace3b..54707c3 100644 --- a/src/os/debian.rs +++ b/src/os/debian.rs @@ -46,6 +46,58 @@ impl Packages for Apt { "dpkg-query", &["--show", "--showformat", "${Package} ${Status}\\n"], ))?; + + let auto_set: HashSet = self + .automatic()? + .into_iter() + .map(|package| package.name().to_owned()) + .collect(); + + Ok(Apt::determine_manual(&raw_all, &auto_set)) + } + + fn automatic(&self) -> Result, pkg::Error> { + Ok(Apt::determine_auto(&read_to_string( + "/var/lib/apt/extended_states", + )?)) + } + + fn variant(&self) -> &PackagerVariant { + &self.variant + } +} + +impl Apt { + fn haul( + operation: &Operation, + packages: &[Package], + config: &Configuration, + ) -> Result { + if packages.is_empty() { + println!("Package selection is empty: Nothing to {operation}"); + return Ok(Transaction::default()); + } + + let rollback_operation = match operation { + Operation::Install => Operation::Uninstall, + Operation::Uninstall => Operation::Install, + }; + + let run_args: Vec<&str> = iter::once(operation.into()) + .chain(packages.iter().map(|p| p.into())) + .collect(); + + let rollback_args: Vec<&str> = iter::once(rollback_operation.into()) + .chain(packages.iter().map(|p| p.into())) + .collect(); + + let run = Command::new("apt", &run_args).escalate(config)?; + let rollback = Command::new("apt", &rollback_args).escalate(config)?; + let transaction_command = TransactionCommand::new(run, rollback); + Ok(Transaction::single(&transaction_command)) + } + + fn determine_manual(raw_all: &str, auto_set: &HashSet) -> Vec { let all = raw_all.lines().filter_map(|line| { let pair = line.split_once(' '); match pair { @@ -58,11 +110,6 @@ impl Packages for Apt { } }); - let auto_set: HashSet = self - .automatic()? - .into_iter() - .map(|package| package.name().to_owned()) - .collect(); let mut manual_packages: Vec = all .into_iter() .filter(|name| !auto_set.contains(name)) @@ -70,13 +117,10 @@ impl Packages for Apt { .collect(); manual_packages.sort(); - Ok(manual_packages) + manual_packages } - fn automatic(&self) -> Result, pkg::Error> { - let path = "/var/lib/apt/extended_states"; - let extended_states = read_to_string(path)?; - + fn determine_auto(extended_states: &str) -> Vec { let lines: Vec<&str> = extended_states .lines() .filter(|line| !line.is_empty()) @@ -138,50 +182,18 @@ impl Packages for Apt { continue; }; - packages.push(Package::new_with_manual(name_value, auto_value == "0")); + if auto_value == "1" { + packages.push(Package::new_with_manual(name_value, auto_value == "0")); + } else { + elog(&format!( + "Skipping: Package {name_value} has an auto-installed value different from 1" + )); + } } } packages.sort(); - Ok(packages) - } - - fn variant(&self) -> &PackagerVariant { - &self.variant - } -} - -impl Apt { - fn haul( - operation: &Operation, - packages: &[Package], - config: &Configuration, - ) -> Result { - if packages.is_empty() { - println!("Package selection is empty: Nothing to {operation}"); - return Ok(Transaction::default()); - } - - // TODO This works as it is stated and is interesting as part of the - // PoC, but doesn't really make sense to install something that wasn't - // installed in the first place as the "rollback" of a failed uninstall - let rollback_operation = match operation { - Operation::Install => Operation::Uninstall, - Operation::Uninstall => Operation::Install, - }; - - let run_args: Vec<&str> = iter::once(operation.into()) - .chain(packages.iter().map(|p| p.into())) - .collect(); - - let rollback_args: Vec<&str> = iter::once(rollback_operation.into()) - .chain(packages.iter().map(|p| p.into())) - .collect(); - - let run = Command::new("apt", &run_args).escalate(config)?; - let rollback = Command::new("apt", &rollback_args).escalate(config)?; - let transaction_command = TransactionCommand::new(run, rollback); - Ok(Transaction::single(&transaction_command)) + packages } } @@ -214,3 +226,181 @@ impl std::fmt::Display for Operation { write!(f, "{s}") } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn determine_manual_given_empty_auto_set() { + let raw_all = "avocado install ok installed\n\ + turnip install ok installed\n\ + carrot install ok installed\n\ + sunflower install ok installed\n\ + pumpkin install ok installed\n\ + squash install ok installed"; + + let auto_set: HashSet = HashSet::default(); + + let manual = Apt::determine_manual(raw_all, &auto_set); + assert_eq!( + manual, + vec![ + "avocado".into(), + "carrot".into(), + "pumpkin".into(), + "squash".into(), + "sunflower".into(), + "turnip".into(), + ] + ); + } + + #[test] + fn determine_manual_given_nonempty_auto_set() { + let raw_all = "avocado install ok installed\n\ + turnip install ok installed\n\ + carrot install ok installed\n\ + sunflower install ok installed\n\ + pumpkin install ok installed\n\ + squash install ok installed"; + + let mut auto_set: HashSet = HashSet::default(); + auto_set.insert("sunflower".to_string()); + auto_set.insert("turnip".to_string()); + + let manual = Apt::determine_manual(raw_all, &auto_set); + assert_eq!( + manual, + vec![ + "avocado".into(), + "carrot".into(), + "pumpkin".into(), + "squash".into(), + ] + ); + } + + #[test] + fn determine_manual_given_empty_raw_input() { + let raw_all = ""; + + let mut auto_set: HashSet = HashSet::default(); + auto_set.insert("sunflower".to_string()); + auto_set.insert("turnip".to_string()); + + let manual = Apt::determine_manual(raw_all, &auto_set); + assert!(manual.is_empty()); + } +} + +#[cfg(test)] +mod proptests { + use super::*; + use proptest::prelude::*; + + proptest! { + #[test] + fn determine_manual_given_empty_auto_set( + package_1 in "[a-zA-Z0-9-_]{1,24}", + package_2 in "[a-zA-Z0-9-_]{1,24}", + package_3 in "[a-zA-Z0-9-_]{1,24}", + package_4 in "[a-zA-Z0-9-_]{1,24}", + package_5 in "[a-zA-Z0-9-_]{1,24}", + package_6 in "[a-zA-Z0-9-_]{1,24}", + ) { + let raw_all = format!("{package_1} install ok installed\n\ + {package_2} install ok installed\n\ + {package_3} install ok installed\n\ + {package_4} install ok installed\n\ + {package_5} install ok installed\n\ + {package_6} install ok installed"); + + let auto_set: HashSet = HashSet::default(); + + let manual = Apt::determine_manual(&raw_all, &auto_set); + + let mut actual: Vec = manual + .iter().map(|p| p.name().to_string()).collect(); + actual.sort(); + let mut expected = vec![ + package_1, + package_2, + package_3, + package_4, + package_5, + package_6, + ]; + expected.sort(); + assert_eq!(actual, expected); + } + } + + proptest! { + #[test] + fn determine_manual_given_nonempty_auto_set( + package_1 in "[a-zA-Z0-9-_]{1,24}", + package_2 in "[a-zA-Z0-9-_]{1,24}", + package_3 in "[a-zA-Z0-9-_]{1,24}", + package_4 in "[a-z]{1,8}\\p{Cyrillic}{1,8}\\p{Greek}{1,24}", + package_5 in "[a-z]{1,8}\\p{Cyrillic}{1,8}\\p{Greek}{1,24}", + package_6 in "[a-z]{1,8}\\p{Cyrillic}{1,8}\\p{Greek}{1,24}", + ) { + let mut args = [&package_1, + &package_2, + &package_3, + &package_4, + &package_5, + &package_6 + ]; + let (_, dupes) = &args.partition_dedup(); + prop_assume!(dupes.is_empty()); + + let raw_all = format!("{package_1} install ok installed\n\ + {package_2} install ok installed\n\ + {package_3} install ok installed\n\ + {package_4} install ok installed\n\ + {package_5} install ok installed\n\ + {package_6} install ok installed"); + + println!("raw_all: <{raw_all}>"); + + let mut auto_set: HashSet = HashSet::default(); + auto_set.insert(package_1); + auto_set.insert(package_3); + auto_set.insert(package_5); + println!("auto_set: <{auto_set:#?}>"); + + let manual = Apt::determine_manual(&raw_all, &auto_set); + println!("manual: <{manual:#?}>"); + + let mut actual: Vec = manual + .iter().map(|p| p.name().to_string()).collect(); + actual.sort(); + let mut expected = vec![package_2, package_4, package_6]; + expected.sort(); + assert_eq!(actual, expected); + } + } + + proptest! { + #[test] + fn determine_manual_given_empty_raw_input( + auto_package_1 in "[a-zA-Z0-9-_]{1,24}", + auto_package_2 in "[a-zA-Z0-9-_]{1,24}", + auto_package_3 in "", + auto_package_4 in "[a-z]{1,4}\\p{Cyrillic}{1,4}\\p{Greek}{1,24}", + ) { + let raw_all = ""; + + let mut auto_set: HashSet = HashSet::default(); + auto_set.insert(auto_package_1); + auto_set.insert(auto_package_2); + auto_set.insert(auto_package_3); + auto_set.insert(auto_package_4); + + let manual = Apt::determine_manual(raw_all, &auto_set); + assert!(manual.is_empty()); + } + } +} diff --git a/src/state.rs b/src/state.rs index 430f769..ae245e2 100644 --- a/src/state.rs +++ b/src/state.rs @@ -87,3 +87,19 @@ fn strip_quotes(original: &str) -> String { }; no_suffix.to_string() } + +#[cfg(test)] +mod tests { + use super::*; + use proptest::prelude::*; + + proptest! { + #[test] + fn strip_quotes_props( + s1 in "[\\PC]{1,24}" + ) { + let stripped = strip_quotes(&format!(r#""{s1}""#)); + assert_eq!(stripped, s1); + } + } +} From 89d1634a639d3eada12d4b9f36e0a98d72de6a6b Mon Sep 17 00:00:00 2001 From: jutty Date: Sun, 5 Apr 2026 19:46:31 -0300 Subject: [PATCH 2/6] Add test harness for IO serial tests --- .justfile | 32 ++++++++++- Cargo.toml | 6 +++ src/conf.rs | 72 +++++++++++++++++++++++-- src/dev.rs | 2 + src/{ => dev}/log.rs | 0 src/dev/test.rs | 124 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 +- src/main.rs | 14 ++--- src/os/debian.rs | 8 +-- src/run.rs | 2 +- src/run/executor.rs | 2 +- src/run/expeditor.rs | 2 +- src/run/teller.rs | 2 +- src/state.rs | 2 +- 14 files changed, 250 insertions(+), 23 deletions(-) create mode 100644 src/dev.rs rename src/{ => dev}/log.rs (100%) create mode 100644 src/dev/test.rs diff --git a/.justfile b/.justfile index 1068505..10b7698 100644 --- a/.justfile +++ b/.justfile @@ -1,5 +1,5 @@ -watch command="run" args="": - DEBUG=${DEBUG:-} watchexec -c -w src -- cargo {{ command }} {{ args }} +watch *args: + watchexec -c -w src -w Cargo.toml -- just {{ args }} alias w := watch @@ -12,3 +12,31 @@ verify: && return done +[env("PROPTEST_CASES", "16640")] +test pattern="": + cargo test {{ pattern}} --timings -- --test-threads=1 'serial_tests::' + cargo test {{ pattern}} --timings --bin tori + cargo test {{ pattern}} --timings --doc + cargo test {{ pattern}} --timings --lib -- --skip 'serial_tests::' + + + +mutate: + cargo mutants --iterate \ + -E ' bool' \ + --output target/mutants + + +cover: + cargo llvm-cov --no-report + cargo llvm-cov report --html + cargo llvm-cov report \ + | tail -1 | awk \ + '{ print " [ Regions:", $4, "• Functions:", $7, "• Lines:", $10, "]" }' + +cover-open: + cargo llvm-cov report --open + diff --git a/Cargo.toml b/Cargo.toml index 0e2cd89..6974154 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -170,3 +170,9 @@ used_underscore_items = "warn" useless_let_if_seq = "warn" zero_sized_map_values = "warn" zombie_processes = "deny" + +[profile.test.package.proptest] +opt-level = 3 + +[profile.test.package.rand_chacha] +opt-level = 3 diff --git a/src/conf.rs b/src/conf.rs index b336348..65c3c3f 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -5,24 +5,28 @@ use std::{ }; use crate::{ - log::{self, elog}, + dev::{log::elog}, run::Command, }; pub fn load() -> Result { - log::elog("Loading configuration"); + elog("Loading configuration"); let mut candidate = Configuration::default(); let root = get_root(); + elog(&format!("Reading 'tori.conf' from: {root:?}")); let contents = fs::read_to_string(root.join("tori.conf"))?; + elog(&format!("Read configuration: {contents:?}")); let map: HashMap = contents .lines() .filter_map(|line| line.split_once('=')) - .map(|(k, v)| (k.to_owned(), v.to_owned())) + .map(|(k, v)| (k.trim().to_owned(), v.trim().to_owned())) .collect(); + elog(&format!("Assembled configuration map: {map:#?}")); + if let Some(su_command) = map.get("su_command") { let wraps = map.get("su_command_wraps").is_some_and(|v| v == "true"); candidate.su_command = parse_su_command(su_command, wraps)?; @@ -36,6 +40,7 @@ pub fn load() -> Result { } } + elog(&format!("Assembled configuration candidate: {candidate:?}")); Ok(candidate) } @@ -183,9 +188,10 @@ impl Default for SuCommand { } } +#[derive(Debug)] pub struct Error { - message: String, - kind: ErrorKind, + pub message: String, + pub kind: ErrorKind, } impl Error { @@ -221,6 +227,7 @@ impl From for Error { } } +#[derive(Debug)] pub enum ErrorKind { CommandNotInPath, VarError, @@ -242,3 +249,58 @@ impl std::fmt::Display for ErrorKind { write!(f, "{s}") } } + +#[cfg(test)] +#[expect(clippy::panic_in_result_fn, //clippy::unwrap_in_result +)] +mod serial_tests { + use std::{env, fs, os::unix::fs::PermissionsExt as _, io::{Write as _}}; + use super::*; + use crate::{dev::test::{Directories, Error}}; + + #[test] + fn failed_config_read() -> Result<(), Error> { + let dirs = Directories::setup("failed_config_read")?; + + fs::write(&dirs.conf, [1, 0, 1])?; + let mut permissions = fs::metadata(&dirs.conf)?.permissions(); + permissions.set_mode(0o200); + fs::set_permissions(&dirs.conf, permissions)?; + + let new_permissions = fs::metadata(&dirs.conf)?.permissions(); + assert_eq!(new_permissions.mode() & 0o777, 0o200); + + let error = load().unwrap_err(); + + assert!(matches!(&error.kind, ErrorKind::IO)); + Ok(()) + } + + #[test] + fn prefer_system() -> Result<(), Error> { + let dirs = Directories::setup("prefer_system")?; + + let mut conf = fs::File::create_new(&dirs.conf)?; + println!("conf: {conf:#?}"); + println!("XDG_CONFIG_DIR: {:#?}", env::var("XDG_CONFIG_DIR")); + + let conf_root_contents = dirs.conf_root.read_dir(); + println!("conf_root_contents: {conf_root_contents:#?}"); + + let write_result = conf.write_all(b"merge_strategy = prefer system\n"); + println!("write_result: {write_result:#?}"); + conf.sync_all()?; + + let mut perms = fs::metadata(&dirs.conf)?.permissions(); + println!("perms: {perms:#?}"); + perms.set_mode(0o664); + conf.set_permissions(perms)?; + + let configuration = load()?; + println!("configuration: {configuration:#?}"); + + assert!(matches!(configuration.merge_strategy, MergeStrategy::PreferSystem)); + + Ok(()) + } +} diff --git a/src/dev.rs b/src/dev.rs new file mode 100644 index 0000000..c4eb55e --- /dev/null +++ b/src/dev.rs @@ -0,0 +1,2 @@ +pub mod log; +pub mod test; diff --git a/src/log.rs b/src/dev/log.rs similarity index 100% rename from src/log.rs rename to src/dev/log.rs diff --git a/src/dev/test.rs b/src/dev/test.rs new file mode 100644 index 0000000..320e2c9 --- /dev/null +++ b/src/dev/test.rs @@ -0,0 +1,124 @@ +use std::{env, fs, io, path::PathBuf}; + +use crate::{dev::log::elog, conf}; + +#[derive(Debug)] +pub struct Directories { + pub original: PathBuf, + pub tube: PathBuf, + pub conf: PathBuf, + pub conf_root: PathBuf, +} + +impl Directories { + /// Sets up self-cleaning original, temporary and 'templates' directories. + /// + /// # Errors + /// May return Error when: + /// - Current directory does not exist or lacking permissions + /// - Several I/O possibilities from directory creation failures + /// - Several I/O possibilities from working directory changing failures + pub fn setup(dir_name: &str) -> Result { + let original = env::current_dir()?; + let tube = original.join(format!("target/tubes/{dir_name}")); + let xdg_conf = tube.join(".config"); + let conf_root = xdg_conf.join("tori"); + let conf = conf_root.join("tori.conf"); + + drop(fs::remove_dir_all(&tube)); + + if let Err(error) = fs::create_dir_all(&conf_root) { + return Err(Error::with_io( + "Failed configuration root directory creation", + error, + )) + } + + if let Err(error) = env::set_current_dir(&tube) { + return Err(Error::with_io("Failed current directory change", error)) + } + + unsafe { env::set_var("XDG_CONFIG_DIR", &xdg_conf); } + + Ok(Directories { + original, + tube, + conf, + conf_root, + }) + } +} + +impl Drop for Directories { + fn drop(&mut self) { + if let Err(error) = std::env::set_current_dir(&self.original) { + elog(&format!("Couldn't reset to original directory: {error}")); + } + if let Err(error) = std::fs::remove_dir_all(&self.tube) { + elog(&format!("Couldn't cleanup tube directory: {error}")); + } + } +} + +#[derive(Debug)] +pub struct Error { + pub message: String, + pub inner: Option, +} + +#[derive(Debug, Default)] +pub struct InnerErrors { + pub io: Option, + pub conf: Option, +} + +impl Error { + fn with_io(message: &str, inner: io::Error) -> Error { + Error { + message: String::from(message), + inner: Some(InnerErrors { io: Some(inner), conf: None }), + } + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let mut message = self.message.clone(); + + if let Some(inner) = &self.inner { + message = format!("{message}\n{inner:#?}"); + } + + write!(f, "{message}") + } +} + +impl From for Error { + fn from(string: String) -> Error { + Error { + message: string, + inner: None, + } + } +} + +impl From<&str> for Error { + fn from(str: &str) -> Error { Error::from(String::from(str)) } +} + +impl From for Error { + fn from(inner: io::Error) -> Error { + let mut error = Error::from(inner.to_string()); + error.inner = Some(InnerErrors { io: Some(inner), ..InnerErrors::default() }); + error + } +} + +impl From for Error { + fn from(conf_error: conf::Error) -> Error { + Error { + message: conf_error.message.clone(), + inner: Some(InnerErrors { conf: Some(conf_error), io: None }), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 11eea8a..8c53dc9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,10 @@ +#![feature(slice_partition_dedup)] +#![allow(unused_features)] + pub mod conf; pub mod state; pub mod os; pub mod run; -pub mod log; +pub mod dev; diff --git a/src/main.rs b/src/main.rs index ee53102..42dc5a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ -use tori::{conf, log, run, state}; +use tori::{conf, dev::log::elog, run, state}; fn main() -> std::process::ExitCode { - log::elog(&format!("tori {}", env!("CARGO_PKG_VERSION"))); + elog(&format!("tori {}", env!("CARGO_PKG_VERSION"))); let configuration = match conf::load() { Ok(c) => c, Err(error) => { @@ -9,13 +9,13 @@ fn main() -> std::process::ExitCode { return 1.into(); } }; - log::elog(&format!("Configuration: {configuration:#?}")); + elog(&format!("Configuration: {configuration:#?}")); let order = run::teller::parse(std::env::args()); - log::elog(&format!("Order: {order:#?}")); + elog(&format!("Order: {order:#?}")); let state = state::setup(configuration, &[order]); - log::elog(&format!("State: {state:#?}")); - let result = run::expeditor::fulfill(&state); - log::elog(&format!("Filled Order: {result:#?}")); + elog(&format!("State: {state:#?}")); + let result = run::expeditor::expedite(&state); + elog(&format!("Filled Order: {result:#?}")); if result.is_ok() { 0.into() } else { 1.into() } } diff --git a/src/os/debian.rs b/src/os/debian.rs index 54707c3..fcce23b 100644 --- a/src/os/debian.rs +++ b/src/os/debian.rs @@ -2,7 +2,7 @@ use std::{collections::HashSet, fs::read_to_string, iter}; use crate::{ conf::Configuration, - log::elog, + dev::log::elog, os::{ Kind, OperatingSystem, pkg::{self, Package, PackagerVariant, Packages}, @@ -269,9 +269,11 @@ mod tests { auto_set.insert("sunflower".to_string()); auto_set.insert("turnip".to_string()); - let manual = Apt::determine_manual(raw_all, &auto_set); + let mut manual = Apt::determine_manual(raw_all, &auto_set); + let (uniques, dupes) = manual.as_mut_slice().partition_dedup(); + assert!(dupes.is_empty()); assert_eq!( - manual, + uniques, vec![ "avocado".into(), "carrot".into(), diff --git a/src/run.rs b/src/run.rs index dcfe4ba..1b92f9f 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1,4 +1,4 @@ -use crate::{conf::Configuration, log::elog}; +use crate::{conf::Configuration, dev::log::elog}; pub mod executor; pub mod expeditor; diff --git a/src/run/executor.rs b/src/run/executor.rs index 4b0a165..31ff0a0 100644 --- a/src/run/executor.rs +++ b/src/run/executor.rs @@ -1,7 +1,7 @@ use std::process; use crate::{ - log::elog, + dev::log::elog, os::pkg::Package, run::{Command, Transaction, TransactionCommandStatus}, }; diff --git a/src/run/expeditor.rs b/src/run/expeditor.rs index f1f31a7..a6b386c 100644 --- a/src/run/expeditor.rs +++ b/src/run/expeditor.rs @@ -4,7 +4,7 @@ use crate::{ state::State, }; -pub fn fulfill(state: &State) -> Result<(), Error> { +pub fn expedite(state: &State) -> Result<(), Error> { let orders = state.orders(); for order in orders { diff --git a/src/run/teller.rs b/src/run/teller.rs index b2dc51d..82fe419 100644 --- a/src/run/teller.rs +++ b/src/run/teller.rs @@ -1,5 +1,5 @@ use crate::{ - log::elog, + dev::log::elog, run::{Order, Task, TaskKind}, }; use std::{env, path::PathBuf}; diff --git a/src/state.rs b/src/state.rs index ae245e2..0ad5c63 100644 --- a/src/state.rs +++ b/src/state.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use crate::{ conf::Configuration, - log::elog, + dev::log::elog, os::OperatingSystem, run::{Command, Order, executor::read}, }; From eac1ffbda6059b8a44e981c814aefcf0c4eefae6 Mon Sep 17 00:00:00 2001 From: jutty Date: Thu, 23 Apr 2026 16:04:45 -0300 Subject: [PATCH 3/6] Add cargo vet and deny checks --- .justfile | 32 +- Cargo.lock | 288 ++---------- Cargo.toml | 17 +- deny.toml | 242 ++++++++++ supply-chain/audits.toml | 151 +++++++ supply-chain/config.toml | 128 ++++++ supply-chain/imports.lock | 919 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 1510 insertions(+), 267 deletions(-) create mode 100644 deny.toml create mode 100644 supply-chain/audits.toml create mode 100644 supply-chain/config.toml create mode 100644 supply-chain/imports.lock diff --git a/.justfile b/.justfile index 10b7698..263f37b 100644 --- a/.justfile +++ b/.justfile @@ -3,15 +3,6 @@ watch *args: alias w := watch -[script] -verify: - for solver in cadical bitwuzla cvc5 kissat minisat z3; do - printf '\n => trying solver %s\n\n' $solver; sleep 1 - timeout 20m \ - cargo kani --solver $solver \ - && return - done - [env("PROPTEST_CASES", "16640")] test pattern="": cargo test {{ pattern}} --timings -- --test-threads=1 'serial_tests::' @@ -19,16 +10,23 @@ test pattern="": cargo test {{ pattern}} --timings --doc cargo test {{ pattern}} --timings --lib -- --skip 'serial_tests::' - +alias t:= test mutate: + -just mutate-single -- --test-threads=1 serial_tests:: + -just mutate-single -- --skip serial_tests:: + +alias m := mutate + +[private] +mutate-single *cargo_test_args: cargo mutants --iterate \ -E ' bool' \ - --output target/mutants - + --output target/mutants \ + -- {{ cargo_test_args }} cover: cargo llvm-cov --no-report @@ -37,6 +35,16 @@ cover: | tail -1 | awk \ '{ print " [ Regions:", $4, "• Functions:", $7, "• Lines:", $10, "]" }' +alias c := cover + cover-open: cargo llvm-cov report --open +vet: + cargo vet + +deny: + cargo deny check + +check: && test vet deny + cargo check diff --git a/Cargo.lock b/Cargo.lock index 404961a..929137f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,6 @@ # 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 = "arrayref" version = "0.3.9" @@ -85,6 +79,15 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" +[[package]] +name = "convert_case" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cpufeatures" version = "0.3.0" @@ -139,12 +142,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[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.4" @@ -153,50 +150,16 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi 5.3.0", + "r-efi", "wasip2", ] -[[package]] -name = "getrandom" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" -dependencies = [ - "cfg-if", - "libc", - "r-efi 6.0.0", - "wasip2", - "wasip3", -] - -[[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.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -[[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.13.1" @@ -204,33 +167,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", - "hashbrown 0.16.1", - "serde", - "serde_core", + "hashbrown", ] -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - [[package]] name = "jobserver" version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.4", + "getrandom", "libc", ] -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libc" version = "0.2.184" @@ -255,18 +204,6 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "memchr" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - [[package]] name = "num-traits" version = "0.2.19" @@ -303,16 +240,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - [[package]] name = "proc-macro2" version = "1.0.106" @@ -332,6 +259,7 @@ dependencies = [ "bit-vec", "bitflags", "num-traits", + "proptest-macro", "rand", "rand_chacha", "rand_xorshift", @@ -341,6 +269,29 @@ dependencies = [ "unarray", ] +[[package]] +name = "proptest-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c57924a81864dddafba92e1bf92f9bf82f97096c44489548a60e888e1547549b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proptest-macro" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efaa288b896cb2b345da7b7f2110ab19e51565b83495b56fcec98a62f8b1f33e" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -362,12 +313,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - [[package]] name = "rand" version = "0.9.2" @@ -394,7 +339,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.4", + "getrandom", ] [[package]] @@ -446,12 +391,6 @@ dependencies = [ "wait-timeout", ] -[[package]] -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" @@ -481,19 +420,6 @@ dependencies = [ "syn", ] -[[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 = "serde_spanned" version = "1.1.1" @@ -538,7 +464,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom", "once_cell", "rustix", "windows-sys", @@ -589,6 +515,7 @@ version = "0.8.0" dependencies = [ "blake3", "proptest", + "proptest-derive", "serde", "tar", "toml", @@ -608,10 +535,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] -name = "unicode-xid" -version = "0.2.6" +name = "unicode-segmentation" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "wait-timeout" @@ -631,49 +558,6 @@ 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" @@ -700,88 +584,6 @@ name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] [[package]] name = "xattr" @@ -813,12 +615,6 @@ dependencies = [ "syn", ] -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" - [[package]] name = "zstd" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index 6974154..8df261b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,14 +11,19 @@ documentation = "https://tori.jutty.dev/docs/" edition = "2024" rust-version = "1.93.0" -[dev-dependencies] -proptest = "1.0.0" +[dependencies] +blake3 = "1.8.4" +proptest = { version = "1.11.0", features = ["attr-macro", "default", "proptest-macro"] } +proptest-derive = "0.8.0" +serde = "1.0.228" +tar = "0.4.45" +toml = "1.1.2" +zstd = "0.13.3" [lints.rust] nonstandard-style = "warn" future-incompatible = "warn" keyword-idents = "warn" -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(kani)'] } [lints.clippy] allow_attributes = "warn" @@ -170,9 +175,3 @@ used_underscore_items = "warn" useless_let_if_seq = "warn" zero_sized_map_values = "warn" zombie_processes = "deny" - -[profile.test.package.proptest] -opt-level = 3 - -[profile.test.package.rand_chacha] -opt-level = 3 diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..1f884a9 --- /dev/null +++ b/deny.toml @@ -0,0 +1,242 @@ +# This template contains all of the possible sections and their default values + +# Note that all fields that take a lint level have these possible values: +# * deny - An error will be produced and the check will fail +# * warn - A warning will be produced, but the check will not fail +# * allow - No warning or error will be produced, though in some cases a note +# will be + +# The values provided in this template are the default values that will be used +# when any section or field is not specified in your own configuration + +# Root options + +# The graph table configures how the dependency graph is constructed and thus +# which crates the checks are performed against +[graph] +# If 1 or more target triples (and optionally, target_features) are specified, +# only the specified targets will be checked when running `cargo deny check`. +# This means, if a particular package is only ever used as a target specific +# dependency, such as, for example, the `nix` crate only being used via the +# `target_family = "unix"` configuration, that only having windows targets in +# this list would mean the nix crate, as well as any of its exclusive +# dependencies not shared by any other crates, would be ignored, as the target +# list here is effectively saying which targets you are building for. +targets = [ + # The triple can be any string, but only the target triples built in to + # rustc (as of 1.40) can be checked against actual config expressions + #"x86_64-unknown-linux-musl", + # You can also specify which target_features you promise are enabled for a + # particular target. target_features are currently not validated against + # the actual valid features supported by the target architecture. + #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, +] +# When creating the dependency graph used as the source of truth when checks are +# executed, this field can be used to prune crates from the graph, removing them +# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate +# is pruned from the graph, all of its dependencies will also be pruned unless +# they are connected to another crate in the graph that hasn't been pruned, +# so it should be used with care. The identifiers are [Package ID Specifications] +# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html) +#exclude = [] +# If true, metadata will be collected with `--all-features`. Note that this can't +# be toggled off if true, if you want to conditionally enable `--all-features` it +# is recommended to pass `--all-features` on the cmd line instead +all-features = false +# If true, metadata will be collected with `--no-default-features`. The same +# caveat with `all-features` applies +no-default-features = false +# If set, these feature will be enabled when collecting metadata. If `--features` +# is specified on the cmd line they will take precedence over this option. +#features = [] + +# The output table provides options for how/if diagnostics are outputted +[output] +# When outputting inclusion graphs in diagnostics that include features, this +# option can be used to specify the depth at which feature edges will be added. +# This option is included since the graphs can be quite large and the addition +# of features from the crate(s) to all of the graph roots can be far too verbose. +# This option can be overridden via `--feature-depth` on the cmd line +feature-depth = 1 + +# This section is considered when running `cargo deny check advisories` +# More documentation for the advisories section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html +[advisories] +# The path where the advisory databases are cloned/fetched into +#db-path = "$CARGO_HOME/advisory-dbs" +# The url(s) of the advisory databases to use +#db-urls = ["https://github.com/rustsec/advisory-db"] +# A list of advisory IDs to ignore. Note that ignored advisories will still +# output a note when they are encountered. +ignore = [ + #"RUSTSEC-0000-0000", + #{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" }, + #"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish + #{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" }, +] +# If this is true, then cargo deny will use the git executable to fetch advisory database. +# If this is false, then it uses a built-in git library. +# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support. +# See Git Authentication for more information about setting up git authentication. +#git-fetch-with-cli = true + +# This section is considered when running `cargo deny check licenses` +# More documentation for the licenses section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html +[licenses] +# List of explicitly allowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +allow = [ + "MIT", + "BSD-2-Clause", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "GPL-3.0-only", + "Unicode-3.0", +] +# The confidence threshold for detecting a license from license text. +# The higher the value, the more closely the license text must be to the +# canonical license text of a valid SPDX license file. +# [possible values: any between 0.0 and 1.0]. +confidence-threshold = 0.8 +# Allow 1 or more licenses on a per-crate basis, so that particular licenses +# aren't accepted for every possible crate as with the normal allow list +exceptions = [ + # Each entry is the crate and version constraint, and its specific allow + # list + #{ allow = ["Zlib"], crate = "adler32" }, +] + +# Some crates don't have (easily) machine readable licensing information, +# adding a clarification entry for it allows you to manually specify the +# licensing information +#[[licenses.clarify]] +# The package spec the clarification applies to +#crate = "ring" +# The SPDX expression for the license requirements of the crate +#expression = "MIT AND ISC AND OpenSSL" +# One or more files in the crate's source used as the "source of truth" for +# the license expression. If the contents match, the clarification will be used +# when running the license check, otherwise the clarification will be ignored +# and the crate will be checked normally, which may produce warnings or errors +# depending on the rest of your configuration +#license-files = [ +# Each entry is a crate relative path, and the (opaque) hash of its contents +#{ path = "LICENSE", hash = 0xbd0eed23 } +#] + +[licenses.private] +# If true, ignores workspace crates that aren't published, or are only +# published to private registries. +# To see how to mark a crate as unpublished (to the official registry), +# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. +ignore = false +# One or more private registries that you might publish crates to, if a crate +# is only published to private registries, and ignore is true, the crate will +# not have its license(s) checked +registries = [ + #"https://sekretz.com/registry +] + +# This section is considered when running `cargo deny check bans`. +# More documentation about the 'bans' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html +[bans] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "warn" +# Lint level for when a crate version requirement is `*` +wildcards = "allow" +# The graph highlighting used when creating dotgraphs for crates +# with multiple versions +# * lowest-version - The path to the lowest versioned duplicate is highlighted +# * simplest-path - The path to the version with the fewest edges is highlighted +# * all - Both lowest-version and simplest-path are used +highlight = "all" +# The default lint level for `default` features for crates that are members of +# the workspace that is being checked. This can be overridden by allowing/denying +# `default` on a crate-by-crate basis if desired. +workspace-default-features = "allow" +# The default lint level for `default` features for external crates that are not +# members of the workspace. This can be overridden by allowing/denying `default` +# on a crate-by-crate basis if desired. +external-default-features = "allow" +# List of crates that are allowed. Use with care! +allow = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" }, +] +# If true, workspace members are automatically allowed even when using deny-by-default +# This is useful for organizations that want to deny all external dependencies by default +# but allow their own workspace crates without having to explicitly list them +allow-workspace = false +# List of crates to deny +deny = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" }, + # Wrapper crates can optionally be specified to allow the crate when it + # is a direct dependency of the otherwise banned crate + #{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] }, +] + +# List of features to allow/deny +# Each entry the name of a crate and a version range. If version is +# not specified, all versions will be matched. +#[[bans.features]] +#crate = "reqwest" +# Features to not allow +#deny = ["json"] +# Features to allow +#allow = [ +# "rustls", +# "__rustls", +# "__tls", +# "hyper-rustls", +# "rustls", +# "rustls-pemfile", +# "rustls-tls-webpki-roots", +# "tokio-rustls", +# "webpki-roots", +#] +# If true, the allowed features must exactly match the enabled feature set. If +# this is set there is no point setting `deny` +#exact = true + +# Certain crates/versions that will be skipped when doing duplicate detection. +skip = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" }, +] +# Similarly to `skip` allows you to skip certain crates during duplicate +# detection. Unlike skip, it also includes the entire tree of transitive +# dependencies starting at the specified crate, up to a certain depth, which is +# by default infinite. +skip-tree = [ + #"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies + #{ crate = "ansi_term@0.11.0", depth = 20 }, +] + +# This section is considered when running `cargo deny check sources`. +# More documentation about the 'sources' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html +[sources] +# Lint level for what to happen when a crate from a crate registry that is not +# in the allow list is encountered +unknown-registry = "warn" +# Lint level for what to happen when a crate from a git repository that is not +# in the allow list is encountered +unknown-git = "warn" +# List of URLs for allowed crate registries. Defaults to the crates.io index +# if not specified. If it is specified but empty, no registries are allowed. +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# List of URLs for allowed Git repositories +allow-git = [] + +[sources.allow-org] +# github.com organizations to allow git sources for +github = [] +# gitlab.com organizations to allow git sources for +gitlab = [] +# bitbucket.org organizations to allow git sources for +bitbucket = [] diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml new file mode 100644 index 0000000..c154184 --- /dev/null +++ b/supply-chain/audits.toml @@ -0,0 +1,151 @@ + +# cargo-vet audits file + +[[audits.bitflags]] +who = "jutty " +criteria = "safe-to-deploy" +delta = "2.10.0 -> 2.11.0" + +[[trusted.cc]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2022-10-29" +end = "2027-04-12" + +[[trusted.filetime]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-04-23" +end = "2027-04-12" + +[[trusted.find-msvc-tools]] +criteria = "safe-to-deploy" +user-id = 539 # Josh Stone (cuviper) +start = "2025-08-29" +end = "2027-04-12" + +[[trusted.hashbrown]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2025-04-30" +end = "2027-04-12" + +[[trusted.indexmap]] +criteria = "safe-to-deploy" +user-id = 539 # Josh Stone (cuviper) +start = "2020-01-15" +end = "2027-04-12" + +[[trusted.jobserver]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2024-07-23" +end = "2027-04-12" + +[[trusted.libc]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2024-08-15" +end = "2027-04-12" + +[[trusted.linux-raw-sys]] +criteria = "safe-to-deploy" +user-id = 6825 # Dan Gohman (sunfishcode) +start = "2021-06-12" +end = "2027-04-12" + +[[trusted.proc-macro2]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-04-23" +end = "2027-04-12" + +[[trusted.quote]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-04-09" +end = "2027-04-12" + +[[trusted.regex-syntax]] +criteria = "safe-to-deploy" +user-id = 189 # Andrew Gallant (BurntSushi) +start = "2019-03-30" +end = "2027-04-12" + +[[trusted.rustix]] +criteria = "safe-to-deploy" +user-id = 6825 # Dan Gohman (sunfishcode) +start = "2021-10-29" +end = "2027-04-12" + +[[trusted.serde_spanned]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2023-01-20" +end = "2027-04-12" + +[[trusted.syn]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-01" +end = "2027-04-12" + +[[trusted.tar]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-03-04" +end = "2027-04-12" + +[[trusted.toml]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2022-12-14" +end = "2027-04-12" + +[[trusted.toml_datetime]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2022-10-21" +end = "2027-04-12" + +[[trusted.toml_parser]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2025-07-08" +end = "2027-04-12" + +[[trusted.toml_writer]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2025-07-08" +end = "2027-04-12" + +[[trusted.unicode-ident]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2021-10-02" +end = "2027-04-12" + +[[trusted.unicode-segmentation]] +criteria = "safe-to-deploy" +user-id = 1139 # Manish Goregaokar (Manishearth) +start = "2019-05-15" +end = "2027-04-12" + +[[trusted.wait-timeout]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2025-02-03" +end = "2027-04-12" + +[[trusted.windows-sys]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2021-11-15" +end = "2027-04-12" + +[[trusted.winnow]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2023-02-22" +end = "2027-04-12" diff --git a/supply-chain/config.toml b/supply-chain/config.toml new file mode 100644 index 0000000..9a9c8a8 --- /dev/null +++ b/supply-chain/config.toml @@ -0,0 +1,128 @@ + +# cargo-vet config file + +[cargo-vet] +version = "0.10" + +[imports.bytecode-alliance] +url = "https://raw.githubusercontent.com/bytecodealliance/wasmtime/main/supply-chain/audits.toml" + +[imports.google] +url = "https://raw.githubusercontent.com/google/supply-chain/main/audits.toml" + +[imports.isrg] +url = "https://raw.githubusercontent.com/divviup/libprio-rs/main/supply-chain/audits.toml" + +[imports.mozilla] +url = "https://raw.githubusercontent.com/mozilla/supply-chain/main/audits.toml" + +[imports.zcash] +url = "https://raw.githubusercontent.com/zcash/rust-ecosystem/main/supply-chain/audits.toml" + +[[exemptions.blake3]] +version = "1.8.4" +criteria = "safe-to-deploy" + +[[exemptions.cc]] +version = "1.2.59" +criteria = "safe-to-deploy" + +[[exemptions.constant_time_eq]] +version = "0.4.2" +criteria = "safe-to-deploy" + +[[exemptions.convert_case]] +version = "0.11.0" +criteria = "safe-to-deploy" + +[[exemptions.cpufeatures]] +version = "0.3.0" +criteria = "safe-to-deploy" + +[[exemptions.fastrand]] +version = "2.4.0" +criteria = "safe-to-deploy" + +[[exemptions.find-msvc-tools]] +version = "0.1.9" +criteria = "safe-to-deploy" + +[[exemptions.getrandom]] +version = "0.3.4" +criteria = "safe-to-deploy" + +[[exemptions.libredox]] +version = "0.1.15" +criteria = "safe-to-deploy" + +[[exemptions.once_cell]] +version = "1.21.4" +criteria = "safe-to-deploy" + +[[exemptions.plain]] +version = "0.2.3" +criteria = "safe-to-deploy" + +[[exemptions.ppv-lite86]] +version = "0.2.21" +criteria = "safe-to-deploy" + +[[exemptions.proptest]] +version = "1.11.0" +criteria = "safe-to-deploy" + +[[exemptions.proptest-derive]] +version = "0.8.0" +criteria = "safe-to-deploy" + +[[exemptions.proptest-macro]] +version = "0.5.0" +criteria = "safe-to-deploy" + +[[exemptions.quick-error]] +version = "1.2.3" +criteria = "safe-to-deploy" + +[[exemptions.r-efi]] +version = "5.3.0" +criteria = "safe-to-deploy" + +[[exemptions.rand_xorshift]] +version = "0.4.0" +criteria = "safe-to-deploy" + +[[exemptions.redox_syscall]] +version = "0.7.3" +criteria = "safe-to-deploy" + +[[exemptions.rusty-fork]] +version = "0.3.1" +criteria = "safe-to-deploy" + +[[exemptions.tempfile]] +version = "3.27.0" +criteria = "safe-to-deploy" + +[[exemptions.unarray]] +version = "0.1.4" +criteria = "safe-to-deploy" + +[[exemptions.zerocopy]] +version = "0.8.48" +criteria = "safe-to-deploy" + +[[exemptions.zerocopy-derive]] +version = "0.8.48" +criteria = "safe-to-deploy" + +[[exemptions.zstd]] +version = "0.13.3" +criteria = "safe-to-deploy" + +[[exemptions.zstd-safe]] +version = "7.2.4" +criteria = "safe-to-deploy" + +[[exemptions.zstd-sys]] +version = "2.0.16+zstd.1.5.7" +criteria = "safe-to-deploy" diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock new file mode 100644 index 0000000..4eb601f --- /dev/null +++ b/supply-chain/imports.lock @@ -0,0 +1,919 @@ + +# cargo-vet imports lock + +[[publisher.filetime]] +version = "0.2.27" +when = "2026-01-18" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[publisher.hashbrown]] +version = "0.16.1" +when = "2025-11-20" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.indexmap]] +version = "2.13.1" +when = "2026-04-02" +user-id = 539 +user-login = "cuviper" +user-name = "Josh Stone" + +[[publisher.jobserver]] +version = "0.1.34" +when = "2025-08-23" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.libc]] +version = "0.2.184" +when = "2026-04-01" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.linux-raw-sys]] +version = "0.12.1" +when = "2025-12-23" +user-id = 6825 +user-login = "sunfishcode" +user-name = "Dan Gohman" + +[[publisher.proc-macro2]] +version = "1.0.106" +when = "2026-01-21" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.quote]] +version = "1.0.45" +when = "2026-03-03" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.regex-syntax]] +version = "0.8.10" +when = "2026-02-24" +user-id = 189 +user-login = "BurntSushi" +user-name = "Andrew Gallant" + +[[publisher.rustix]] +version = "1.1.4" +when = "2026-02-22" +user-id = 6825 +user-login = "sunfishcode" +user-name = "Dan Gohman" + +[[publisher.serde_spanned]] +version = "1.1.1" +when = "2026-03-31" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.syn]] +version = "2.0.117" +when = "2026-02-20" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.tar]] +version = "0.4.45" +when = "2026-03-19" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[publisher.toml]] +version = "1.1.2+spec-1.1.0" +when = "2026-04-01" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.toml_datetime]] +version = "1.1.1+spec-1.1.0" +when = "2026-03-31" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.toml_parser]] +version = "1.1.2+spec-1.1.0" +when = "2026-04-01" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.toml_writer]] +version = "1.1.1+spec-1.1.0" +when = "2026-03-31" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.unicode-ident]] +version = "1.0.24" +when = "2026-02-16" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.unicode-segmentation]] +version = "1.13.2" +when = "2026-03-26" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.wait-timeout]] +version = "0.2.1" +when = "2025-02-03" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[publisher.wasip2]] +version = "1.0.2+wasi-0.2.9" +when = "2026-01-15" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[publisher.windows-sys]] +version = "0.61.2" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.winnow]] +version = "1.0.1" +when = "2026-03-30" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.wit-bindgen]] +version = "0.51.0" +when = "2026-01-12" +trusted-publisher = "github:bytecodealliance/wit-bindgen" + +[[audits.bytecode-alliance.wildcard-audits.wasip2]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2025-08-10" +end = "2026-08-21" +notes = """ +This is a Bytecode Alliance authored crate. +""" + +[[audits.bytecode-alliance.wildcard-audits.wit-bindgen]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +trusted-publisher = "github:bytecodealliance/wit-bindgen" +start = "2025-08-13" +end = "2027-01-08" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.audits.arrayref]] +who = "Nick Fitzgerald " +criteria = "safe-to-deploy" +version = "0.3.6" +notes = """ +Unsafe code, but its logic looks good to me. Necessary given what it is +doing. Well tested, has quickchecks. +""" + +[[audits.bytecode-alliance.audits.arrayvec]] +who = "Nick Fitzgerald " +criteria = "safe-to-deploy" +version = "0.7.2" +notes = """ +Well documented invariants, good assertions for those invariants in unsafe code, +and tested with MIRI to boot. LGTM. +""" + +[[audits.bytecode-alliance.audits.bitflags]] +who = "Jamey Sharp " +criteria = "safe-to-deploy" +delta = "2.1.0 -> 2.2.1" +notes = """ +This version adds unsafe impls of traits from the bytemuck crate when built +with that library enabled, but I believe the impls satisfy the documented +safety requirements for bytemuck. The other changes are minor. +""" + +[[audits.bytecode-alliance.audits.bitflags]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "2.3.2 -> 2.3.3" +notes = """ +Nothing outside the realm of what one would expect from a bitflags generator, +all as expected. +""" + +[[audits.bytecode-alliance.audits.bitflags]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "2.4.1 -> 2.6.0" +notes = """ +Changes in how macros are invoked and various bits and pieces of macro-fu. +Otherwise no major changes and nothing dealing with `unsafe`. +""" + +[[audits.bytecode-alliance.audits.bitflags]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "2.7.0 -> 2.9.4" +notes = "Tweaks to the macro, nothing out of order." + +[[audits.bytecode-alliance.audits.cfg-if]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "1.0.0" +notes = "I am the author of this crate." + +[[audits.bytecode-alliance.audits.errno]] +who = "Dan Gohman " +criteria = "safe-to-deploy" +version = "0.3.0" +notes = "This crate uses libc and windows-sys APIs to get and set the raw OS error value." + +[[audits.bytecode-alliance.audits.errno]] +who = "Dan Gohman " +criteria = "safe-to-deploy" +delta = "0.3.0 -> 0.3.1" +notes = "Just a dependency version bump and a bug fix for redox" + +[[audits.bytecode-alliance.audits.errno]] +who = "Dan Gohman " +criteria = "safe-to-deploy" +delta = "0.3.9 -> 0.3.10" + +[[audits.bytecode-alliance.audits.num-traits]] +who = "Andrew Brown " +criteria = "safe-to-deploy" +version = "0.2.19" +notes = "As advertised: a numeric library. The only `unsafe` is from some float-to-int conversions, which seems expected." + +[[audits.bytecode-alliance.audits.pkg-config]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.3.25" +notes = "This crate shells out to the pkg-config executable, but it appears to sanitize inputs reasonably." + +[[audits.bytecode-alliance.audits.pkg-config]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.3.26 -> 0.3.29" +notes = """ +No `unsafe` additions or anything outside of the purview of the crate in this +change. +""" + +[[audits.bytecode-alliance.audits.pkg-config]] +who = "Chris Fallin " +criteria = "safe-to-deploy" +delta = "0.3.29 -> 0.3.32" + +[[audits.bytecode-alliance.audits.shlex]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "1.1.0" +notes = "Only minor `unsafe` code blocks which look valid and otherwise does what it says on the tin." + +[[audits.bytecode-alliance.audits.xattr]] +who = "Andrew Brown " +criteria = "safe-to-deploy" +version = "1.2.0" +notes = "This crate contains `unsafe` calls to libc `extattr_*` functions as one would expect from the crate's purpose." + +[[audits.bytecode-alliance.audits.xattr]] +who = "Andrew Brown " +criteria = "safe-to-deploy" +delta = "1.2.0 -> 1.3.1" +notes = "Minor changes to MacOS-specific code." + +[[audits.bytecode-alliance.audits.xattr]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "1.3.1 -> 1.6.1" +notes = "Refactorings and minor updates, nothing out of place." + +[[audits.google.audits.autocfg]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "1.4.0" +notes = "Contains no unsafe" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.bitflags]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "1.3.2" +notes = """ +Security review of earlier versions of the crate can be found at +(Google-internal, sorry): go/image-crate-chromium-security-review + +The crate exposes a function marked as `unsafe`, but doesn't use any +`unsafe` blocks (except for tests of the single `unsafe` function). I +think this justifies marking this crate as `ub-risk-1`. + +Additional review comments can be found at https://crrev.com/c/4723145/31 +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.equivalent]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "1.0.1" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.equivalent]] +who = "Jonathan Hao " +criteria = "safe-to-deploy" +delta = "1.0.1 -> 1.0.2" +notes = "No changes to any .rs files or Rust code." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rand]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "0.8.5" +notes = """ +For more detailed unsafe review notes please see https://crrev.com/c/6362797 +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "1.0.197" +notes = """ +Grepped for `-i cipher`, `-i crypto`, `'\bfs\b'`, `'\bnet\b'`, `'\bunsafe\b'`. + +There were some hits for `net`, but they were related to serialization and +not actually opening any connections or anything like that. + +There were 2 hits of `unsafe` when grepping: +* In `fn as_str` in `impl Buf` +* In `fn serialize` in `impl Serialize for net::Ipv4Addr` + +Unsafe review comments can be found in https://crrev.com/c/5350573/2 (this +review also covered `serde_json_lenient`). + +Version 1.0.130 of the crate has been added to Chromium in +https://crrev.com/c/3265545. The CL description contains a link to a +(Google-internal, sorry) document with a mini security review. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "1.0.197 -> 1.0.198" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "danakj " +criteria = "safe-to-deploy" +delta = "1.0.198 -> 1.0.201" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "1.0.201 -> 1.0.202" +notes = "Trivial changes" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.202 -> 1.0.203" +notes = "s/doc_cfg/docsrs/ + tuple_impls/tuple_impl_body-related changes" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Adrian Taylor " +criteria = "safe-to-deploy" +delta = "1.0.203 -> 1.0.204" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.204 -> 1.0.207" +notes = "The small change in `src/private/ser.rs` should have no impact on `ub-risk-2`." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.207 -> 1.0.209" +notes = """ +The delta carries fairly small changes in `src/private/de.rs` and +`src/private/ser.rs` (see https://crrev.com/c/5812194/2..5). AFAICT the +delta has no impact on the `unsafe`, `from_utf8_unchecked`-related parts +of the crate (in `src/de/format.rs` and `src/ser/impls.rs`). +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Adrian Taylor " +criteria = "safe-to-deploy" +delta = "1.0.209 -> 1.0.210" +notes = "Almost no new code - just feature rearrangement" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Liza Burakova " +criteria = "safe-to-deploy" +delta = "1.0.210 -> 1.0.213" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "1.0.213 -> 1.0.214" +notes = "No unsafe, no crypto" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Adrian Taylor " +criteria = "safe-to-deploy" +delta = "1.0.214 -> 1.0.215" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.215 -> 1.0.216" +notes = "The delta makes minor changes in `build.rs` - switching to the `?` syntax sugar." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "1.0.216 -> 1.0.217" +notes = "Minimal changes, nothing unsafe" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Daniel Cheng " +criteria = "safe-to-deploy" +delta = "1.0.217 -> 1.0.218" +notes = "No changes outside comments and documentation." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.218 -> 1.0.219" +notes = "Just allowing `clippy::elidable_lifetime_names`." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "1.0.197" +notes = 'Grepped for "unsafe", "crypt", "cipher", "fs", "net" - there were no hits' +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "danakj " +criteria = "safe-to-deploy" +delta = "1.0.197 -> 1.0.201" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "1.0.201 -> 1.0.202" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.202 -> 1.0.203" +notes = 'Grepped for "unsafe", "crypt", "cipher", "fs", "net" - there were no hits' +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Adrian Taylor " +criteria = "safe-to-deploy" +delta = "1.0.203 -> 1.0.204" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.204 -> 1.0.207" +notes = 'Grepped for \"unsafe\", \"crypt\", \"cipher\", \"fs\", \"net\" - there were no hits' +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.207 -> 1.0.209" +notes = ''' +There are no code changes in this delta - see https://crrev.com/c/5812194/2..5 + +I've neverthless also grepped for `-i cipher`, `-i crypto`, `\bfs\b`, +`\bnet\b`, and `\bunsafe\b`. There were no hits. +''' +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Adrian Taylor " +criteria = "safe-to-deploy" +delta = "1.0.209 -> 1.0.210" +notes = "Almost no new code - just feature rearrangement" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Liza Burakova " +criteria = "safe-to-deploy" +delta = "1.0.210 -> 1.0.213" +notes = "Grepped for 'unsafe', 'crypt', 'cipher', 'fs', 'net' - there were no hits" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "1.0.213 -> 1.0.214" +notes = "No changes to unsafe, no crypto" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Adrian Taylor " +criteria = "safe-to-deploy" +delta = "1.0.214 -> 1.0.215" +notes = "Minor changes should not impact UB risk" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.215 -> 1.0.216" +notes = "The delta adds `#[automatically_derived]` in a few places. Still no `unsafe`." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "1.0.216 -> 1.0.217" +notes = "No changes" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Daniel Cheng " +criteria = "safe-to-deploy" +delta = "1.0.217 -> 1.0.218" +notes = "No changes outside comments and documentation." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.serde_derive]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.0.218 -> 1.0.219" +notes = "Minor changes (clippy tweaks, using `mem::take` instead of `mem::replace`)." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.isrg.audits.cfg-if]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "1.0.0 -> 1.0.1" + +[[audits.isrg.audits.cfg-if]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "1.0.1 -> 1.0.3" + +[[audits.isrg.audits.cfg-if]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "1.0.3 -> 1.0.4" + +[[audits.isrg.audits.rand]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.8.5 -> 0.9.1" + +[[audits.isrg.audits.rand]] +who = "Tim Geoghegan " +criteria = "safe-to-deploy" +delta = "0.9.1 -> 0.9.2" + +[[audits.isrg.audits.rand_chacha]] +who = "David Cook " +criteria = "safe-to-deploy" +version = "0.3.1" + +[[audits.isrg.audits.rand_chacha]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.3.1 -> 0.9.0" + +[[audits.isrg.audits.rand_core]] +who = "David Cook " +criteria = "safe-to-deploy" +version = "0.6.3" + +[[audits.isrg.audits.rand_core]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.6.4 -> 0.9.3" + +[[audits.isrg.audits.rand_core]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "0.9.3 -> 0.9.5" + +[[audits.isrg.audits.serde]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "1.0.219 -> 1.0.224" + +[[audits.isrg.audits.serde]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "1.0.224 -> 1.0.225" + +[[audits.isrg.audits.serde]] +who = "Tim Geoghegan " +criteria = "safe-to-deploy" +delta = "1.0.225 -> 1.0.226" + +[[audits.isrg.audits.serde_core]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +version = "1.0.224" + +[[audits.isrg.audits.serde_core]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "1.0.224 -> 1.0.225" + +[[audits.isrg.audits.serde_core]] +who = "Tim Geoghegan " +criteria = "safe-to-deploy" +delta = "1.0.225 -> 1.0.226" + +[[audits.isrg.audits.serde_derive]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "1.0.219 -> 1.0.224" + +[[audits.isrg.audits.serde_derive]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "1.0.224 -> 1.0.225" + +[[audits.isrg.audits.serde_derive]] +who = "Tim Geoghegan " +criteria = "safe-to-deploy" +delta = "1.0.225 -> 1.0.226" + +[[audits.mozilla.audits.arrayvec]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +delta = "0.7.2 -> 0.7.6" +notes = "Manually verified new unsafe pointer arithmetic." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-set]] +who = "Aria Beingessner " +criteria = "safe-to-deploy" +version = "0.5.2" +notes = "Another crate I own via contain-rs that is ancient and maintenance mode, no known issues." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-set]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.5.2 -> 0.5.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-set]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.5.3 -> 0.6.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-set]] +who = "Jim Blandy " +criteria = "safe-to-deploy" +delta = "0.6.0 -> 0.8.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-vec]] +who = "Aria Beingessner " +criteria = "safe-to-deploy" +version = "0.6.3" +notes = "Another crate I own via contain-rs that is ancient and in maintenance mode but otherwise perfectly fine." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-vec]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.6.3 -> 0.7.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-vec]] +who = "Jim Blandy " +criteria = "safe-to-deploy" +delta = "0.7.0 -> 0.8.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bitflags]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +delta = "1.3.2 -> 2.0.2" +notes = "Removal of some unsafe code/methods. No changes to externals, just some refactoring (mostly internal)." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bitflags]] +who = "Nicolas Silva " +criteria = "safe-to-deploy" +delta = "2.0.2 -> 2.1.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bitflags]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "2.2.1 -> 2.3.2" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bitflags]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "2.3.3 -> 2.4.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bitflags]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "2.4.0 -> 2.4.1" +notes = "Only allowing new clippy lints" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.bitflags]] +who = [ + "Teodor Tanasoaia ", + "Erich Gubler ", +] +criteria = "safe-to-deploy" +delta = "2.6.0 -> 2.7.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bitflags]] +who = "Benjamin VanderSloot " +criteria = "safe-to-deploy" +delta = "2.9.4 -> 2.10.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.errno]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.3.1 -> 0.3.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.fnv]] +who = "Bobby Holley " +criteria = "safe-to-deploy" +version = "1.0.7" +notes = "Simple hasher implementation with no unsafe code." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.pkg-config]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.3.25 -> 0.3.26" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.rand_core]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.6.3 -> 0.6.4" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "1.0.226 -> 1.0.227" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "1.0.227 -> 1.0.228" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde_core]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "1.0.226 -> 1.0.227" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde_core]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "1.0.227 -> 1.0.228" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde_derive]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "1.0.226 -> 1.0.227" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde_derive]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "1.0.227 -> 1.0.228" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.shlex]] +who = "Max Inden " +criteria = "safe-to-deploy" +delta = "1.1.0 -> 1.3.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.windows-link]] +who = "Mark Hammond " +criteria = "safe-to-deploy" +version = "0.1.1" +notes = "A microsoft crate allowing unsafe calls to windows apis." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.windows-link]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "0.1.1 -> 0.2.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.zcash.audits.arrayref]] +who = "Daira-Emma Hopwood " +criteria = "safe-to-deploy" +delta = "0.3.6 -> 0.3.8" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.arrayref]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.8 -> 0.3.9" +notes = "Changes to `unsafe` lines are to make some existing `unsafe fn`s `const`." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.autocfg]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.4.0 -> 1.5.0" +notes = "Filesystem change is to remove the generated LLVM IR output file after probing." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.3 -> 0.3.8" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Daira-Emma Hopwood " +criteria = "safe-to-deploy" +delta = "0.3.8 -> 0.3.9" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.10 -> 0.3.11" +notes = "The `__errno` location for vxworks and cygwin looks correct from a quick search." +aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.11 -> 0.3.13" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.13 -> 0.3.14" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.windows-link]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.2.0 -> 0.2.1" +notes = "No code changes at all." +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" From 0fbc65e24b542e51f9cb52462509647c9357abdb Mon Sep 17 00:00:00 2001 From: jutty Date: Thu, 23 Apr 2026 16:06:11 -0300 Subject: [PATCH 4/6] Add location to log function --- src/dev/log.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dev/log.rs b/src/dev/log.rs index a9d5720..f5310d5 100644 --- a/src/dev/log.rs +++ b/src/dev/log.rs @@ -1,7 +1,9 @@ +#[track_caller] pub fn elog(message: &str) { if let Ok(debug) = std::env::var("DEBUG") && !debug.is_empty() { - eprintln!(" [log] {message}"); + let location = std::panic::Location::caller(); + eprintln!(" !debug [{location}] {message}"); } } From 3efdf18f39f574fed1b980e6cf93a4bc87bf7a21 Mon Sep 17 00:00:00 2001 From: jutty Date: Thu, 23 Apr 2026 16:06:32 -0300 Subject: [PATCH 5/6] Move temporary test directories to RAM --- src/dev/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dev/test.rs b/src/dev/test.rs index 320e2c9..55bfd14 100644 --- a/src/dev/test.rs +++ b/src/dev/test.rs @@ -20,7 +20,7 @@ impl Directories { /// - Several I/O possibilities from working directory changing failures pub fn setup(dir_name: &str) -> Result { let original = env::current_dir()?; - let tube = original.join(format!("target/tubes/{dir_name}")); + let tube = original.join(format!("/tmp/tubes/{dir_name}")); let xdg_conf = tube.join(".config"); let conf_root = xdg_conf.join("tori"); let conf = conf_root.join("tori.conf"); From 18cba43f7f26f3ffec9c526df0bf6535058d5f5b Mon Sep 17 00:00:00 2001 From: jutty Date: Thu, 23 Apr 2026 16:09:22 -0300 Subject: [PATCH 6/6] Improve su_command parsing --- proptest-regressions/conf.txt | 9 ++ src/conf.rs | 186 +++++++++++++++++++++++++++++----- src/dev/test.rs | 40 ++++++-- 3 files changed, 199 insertions(+), 36 deletions(-) create mode 100644 proptest-regressions/conf.txt diff --git a/proptest-regressions/conf.txt b/proptest-regressions/conf.txt new file mode 100644 index 0000000..cf40de9 --- /dev/null +++ b/proptest-regressions/conf.txt @@ -0,0 +1,9 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 74b674162f67e0a42dccabd5bde0a39fa18f11dfaecb6971995502f93a07fa41 # shrinks to SuCommandWrapsIsReadFromConfigArgs = SuCommandWrapsIsReadFromConfigArgs { value: "" } +cc 00d0bfa64cfe51948411edf0dd89386ccc18f9644800172acf487b5373839cf8 # shrinks to ConfigurationParsesArgs = ConfigurationParsesArgs { raw: Raw { su_command: Some(""), su_command_wraps: None, merge_strategy: None } } +cc 7b467bb66998ed166bac12dfb9bc8980f02d852d65ae337e3fac7a5d93f03c9a # shrinks to ConfigurationParsesArgs = ConfigurationParsesArgs { raw: Raw { su_command: None, su_command_wraps: None, merge_strategy: Some("") } } diff --git a/src/conf.rs b/src/conf.rs index 65c3c3f..a01ad76 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -1,23 +1,29 @@ use std::{ collections::HashMap, fs::{self, DirEntry}, + os::unix::fs::PermissionsExt as _, path::PathBuf, }; -use crate::{ - dev::{log::elog}, - run::Command, -}; +use proptest_derive::Arbitrary; + +use crate::{dev::log::elog, run::Command}; + +#[derive(Debug, Arbitrary)] +struct Raw { + su_command: Option, + su_command_wraps: Option, + merge_strategy: Option, +} pub fn load() -> Result { elog("Loading configuration"); - let mut candidate = Configuration::default(); - let root = get_root(); elog(&format!("Reading 'tori.conf' from: {root:?}")); + let contents = fs::read_to_string(root.join("tori.conf"))?; - elog(&format!("Read configuration: {contents:?}")); + elog(&format!("Read configuration file: {contents:?}")); let map: HashMap = contents .lines() @@ -27,24 +33,49 @@ pub fn load() -> Result { elog(&format!("Assembled configuration map: {map:#?}")); - if let Some(su_command) = map.get("su_command") { - let wraps = map.get("su_command_wraps").is_some_and(|v| v == "true"); - candidate.su_command = parse_su_command(su_command, wraps)?; - } + let raw = Raw { + su_command: map.get("su_command").cloned(), + su_command_wraps: map.get("su_command_wraps").cloned(), + merge_strategy: map.get("merge_strategy").cloned(), + }; - if let Some(merge_strategy) = map.get("merge_strategy") { - candidate.merge_strategy = match merge_strategy.as_str() { - "prefer configuration" => MergeStrategy::PreferConfig, - "prefer system" => MergeStrategy::PreferSystem, - _ => MergeStrategy::default(), + elog(&format!("Read raw configuration: {raw:?}")); + Ok(parse(&raw)) +} + +fn parse(raw: &Raw) -> Configuration { + let default = Configuration::default(); + let mut candidate = default; + + if let Some(su_command_value) = &raw.su_command { + let wraps_value = match &raw.su_command_wraps { + Some(wraps) => wraps == "true", + None => false, + }; + + match parse_su_command(su_command_value, wraps_value) { + Ok(s) => candidate.su_command = s, + Err(error) => println!("Failed parsing su_comand configuration value: {error}"), } } - elog(&format!("Assembled configuration candidate: {candidate:?}")); - Ok(candidate) + if let Some(merge_strategy) = &raw.merge_strategy { + candidate.merge_strategy = match merge_strategy.as_str() { + "prefer configuration" => MergeStrategy::PreferConfig, + "prefer system" => MergeStrategy::PreferSystem, + any => { + println!("Unrecognized merge strategy: {any}"); + MergeStrategy::default() + } + } + } + + elog(&format!("Parsed configuration candidate: {candidate:?}")); + candidate } fn parse_su_command(config_value: &str, wraps: bool) -> Result { + // TODO this is a horrible way to split because it will unquote everything let split: Vec<&str> = config_value.split(' ').filter(|s| !s.is_empty()).collect(); let Some((base, args)) = split.split_first() else { @@ -54,13 +85,29 @@ fn parse_su_command(config_value: &str, wraps: bool) -> Result )); }; - let Ok(resolved_base) = resolve_command(base) else { - return Err(Error::new( - "su_command does not resolve to a command in PATH", - ErrorKind::CommandNotInPath, - )); + let resolved_base = if PathBuf::from(base).is_absolute() { + PathBuf::from(base) + } else { + resolve_command(base)? }; + if resolved_base.is_file() + && let Ok(metadata) = resolved_base.metadata() + { + let mode = metadata.permissions().mode(); + if mode & 0o111 == 0 { + return Err(Error::new( + "su_command path does not point to an executable file", + ErrorKind::WrongPermissions, + )); + } + } else { + return Err(Error::new( + "su_command path does not point to a file or its metadata is unreadable", + ErrorKind::MetadataUnreadable, + )); + } + let Some(resolved_base_str) = resolved_base.to_str() else { return Err(Error::new( "su_command path contains invalid characters (expected UTF-8)", @@ -227,11 +274,20 @@ impl From for Error { } } +#[cfg(test)] +impl From for proptest::test_runner::TestCaseError { + fn from(error: Error) -> proptest::test_runner::TestCaseError { + proptest::test_runner::TestCaseError::fail(format!("{}: {}", error.kind, error.message)) + } +} + #[derive(Debug)] pub enum ErrorKind { CommandNotInPath, VarError, MalformedConfigLine, + MetadataUnreadable, + WrongPermissions, UTF8, IO, } @@ -243,6 +299,8 @@ impl std::fmt::Display for ErrorKind { VarError => "Environment variable error", CommandNotInPath => "Command not in PATH", MalformedConfigLine => "Malformed configuration line", + MetadataUnreadable => "Metadata unreadable", + WrongPermissions => "Wrong permissions", UTF8 => "Invalid characters could not be decoded (expected UTF-8)", IO => "Input/Output error", }; @@ -250,13 +308,15 @@ impl std::fmt::Display for ErrorKind { } } +// TODO review this test #[cfg(test)] -#[expect(clippy::panic_in_result_fn, //clippy::unwrap_in_result -)] +#[expect(clippy::panic_in_result_fn)] mod serial_tests { - use std::{env, fs, os::unix::fs::PermissionsExt as _, io::{Write as _}}; + use proptest::property_test; + use std::{env, fs, io::Write as _, os::unix::fs::PermissionsExt as _}; + use super::*; - use crate::{dev::test::{Directories, Error}}; + use crate::dev::test::{Directories, Error}; #[test] fn failed_config_read() -> Result<(), Error> { @@ -299,8 +359,78 @@ mod serial_tests { let configuration = load()?; println!("configuration: {configuration:#?}"); - assert!(matches!(configuration.merge_strategy, MergeStrategy::PreferSystem)); + assert!(matches!( + configuration.merge_strategy, + MergeStrategy::PreferSystem + )); Ok(()) } + + #[property_test] + fn su_command_wrap_is_read_from_config(value: String) -> Result<(), Error> { + let dirs = Directories::setup("su_command_wraps_is_read_from_config")?; + + let mut conf = fs::File::create_new(&dirs.conf)?; + conf.write_all(format!("su_command_wraps = {value}").as_bytes())?; + conf.sync_all()?; + + let configuration = load()?; + let default = Configuration::default(); + + if value == "false" { + assert!(!configuration.su_command.wraps); + } else if configuration.su_command == default.su_command { + assert!(configuration.su_command.wraps); + } else { + assert!(value == "true"); + } + + Ok(()) + } + + #[property_test] + fn configuration_parses(raw: Raw) { + let parsed = parse(&raw); + let default = Configuration::default(); + + if let Some(su_command_value) = raw.su_command { + // these duplicated extractions are also in the tested + // code, this shpuld be in Command::from(&str) + let (base, args_opt) = match su_command_value.split_once(' ') { + Some((b, a)) => (b, Some(a)), + None => (su_command_value.as_str(), None), + }; + + let args = match args_opt { + Some(a) => vec![a], + None => vec![], + }; + + // this could also be a method of Command + if let Ok(resolved_su_command) = resolve_command(base) { + assert_eq!(parsed.su_command.command.base, resolved_su_command); + } else { + assert_eq!(parsed.su_command, default.su_command); + } + } else { + assert_eq!(parsed.su_command, default.su_command); + } + + if let Some(merge_strategy) = &raw.merge_strategy { + use MergeStrategy::*; + + // i guess this is fine (could be a match?) but it makes + // you think about how tests duplicate tautologies + if merge_strategy == "prefer system" { + assert!(matches!(parsed.merge_strategy, PreferSystem)); + } else if merge_strategy == "prefer configuration" { + assert!(matches!(parsed.merge_strategy, PreferConfig)); + } else { + assert!(matches!(parsed.merge_strategy, Interactive)); + } + } + + // TODO match raw.su_command_wraps {} + } } diff --git a/src/dev/test.rs b/src/dev/test.rs index 55bfd14..af6d452 100644 --- a/src/dev/test.rs +++ b/src/dev/test.rs @@ -1,6 +1,6 @@ use std::{env, fs, io, path::PathBuf}; -use crate::{dev::log::elog, conf}; +use crate::{conf, dev::log::elog}; #[derive(Debug)] pub struct Directories { @@ -31,14 +31,16 @@ impl Directories { return Err(Error::with_io( "Failed configuration root directory creation", error, - )) + )); } if let Err(error) = env::set_current_dir(&tube) { - return Err(Error::with_io("Failed current directory change", error)) + return Err(Error::with_io("Failed current directory change", error)); } - unsafe { env::set_var("XDG_CONFIG_DIR", &xdg_conf); } + unsafe { + env::set_var("XDG_CONFIG_DIR", &xdg_conf); + } Ok(Directories { original, @@ -76,7 +78,10 @@ impl Error { fn with_io(message: &str, inner: io::Error) -> Error { Error { message: String::from(message), - inner: Some(InnerErrors { io: Some(inner), conf: None }), + inner: Some(InnerErrors { + io: Some(inner), + conf: None, + }), } } } @@ -103,13 +108,18 @@ impl From for Error { } impl From<&str> for Error { - fn from(str: &str) -> Error { Error::from(String::from(str)) } + fn from(str: &str) -> Error { + Error::from(String::from(str)) + } } impl From for Error { fn from(inner: io::Error) -> Error { let mut error = Error::from(inner.to_string()); - error.inner = Some(InnerErrors { io: Some(inner), ..InnerErrors::default() }); + error.inner = Some(InnerErrors { + io: Some(inner), + ..InnerErrors::default() + }); error } } @@ -118,7 +128,21 @@ impl From for Error { fn from(conf_error: conf::Error) -> Error { Error { message: conf_error.message.clone(), - inner: Some(InnerErrors { conf: Some(conf_error), io: None }), + inner: Some(InnerErrors { + conf: Some(conf_error), + io: None, + }), } } } + +#[cfg(test)] +impl From for proptest::test_runner::TestCaseError { + fn from(error: Error) -> proptest::test_runner::TestCaseError { + proptest::test_runner::TestCaseError::fail(if let Some(inner) = error.inner { + format!("{}: {:#?}", error.message, inner) + } else { + error.message + }) + } +}