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..263f37b 100644 --- a/.justfile +++ b/.justfile @@ -1,4 +1,50 @@ -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 + +[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::' + +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 \ + -- {{ cargo_test_args }} + +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, "]" }' + +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 c3ccd82..929137f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,643 @@ # It is not intended for manual editing. version = 4 +[[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 = "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" +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 = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "indexmap" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom", + "libc", +] + +[[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 = "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 = "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", + "proptest-macro", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "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" +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 = "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", +] + +[[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 = "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_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", + "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", + "proptest-derive", + "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-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[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 = "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" + +[[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 = "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..8df261b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +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" + +[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" 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/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/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/conf.rs b/src/conf.rs index b336348..a01ad76 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -1,45 +1,81 @@ use std::{ collections::HashMap, fs::{self, DirEntry}, + os::unix::fs::PermissionsExt as _, path::PathBuf, }; -use crate::{ - log::{self, 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 { - log::elog("Loading configuration"); - - let mut candidate = Configuration::default(); + elog("Loading configuration"); 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 file: {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(); - 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)?; - } + elog(&format!("Assembled configuration map: {map:#?}")); - 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(), + 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(), + }; + + 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}"), } } - 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 { @@ -49,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)", @@ -183,9 +235,10 @@ impl Default for SuCommand { } } +#[derive(Debug)] pub struct Error { - message: String, - kind: ErrorKind, + pub message: String, + pub kind: ErrorKind, } impl Error { @@ -221,10 +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, } @@ -236,9 +299,138 @@ 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", }; write!(f, "{s}") } } + +// TODO review this test +#[cfg(test)] +#[expect(clippy::panic_in_result_fn)] +mod serial_tests { + use proptest::property_test; + use std::{env, fs, io::Write as _, os::unix::fs::PermissionsExt 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(()) + } + + #[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.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/dev/log.rs b/src/dev/log.rs new file mode 100644 index 0000000..f5310d5 --- /dev/null +++ b/src/dev/log.rs @@ -0,0 +1,9 @@ +#[track_caller] +pub fn elog(message: &str) { + if let Ok(debug) = std::env::var("DEBUG") + && !debug.is_empty() + { + let location = std::panic::Location::caller(); + eprintln!(" !debug [{location}] {message}"); + } +} diff --git a/src/dev/test.rs b/src/dev/test.rs new file mode 100644 index 0000000..af6d452 --- /dev/null +++ b/src/dev/test.rs @@ -0,0 +1,148 @@ +use std::{env, fs, io, path::PathBuf}; + +use crate::{conf, dev::log::elog}; + +#[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!("/tmp/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, + }), + } + } +} + +#[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 + }) + } +} 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/log.rs b/src/log.rs deleted file mode 100644 index a9d5720..0000000 --- a/src/log.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub fn elog(message: &str) { - if let Ok(debug) = std::env::var("DEBUG") - && !debug.is_empty() - { - eprintln!(" [log] {message}"); - } -} 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 4eace3b..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}, @@ -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,183 @@ 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 mut manual = Apt::determine_manual(raw_all, &auto_set); + let (uniques, dupes) = manual.as_mut_slice().partition_dedup(); + assert!(dupes.is_empty()); + assert_eq!( + uniques, + 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/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 430f769..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}, }; @@ -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); + } + } +} 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"