diff --git a/Cargo.lock b/Cargo.lock index 9350112939bd6..9dce64ce66ab6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -396,7 +396,7 @@ dependencies = [ name = "cargo-miri" version = "0.1.0" dependencies = [ - "cargo_metadata 0.21.0", + "cargo_metadata 0.23.1", "directories", "rustc-build-sysroot", "rustc_tools_util 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -423,6 +423,15 @@ dependencies = [ "serde", ] +[[package]] +name = "cargo-platform" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122ec45a44b270afd1402f351b782c676b173e3c3fb28d86ff7ebfb4d86a4ee4" +dependencies = [ + "serde", +] + [[package]] name = "cargo-util-schemas" version = "0.8.2" @@ -468,6 +477,20 @@ dependencies = [ "thiserror 2.0.15", ] +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform 0.3.1", + "semver", + "serde", + "serde_json", + "thiserror 2.0.15", +] + [[package]] name = "cargotest2" version = "0.1.0" @@ -2157,6 +2180,16 @@ dependencies = [ "windows-targets 0.53.3", ] +[[package]] +name = "libloading" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + [[package]] name = "libm" version = "0.2.15" @@ -2404,7 +2437,7 @@ dependencies = [ "ipc-channel", "libc", "libffi", - "libloading", + "libloading 0.9.0", "measureme", "nix", "rand 0.9.2", @@ -4152,7 +4185,7 @@ version = "0.0.0" dependencies = [ "bitflags", "libc", - "libloading", + "libloading 0.8.8", "odht", "rustc_abi", "rustc_ast", diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index a2b02f286d659..9c7cc020798b8 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -44,20 +44,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" dependencies = [ "anstyle", - "unicode-width 0.2.1", + "unicode-width", ] [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "autocfg" @@ -67,9 +67,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -77,7 +77,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -91,15 +91,15 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bstr" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", "regex-automata", @@ -114,11 +114,11 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "camino" -version = "1.1.10" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -166,10 +166,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -177,9 +178,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -189,9 +190,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ "num-traits", ] @@ -218,18 +219,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.41" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.41" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" dependencies = [ "anstyle", "clap_lex", @@ -238,9 +239,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "cmake" @@ -253,13 +254,13 @@ dependencies = [ [[package]] name = "codespan-reporting" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ "serde", "termcolor", - "unicode-width 0.2.1", + "unicode-width", ] [[package]] @@ -273,7 +274,7 @@ dependencies = [ "eyre", "indenter", "once_cell", - "owo-colors 4.2.2", + "owo-colors", "tracing-error", ] @@ -284,21 +285,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" dependencies = [ "once_cell", - "owo-colors 4.2.2", + "owo-colors", "tracing-core", "tracing-error", ] -[[package]] -name = "colored" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" -dependencies = [ - "lazy_static", - "windows-sys 0.59.0", -] - [[package]] name = "colored" version = "3.0.0" @@ -323,7 +314,7 @@ dependencies = [ "encode_unicode", "libc", "once_cell", - "unicode-width 0.2.1", + "unicode-width", "windows-sys 0.59.0", ] @@ -353,9 +344,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -363,11 +354,12 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.173" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64ed3da1c337cbaae7223cdcff8b4dddf698d188cd3eaddd1116f6b0295950" +checksum = "47ac4eaf7ebe29e92f1b091ceefec7710a53a6f6154b2460afda626c113b65b9" dependencies = [ "cc", + "cxx-build", "cxxbridge-cmd", "cxxbridge-flags", "cxxbridge-macro", @@ -377,9 +369,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.173" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae0a26a75a05551f5ae3d75b3557543d06682284eaa7419113162d602cb45766" +checksum = "2abd4c3021eefbac5149f994c117b426852bca3a0aad227698527bca6d4ea657" dependencies = [ "cc", "codespan-reporting", @@ -392,9 +384,9 @@ dependencies = [ [[package]] name = "cxxbridge-cmd" -version = "1.0.173" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "952d408b6002b7db4b36da07c682a9cbb34f2db0efa03e976ae50a388414e16c" +checksum = "6f12fbc5888b2311f23e52a601e11ad7790d8f0dbb903ec26e2513bf5373ed70" dependencies = [ "clap", "codespan-reporting", @@ -406,20 +398,19 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.173" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccbd201b471c75c6abb6321cace706d1982d270e308b891c11a3262d320f5265" +checksum = "83d3dd7870af06e283f3f8ce0418019c96171c9ce122cfb9c8879de3d84388fd" [[package]] name = "cxxbridge-macro" -version = "1.0.173" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bea8b915bbc4cb4288f242aa7ca18b23ecc6965e4d6e7c1b07905e3fe2e0c41" +checksum = "a26f0d82da663316786791c3d0e9f9edc7d1ee1f04bdad3d2643086a69d6256c" dependencies = [ "indexmap", "proc-macro2", "quote", - "rustversion", "syn", ] @@ -441,7 +432,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -469,12 +460,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -493,6 +484,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "fnv" version = "1.0.7" @@ -507,9 +504,9 @@ checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -543,26 +540,26 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "git2" @@ -581,15 +578,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -600,9 +597,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -613,11 +610,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -628,42 +624,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -673,9 +665,9 @@ dependencies = [ [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -694,15 +686,15 @@ dependencies = [ [[package]] name = "indenter" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" [[package]] name = "indexmap" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", "hashbrown", @@ -717,7 +709,7 @@ dependencies = [ "console", "number_prefix", "portable-atomic", - "unicode-width 0.2.1", + "unicode-width", "web-time", ] @@ -732,9 +724,9 @@ dependencies = [ [[package]] name = "ipc-channel" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1c98b70019c830a1fc39cecfe1f60ff99c4122f0a189697c810c90ec545c14" +checksum = "f93600b5616c2d075f8af8dbd23c1d69278c5d24e4913d220cbc60b14c95c180" dependencies = [ "bincode", "crossbeam-channel", @@ -756,19 +748,19 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -788,9 +780,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libffi" @@ -826,19 +818,19 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.8" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" dependencies = [ "cfg-if", - "windows-targets 0.53.2", + "windows-link 0.2.1", ] [[package]] name = "libredox" -version = "0.1.4" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags", "libc", @@ -846,9 +838,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.22" +version = "1.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" dependencies = [ "cc", "libc", @@ -858,40 +850,39 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212" +checksum = "7f78c730aaa7d0b9336a299029ea49f9ee53b0ed06e9202e8cb7db9bae7b8c82" dependencies = [ "cc", ] [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "measureme" @@ -909,9 +900,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memmap2" @@ -933,13 +924,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -951,10 +942,10 @@ dependencies = [ "capstone", "chrono", "chrono-tz", - "colored 3.0.0", + "colored", "directories", "genmc-sys", - "getrandom 0.3.3", + "getrandom 0.3.4", "ipc-channel", "libc", "libffi", @@ -1001,9 +992,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -1022,9 +1013,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -1040,30 +1031,15 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "owo-colors" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" - -[[package]] -name = "owo-colors" -version = "4.2.2" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" - -[[package]] -name = "pad" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" -dependencies = [ - "unicode-width 0.1.14", -] +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1071,22 +1047,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perf-event-open-sys" @@ -1135,9 +1111,9 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -1153,28 +1129,27 @@ dependencies = [ [[package]] name = "prettydiff" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abec3fb083c10660b3854367697da94c674e9e82aa7511014dc958beeb7215e9" +checksum = "ac17546d82912e64874e3d5b40681ce32eac4e5834344f51efcf689ff1550a65" dependencies = [ - "owo-colors 3.5.0", - "pad", + "owo-colors", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -1187,9 +1162,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha", "rand_core", @@ -1211,34 +1186,34 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror 2.0.12", + "thiserror 2.0.17", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -1248,9 +1223,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -1259,15 +1234,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -1298,22 +1273,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -1329,33 +1304,44 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scratch" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f6280af86e5f559536da57a45ebc84948833b3bee313a7dd25232e09c878a52" +checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2" [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", + "serde_core", ] [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -1364,14 +1350,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.141" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -1414,9 +1401,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "strsim" @@ -1426,9 +1413,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.104" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" dependencies = [ "proc-macro2", "quote", @@ -1448,15 +1435,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1479,11 +1466,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.17", ] [[package]] @@ -1499,9 +1486,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", @@ -1529,9 +1516,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -1580,15 +1567,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ui_test" -version = "0.30.2" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b56a6897cc4bb6f8daf1939b0b39cd9645856997f46f4d0b3e3cb7122dfe9251" +checksum = "44eb652e1a8799d4e47f20851370e86247cbc5270ce677ab1e9409a6d45a9649" dependencies = [ "annotate-snippets", "anyhow", @@ -1596,7 +1583,7 @@ dependencies = [ "cargo-platform", "cargo_metadata", "color-eyre", - "colored 2.2.0", + "colored", "comma", "crossbeam-channel", "indicatif", @@ -1612,31 +1599,26 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-width" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -1647,11 +1629,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", "wasm-bindgen", ] @@ -1681,45 +1663,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1727,22 +1696,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] @@ -1759,41 +1728,64 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "windows" -version = "0.58.0" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ "windows-core", - "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.58.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", + "windows-link 0.1.3", "windows-result", "windows-strings", - "windows-targets 0.52.6", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "windows-link 0.1.3", + "windows-threading", ] [[package]] name = "windows-implement" -version = "0.58.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", @@ -1802,9 +1794,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.58.0" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", @@ -1812,22 +1804,43 @@ dependencies = [ ] [[package]] -name = "windows-result" +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-targets 0.52.6", + "windows-core", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", ] [[package]] name = "windows-strings" -version = "0.1.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-result", - "windows-targets 0.52.6", + "windows-link 0.1.3", ] [[package]] @@ -1836,16 +1849,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.60.2" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-targets 0.53.2", + "windows-link 0.2.1", ] [[package]] @@ -1854,30 +1867,23 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] -name = "windows-targets" -version = "0.53.2" +name = "windows-threading" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.1.3", ] [[package]] @@ -1886,84 +1892,42 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -1971,33 +1935,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -2005,9 +1959,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -2017,18 +1971,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", @@ -2058,9 +2012,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -2069,9 +2023,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -2080,9 +2034,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 8bb4f1c160934..99a48e5d4bc18 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -40,7 +40,7 @@ features = ['unprefixed_malloc_on_supported_platforms'] libc = "0.2" # native-lib dependencies libffi = { version = "5.0.0", optional = true } -libloading = { version = "0.8", optional = true } +libloading = { version = "0.9", optional = true } serde = { version = "1.0.219", features = ["derive"], optional = true } [target.'cfg(target_os = "linux")'.dependencies] @@ -72,7 +72,7 @@ harness = false default = ["stack-cache", "native-lib"] genmc = ["dep:genmc-sys"] stack-cache = [] -stack-cache-consistency-check = ["stack-cache"] +expensive-consistency-checks = ["stack-cache"] tracing = ["serde_json"] native-lib = ["dep:libffi", "dep:libloading", "dep:capstone", "dep:ipc-channel", "dep:nix", "dep:serde"] diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index ea9c04a3cb515..45be05fcc7f78 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -4,29 +4,23 @@ version = 4 [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "camino" -version = "1.1.10" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -44,38 +38,21 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4" +checksum = "122ec45a44b270afd1402f351b782c676b173e3c3fb28d86ff7ebfb4d86a4ee4" dependencies = [ "serde", ] -[[package]] -name = "cargo-util-schemas" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc1a6f7b5651af85774ae5a34b4e8be397d9cf4bc063b7e6dbd99a841837830" -dependencies = [ - "semver", - "serde", - "serde-untagged", - "serde-value", - "thiserror", - "toml", - "unicode-xid", - "url", -] - [[package]] name = "cargo_metadata" -version = "0.21.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cfca2aaa699835ba88faf58a06342a314a950d2b9686165e038286c30316868" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" dependencies = [ "camino", "cargo-platform", - "cargo-util-schemas", "semver", "serde", "serde_json", @@ -84,9 +61,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "directories" @@ -106,18 +83,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "windows-sys", ] [[package]] @@ -126,24 +92,14 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "erased-serde" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" -dependencies = [ - "serde", - "typeid", -] - [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys", ] [[package]] @@ -152,15 +108,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - [[package]] name = "getrandom" version = "0.2.16" @@ -169,139 +116,32 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", ] [[package]] name = "hashbrown" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" - -[[package]] -name = "icu_collections" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" - -[[package]] -name = "icu_properties" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "potential_utf", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.0.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" - -[[package]] -name = "icu_provider" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" -dependencies = [ - "displaydoc", - "icu_locale_core", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] name = "indexmap" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", "hashbrown", @@ -315,15 +155,15 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libredox" -version = "0.1.4" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags", "libc", @@ -331,30 +171,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - -[[package]] -name = "litemap" -version = "0.8.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "num-traits" -version = "0.2.19" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "once_cell" @@ -368,44 +193,20 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "ordered-float" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" -dependencies = [ - "num-traits", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "potential_utf" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" -dependencies = [ - "zerovec", -] - [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -418,9 +219,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", @@ -429,9 +230,9 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd41ead66a69880951b2f7df3139db401d44451b4da123344d27eaa791b89c95" +checksum = "3b881c015c729b43105bbd3702a9bdecee28fafaa21126d1d62e454ec011a4b7" dependencies = [ "anyhow", "rustc_version", @@ -457,15 +258,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys", ] [[package]] @@ -485,48 +286,38 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", + "serde_core", ] [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] [[package]] -name = "serde-untagged" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e" -dependencies = [ - "erased-serde", - "serde", - "typeid", -] - -[[package]] -name = "serde-value" -version = "0.7.0" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ - "ordered-float", - "serde", + "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -535,14 +326,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.141" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -554,83 +346,50 @@ dependencies = [ "serde", ] -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "syn" -version = "2.0.104" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tempfile" -version = "3.20.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "tinystr" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "toml" version = "0.8.23" @@ -673,40 +432,11 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" -[[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "url" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "walkdir" @@ -725,267 +455,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] [[package]] -name = "windows-sys" -version = "0.59.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.2", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winnow" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - -[[package]] -name = "writeable" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" - -[[package]] -name = "yoke" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerotrie" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.1" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml index 64b56ea114ecf..e8da7f2ca8a74 100644 --- a/src/tools/miri/cargo-miri/Cargo.toml +++ b/src/tools/miri/cargo-miri/Cargo.toml @@ -17,7 +17,7 @@ doctest = false # and no doc tests directories = "6" rustc_version = "0.4" serde_json = "1.0.40" -cargo_metadata = "0.21" +cargo_metadata = "0.23" rustc-build-sysroot = "0.5.10" # Enable some feature flags that dev-dependencies need but dependencies diff --git a/src/tools/miri/genmc-sys/build.rs b/src/tools/miri/genmc-sys/build.rs index 1b4e064d1ba21..9e956449a13df 100644 --- a/src/tools/miri/genmc-sys/build.rs +++ b/src/tools/miri/genmc-sys/build.rs @@ -28,7 +28,7 @@ mod downloading { /// The GenMC repository the we get our commit from. pub(crate) const GENMC_GITHUB_URL: &str = "https://github.com/MPI-SWS/genmc.git"; /// The GenMC commit we depend on. It must be available on the specified GenMC repository. - pub(crate) const GENMC_COMMIT: &str = "d9527280bb99f1cef64326b1803ffd952e3880df"; + pub(crate) const GENMC_COMMIT: &str = "aa10ed65117c3291524efc19253b5d443a4602ac"; /// Ensure that a local GenMC repo is present and set to the correct commit. /// Return the path of the GenMC repo and whether the checked out commit was changed. @@ -140,51 +140,6 @@ mod downloading { } } -// FIXME(genmc,llvm): Remove once the LLVM dependency of the GenMC model checker is removed. -/// The linked LLVM version is in the generated `config.h`` file, which we parse and use to link to LLVM. -/// Returns c++ compiler definitions required for building with/including LLVM, and the include path for LLVM headers. -fn link_to_llvm(config_file: &Path) -> (String, String) { - /// Search a string for a line matching `//@VARIABLE_NAME: VARIABLE CONTENT` - fn extract_value<'a>(input: &'a str, name: &str) -> Option<&'a str> { - input - .lines() - .find_map(|line| line.strip_prefix("//@")?.strip_prefix(name)?.strip_prefix(": ")) - } - - let file_content = std::fs::read_to_string(&config_file).unwrap_or_else(|err| { - panic!("GenMC config file ({}) should exist, but got errror {err:?}", config_file.display()) - }); - - let llvm_definitions = extract_value(&file_content, "LLVM_DEFINITIONS") - .expect("Config file should contain LLVM_DEFINITIONS"); - let llvm_include_dirs = extract_value(&file_content, "LLVM_INCLUDE_DIRS") - .expect("Config file should contain LLVM_INCLUDE_DIRS"); - let llvm_library_dir = extract_value(&file_content, "LLVM_LIBRARY_DIR") - .expect("Config file should contain LLVM_LIBRARY_DIR"); - let llvm_config_path = extract_value(&file_content, "LLVM_CONFIG_PATH") - .expect("Config file should contain LLVM_CONFIG_PATH"); - - // Add linker search path. - let lib_dir = PathBuf::from_str(llvm_library_dir).unwrap(); - println!("cargo::rustc-link-search=native={}", lib_dir.display()); - - // Add libraries to link. - let output = std::process::Command::new(llvm_config_path) - .arg("--libs") // Print the libraries to link to (space-separated list) - .output() - .expect("failed to execute llvm-config"); - let llvm_link_libs = - String::try_from(output.stdout).expect("llvm-config output should be a valid string"); - - for link_lib in llvm_link_libs.trim().split(" ") { - let link_lib = - link_lib.strip_prefix("-l").expect("Linker parameter should start with \"-l\""); - println!("cargo::rustc-link-lib=dylib={link_lib}"); - } - - (llvm_definitions.to_string(), llvm_include_dirs.to_string()) -} - /// Build the GenMC model checker library and the Rust-C++ interop library with cxx.rs fn compile_cpp_dependencies(genmc_path: &Path, always_configure: bool) { // Give each step a separate build directory to prevent interference. @@ -204,6 +159,7 @@ fn compile_cpp_dependencies(genmc_path: &Path, always_configure: bool) { .always_configure(always_configure) // We force running the configure step when the GenMC commit changed. .out_dir(genmc_build_dir) .profile(GENMC_CMAKE_PROFILE) + .define("BUILD_LLI", "OFF") .define("GENMC_DEBUG", if enable_genmc_debug { "ON" } else { "OFF" }); // The actual compilation happens here: @@ -214,19 +170,11 @@ fn compile_cpp_dependencies(genmc_path: &Path, always_configure: bool) { println!("cargo::rustc-link-search=native={}", cmake_lib_dir.display()); println!("cargo::rustc-link-lib=static={GENMC_MODEL_CHECKER}"); - // FIXME(genmc,llvm): Remove once the LLVM dependency of the GenMC model checker is removed. - let config_file = genmc_install_dir.join("include").join("genmc").join("config.h"); - let (llvm_definitions, llvm_include_dirs) = link_to_llvm(&config_file); - // Part 2: // Compile the cxx_bridge (the link between the Rust and C++ code). let genmc_include_dir = genmc_install_dir.join("include").join("genmc"); - // FIXME(genmc,llvm): remove once LLVM dependency is removed. - // These definitions are parsed into a cmake list and then printed to the config.h file, so they are ';' separated. - let definitions = llvm_definitions.split(";"); - // These are all the C++ files we need to compile, which needs to be updated if more C++ files are added to Miri. // We use absolute paths since relative paths can confuse IDEs when attempting to go-to-source on a path in a compiler error. let cpp_files_base_path = Path::new("cpp/src/"); @@ -244,16 +192,12 @@ fn compile_cpp_dependencies(genmc_path: &Path, always_configure: bool) { if enable_genmc_debug { bridge.define("ENABLE_GENMC_DEBUG", None); } - for definition in definitions { - bridge.flag(definition); - } bridge .opt_level(2) .debug(true) // Same settings that GenMC uses (default for cmake `RelWithDebInfo`) .warnings(false) // NOTE: enabling this produces a lot of warnings. .std("c++23") .include(genmc_include_dir) - .include(llvm_include_dirs) .include("./cpp/include") .files(&cpp_files) .out_dir(interface_build_dir) diff --git a/src/tools/miri/genmc-sys/cpp/include/MiriInterface.hpp b/src/tools/miri/genmc-sys/cpp/include/MiriInterface.hpp index 3a04edc013681..4929c0cfa150f 100644 --- a/src/tools/miri/genmc-sys/cpp/include/MiriInterface.hpp +++ b/src/tools/miri/genmc-sys/cpp/include/MiriInterface.hpp @@ -220,7 +220,8 @@ struct MiriGenmcShim : private GenMCDriver { auto handle_load_reset_if_none(ThreadId tid, std::optional old_val, Ts&&... params) -> HandleResult { const auto pos = inc_pos(tid); - const auto ret = GenMCDriver::handleLoad(pos, old_val, std::forward(params)...); + const auto ret = + GenMCDriver::handleLoad(nullptr, pos, old_val, std::forward(params)...); // If we didn't get a value, we have to reset the index of the current thread. if (!std::holds_alternative(ret)) { dec_pos(tid); diff --git a/src/tools/miri/genmc-sys/cpp/include/ResultHandling.hpp b/src/tools/miri/genmc-sys/cpp/include/ResultHandling.hpp index 189f32e6f513d..cb5f49c179b05 100644 --- a/src/tools/miri/genmc-sys/cpp/include/ResultHandling.hpp +++ b/src/tools/miri/genmc-sys/cpp/include/ResultHandling.hpp @@ -7,14 +7,16 @@ // GenMC headers: #include "Verification/VerificationError.hpp" +#include +#include +#include #include /** Information about an error, formatted as a string to avoid having to share an error enum and * printing functionality with the Rust side. */ static auto format_error(VerificationError err) -> std::unique_ptr { - auto buf = std::string(); - auto s = llvm::raw_string_ostream(buf); - s << err; + std::stringstream s; + s << std::format("{}", err); return std::make_unique(s.str()); } diff --git a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/EventHandling.cpp b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/EventHandling.cpp index 2b6e5749d41a5..96fb803bcc4eb 100644 --- a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/EventHandling.cpp +++ b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/EventHandling.cpp @@ -34,7 +34,7 @@ void MiriGenmcShim::handle_assume_block(ThreadId thread_id, AssumeType assume_type) { BUG_ON(getExec().getGraph().isThreadBlocked(thread_id)); - GenMCDriver::handleAssume(inc_pos(thread_id), assume_type); + GenMCDriver::handleAssume(nullptr, inc_pos(thread_id), assume_type); } /**** Memory access handling ****/ @@ -76,6 +76,7 @@ void MiriGenmcShim::handle_assume_block(ThreadId thread_id, AssumeType assume_ty ) -> StoreResult { const auto pos = inc_pos(thread_id); const auto ret = GenMCDriver::handleStore( + nullptr, pos, GenmcScalarExt::try_to_sval(old_val), ord, @@ -100,7 +101,7 @@ void MiriGenmcShim::handle_assume_block(ThreadId thread_id, AssumeType assume_ty void MiriGenmcShim::handle_fence(ThreadId thread_id, MemOrdering ord) { const auto pos = inc_pos(thread_id); - GenMCDriver::handleFence(pos, ord, EventDeps()); + GenMCDriver::handleFence(nullptr, pos, ord, EventDeps()); } [[nodiscard]] auto MiriGenmcShim::handle_read_modify_write( @@ -143,6 +144,7 @@ void MiriGenmcShim::handle_fence(ThreadId thread_id, MemOrdering ord) { const auto storePos = inc_pos(thread_id); const auto store_ret = GenMCDriver::handleStore( + nullptr, storePos, GenmcScalarExt::try_to_sval(old_val), ordering, @@ -210,6 +212,7 @@ void MiriGenmcShim::handle_fence(ThreadId thread_id, MemOrdering ord) { const auto storePos = inc_pos(thread_id); const auto store_ret = GenMCDriver::handleStore( + nullptr, storePos, GenmcScalarExt::try_to_sval(old_val), success_ordering, @@ -242,6 +245,7 @@ auto MiriGenmcShim::handle_malloc(ThreadId thread_id, uint64_t size, uint64_t al const auto address_space = AddressSpace::AS_User; const SVal ret_val = GenMCDriver::handleMalloc( + nullptr, pos, size, alignment, @@ -255,7 +259,7 @@ auto MiriGenmcShim::handle_malloc(ThreadId thread_id, uint64_t size, uint64_t al auto MiriGenmcShim::handle_free(ThreadId thread_id, uint64_t address) -> bool { const auto pos = inc_pos(thread_id); - GenMCDriver::handleFree(pos, SAddr(address), EventDeps()); + GenMCDriver::handleFree(nullptr, pos, SAddr(address), EventDeps()); // FIXME(genmc): use returned error from `handleFree` once implemented in GenMC. return getResult().status.has_value(); } diff --git a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Exploration.cpp b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Exploration.cpp index 0f64083ddda68..7722c4bfab69e 100644 --- a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Exploration.cpp +++ b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Exploration.cpp @@ -22,13 +22,23 @@ auto MiriGenmcShim::schedule_next( // a scheduling decision. threads_action_[curr_thread_id].kind = curr_thread_next_instr_kind; - if (const auto result = GenMCDriver::scheduleNext(threads_action_)) - return SchedulingResult { ExecutionState::Ok, static_cast(result.value()) }; - if (getExec().getGraph().isBlocked()) - return SchedulingResult { ExecutionState::Blocked, 0 }; - if (getResult().status.has_value()) // the "value" here is a `VerificationError` - return SchedulingResult { ExecutionState::Error, 0 }; - return SchedulingResult { ExecutionState::Finished, 0 }; + auto result = GenMCDriver::scheduleNext(threads_action_); + return std::visit( + [](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) + return SchedulingResult { ExecutionState::Ok, static_cast(arg) }; + else if constexpr (std::is_same_v) + return SchedulingResult { ExecutionState::Blocked, 0 }; + else if constexpr (std::is_same_v) + return SchedulingResult { ExecutionState::Error, 0 }; + else if constexpr (std::is_same_v) + return SchedulingResult { ExecutionState::Finished, 0 }; + else + static_assert(false, "non-exhaustive visitor!"); + }, + result + ); } /**** Execution start/end handling ****/ diff --git a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Mutex.cpp b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Mutex.cpp index fc3f5e6e09a67..af7e30186cbe0 100644 --- a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Mutex.cpp +++ b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Mutex.cpp @@ -60,6 +60,7 @@ auto MiriGenmcShim::handle_mutex_lock(ThreadId thread_id, uint64_t address, uint const bool is_lock_acquired = *ret_val == MUTEX_UNLOCKED; if (is_lock_acquired) { const auto store_ret = GenMCDriver::handleStore( + nullptr, inc_pos(thread_id), old_val, address, @@ -93,6 +94,7 @@ auto MiriGenmcShim::handle_mutex_try_lock(ThreadId thread_id, uint64_t address, // a mutex to be "unlocked". const auto old_val = MUTEX_UNLOCKED; const auto load_ret = GenMCDriver::handleLoad( + nullptr, ++currPos, old_val, SAddr(address), @@ -115,6 +117,7 @@ auto MiriGenmcShim::handle_mutex_try_lock(ThreadId thread_id, uint64_t address, } const auto store_ret = GenMCDriver::handleStore( + nullptr, ++currPos, old_val, SAddr(address), @@ -136,6 +139,7 @@ auto MiriGenmcShim::handle_mutex_unlock(ThreadId thread_id, uint64_t address, ui -> StoreResult { const auto pos = inc_pos(thread_id); const auto ret = GenMCDriver::handleStore( + nullptr, pos, // As usual, we need to tell GenMC which value was stored at this location before this // atomic access, if there previously was a non-atomic initializing access. We set the diff --git a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Setup.cpp b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Setup.cpp index 5455b1a8de7f8..20c827221a92a 100644 --- a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Setup.cpp +++ b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/Setup.cpp @@ -147,9 +147,16 @@ static auto to_genmc_verbosity_level(const LogLevel log_level) -> VerbosityLevel // that is allowed to leak and memory that is not. conf->warnUnfreedMemory = false; - // FIXME(genmc,error handling): This function currently exits on error, but will return an - // error value in the future. The return value should be checked once this change is made. - checkConfig(*conf); + // Validate the config and exit if there are any errors + std::vector warnings; + auto config_valid = conf->validate(warnings); + for (const auto& w : warnings) + WARN("{}", w); + if (auto* errors = std::get_if(&config_valid); errors) { + for (const auto& e : *errors) + LOG(VerbosityLevel::Error, "{}", e); + exit(EUSER); + } // Create the actual driver and Miri-GenMC communication shim. auto driver = std::make_unique(std::move(conf), mode); diff --git a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/ThreadManagement.cpp b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/ThreadManagement.cpp index d2061fcb406c9..85fc7d92f78f2 100644 --- a/src/tools/miri/genmc-sys/cpp/src/MiriInterface/ThreadManagement.cpp +++ b/src/tools/miri/genmc-sys/cpp/src/MiriInterface/ThreadManagement.cpp @@ -19,10 +19,11 @@ void MiriGenmcShim::handle_thread_create(ThreadId thread_id, ThreadId parent_id) // FIXME(genmc): for supporting symmetry reduction, these will need to be properly set: const unsigned fun_id = 0; const SVal arg = SVal(0); - const ThreadInfo child_info = ThreadInfo { thread_id, parent_id, fun_id, arg }; + const ThreadInfo child_info = + ThreadInfo { thread_id, parent_id, fun_id, arg, "unknown thread" }; // NOTE: Default memory ordering (`Release`) used here. - const auto child_tid = GenMCDriver::handleThreadCreate(pos, child_info, EventDeps()); + const auto child_tid = GenMCDriver::handleThreadCreate(nullptr, pos, child_info, EventDeps()); // Sanity check the thread id, which is the index in the `threads_action_` array. BUG_ON(child_tid != thread_id || child_tid <= 0 || child_tid != threads_action_.size()); threads_action_.push_back(Action(ActionKind::Load, Event(child_tid, 0))); @@ -33,7 +34,7 @@ void MiriGenmcShim::handle_thread_join(ThreadId thread_id, ThreadId child_id) { const auto pos = inc_pos(thread_id); // NOTE: Default memory ordering (`Acquire`) used here. - const auto ret = GenMCDriver::handleThreadJoin(pos, child_id, EventDeps()); + const auto ret = GenMCDriver::handleThreadJoin(nullptr, pos, child_id, EventDeps()); // If the join failed, decrease the event index again: if (!std::holds_alternative(ret)) { dec_pos(thread_id); @@ -46,10 +47,10 @@ void MiriGenmcShim::handle_thread_join(ThreadId thread_id, ThreadId child_id) { void MiriGenmcShim::handle_thread_finish(ThreadId thread_id, uint64_t ret_val) { const auto pos = inc_pos(thread_id); // NOTE: Default memory ordering (`Release`) used here. - GenMCDriver::handleThreadFinish(pos, SVal(ret_val)); + GenMCDriver::handleThreadFinish(nullptr, pos, SVal(ret_val)); } void MiriGenmcShim::handle_thread_kill(ThreadId thread_id) { const auto pos = inc_pos(thread_id); - GenMCDriver::handleThreadKill(pos); + GenMCDriver::handleThreadKill(nullptr, pos); } diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 06a5970646243..25bb5e923183c 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -7a72c5459dd58f81b0e1a0e5436d145485889375 +69d4d5fc0e4db60272aac85ef27ecccef5764f3a diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 9ce2aab8658f2..ecb8abc463bbe 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -158,19 +158,24 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { _: &rustc_interface::interface::Compiler, tcx: TyCtxt<'tcx>, ) -> Compilation { + // Compilation is done, interpretation is starting. Deal with diagnostics from the + // compilation part. We cannot call `sess.finish_diagnostics()` as then "aborting due to + // previous errors" gets printed twice. + tcx.dcx().emit_stashed_diagnostics(); tcx.dcx().abort_if_errors(); tcx.dcx().flush_delayed(); + // Miri is taking over. Start logging. + init_late_loggers(&EarlyDiagCtxt::new(tcx.sess.opts.error_format), tcx); + + // Find the entry point. if !tcx.crate_types().contains(&CrateType::Executable) { tcx.dcx().fatal("miri only makes sense on bin crates"); } - - let early_dcx = EarlyDiagCtxt::new(tcx.sess.opts.error_format); - init_late_loggers(&early_dcx, tcx); - let (entry_def_id, entry_type) = entry_fn(tcx); - let mut config = self.miri_config.take().expect("after_analysis must only be called once"); + // Obtain and complete the Miri configuration. + let mut config = self.miri_config.take().expect("after_analysis must only be called once"); // Add filename to `miri` arguments. config.args.insert(0, tcx.sess.io.input.filestem().to_string()); @@ -179,6 +184,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { env::set_current_dir(cwd).unwrap(); } + // Emit warnings for some unusual configurations. if tcx.sess.opts.optimize != OptLevel::No { tcx.dcx().warn("Miri does not support optimizations: the opt-level is ignored. The only effect \ of selecting a Cargo profile that enables optimizations (such as --release) is to apply \ @@ -193,6 +199,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { optimizations is usually marginal at best."); } + // Invoke the interpreter. let res = if config.genmc_config.is_some() { assert!(self.many_seeds.is_none()); run_genmc_mode(tcx, &config, |genmc_ctx: Rc| { @@ -209,7 +216,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { } else { miri::eval_entry(tcx, entry_def_id, entry_type, &config, None) }; - + // Process interpreter result. if let Err(return_code) = res { tcx.dcx().abort_if_errors(); exit(return_code.get()); @@ -509,7 +516,6 @@ fn main() { Some(BorrowTrackerMethod::TreeBorrows(TreeBorrowsParams { precise_interior_mut: true, })); - miri_config.provenance_mode = ProvenanceMode::Strict; } else if arg == "-Zmiri-tree-borrows-no-precise-interior-mut" { match &mut miri_config.borrow_tracker { Some(BorrowTrackerMethod::TreeBorrows(params)) => { @@ -703,17 +709,6 @@ fn main() { rustc_args.push(arg); } } - // Tree Borrows implies strict provenance, and is not compatible with native calls. - if matches!(miri_config.borrow_tracker, Some(BorrowTrackerMethod::TreeBorrows { .. })) { - if miri_config.provenance_mode != ProvenanceMode::Strict { - fatal_error!( - "Tree Borrows does not support integer-to-pointer casts, and hence requires strict provenance" - ); - } - if !miri_config.native_lib.is_empty() { - fatal_error!("Tree Borrows is not compatible with calling native functions"); - } - } // Native calls and strict provenance are not compatible. if !miri_config.native_lib.is_empty() && miri_config.provenance_mode == ProvenanceMode::Strict { diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index e83028f0248f6..9aa0ce48e09a0 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -352,6 +352,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let borrow_tracker = this.machine.borrow_tracker.as_ref().unwrap(); // The body of this loop needs `borrow_tracker` immutably // so we can't move this code inside the following `end_call`. + for (alloc_id, tag) in &frame .extra .borrow_tracker @@ -378,6 +379,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } borrow_tracker.borrow_mut().end_call(&frame.extra); + interp_ok(()) } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs index fcd6216fc32dc..d8eaba8ec2892 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs @@ -153,7 +153,7 @@ impl<'tcx> Stack { /// Panics if any of the caching mechanisms have broken, /// - The StackCache indices don't refer to the parallel items, /// - There are no Unique items outside of first_unique..last_unique - #[cfg(feature = "stack-cache-consistency-check")] + #[cfg(feature = "expensive-consistency-checks")] fn verify_cache_consistency(&self) { // Only a full cache needs to be valid. Also see the comments in find_granting_cache // and set_unknown_bottom. @@ -197,7 +197,7 @@ impl<'tcx> Stack { tag: ProvenanceExtra, exposed_tags: &FxHashSet, ) -> Result, ()> { - #[cfg(feature = "stack-cache-consistency-check")] + #[cfg(feature = "expensive-consistency-checks")] self.verify_cache_consistency(); let ProvenanceExtra::Concrete(tag) = tag else { @@ -334,7 +334,7 @@ impl<'tcx> Stack { // This primes the cache for the next access, which is almost always the just-added tag. self.cache.add(new_idx, new); - #[cfg(feature = "stack-cache-consistency-check")] + #[cfg(feature = "expensive-consistency-checks")] self.verify_cache_consistency(); } @@ -417,7 +417,7 @@ impl<'tcx> Stack { self.unique_range.end = self.unique_range.end.min(disable_start); } - #[cfg(feature = "stack-cache-consistency-check")] + #[cfg(feature = "expensive-consistency-checks")] self.verify_cache_consistency(); interp_ok(()) @@ -472,7 +472,7 @@ impl<'tcx> Stack { self.unique_range = 0..0; } - #[cfg(feature = "stack-cache-consistency-check")] + #[cfg(feature = "expensive-consistency-checks")] self.verify_cache_consistency(); interp_ok(()) } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index f2410a08625dd..c454bb43a2f59 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -291,9 +291,10 @@ pub(super) struct TbError<'node> { pub conflicting_info: &'node NodeDebugInfo, // What kind of access caused this error (read, write, reborrow, deallocation) pub access_cause: AccessCause, - /// Which tag the access that caused this error was made through, i.e. + /// Which tag, if any, the access that caused this error was made through, i.e. /// which tag was used to read/write/deallocate. - pub accessed_info: &'node NodeDebugInfo, + /// Not set on wildcard accesses. + pub accessed_info: Option<&'node NodeDebugInfo>, } impl TbError<'_> { @@ -302,10 +303,20 @@ impl TbError<'_> { use TransitionError::*; let cause = self.access_cause; let accessed = self.accessed_info; + let accessed_str = + self.accessed_info.map(|v| format!("{v}")).unwrap_or_else(|| "".into()); let conflicting = self.conflicting_info; - let accessed_is_conflicting = accessed.tag == conflicting.tag; + // An access is considered conflicting if it happened through a + // different tag than the one who caused UB. + // When doing a wildcard access (where `accessed` is `None`) we + // do not know which precise tag the accessed happened from, + // however we can be certain that it did not come from the + // conflicting tag. + // This is because the wildcard data structure already removes + // all tags through which an access would cause UB. + let accessed_is_conflicting = accessed.map(|a| a.tag) == Some(conflicting.tag); let title = format!( - "{cause} through {accessed} at {alloc_id:?}[{offset:#x}] is forbidden", + "{cause} through {accessed_str} at {alloc_id:?}[{offset:#x}] is forbidden", alloc_id = self.alloc_id, offset = self.error_offset ); @@ -316,7 +327,7 @@ impl TbError<'_> { let mut details = Vec::new(); if !accessed_is_conflicting { details.push(format!( - "the accessed tag {accessed} is a child of the conflicting tag {conflicting}" + "the accessed tag {accessed_str} is a child of the conflicting tag {conflicting}" )); } let access = cause.print_as_access(/* is_foreign */ false); @@ -330,7 +341,7 @@ impl TbError<'_> { let access = cause.print_as_access(/* is_foreign */ true); let details = vec![ format!( - "the accessed tag {accessed} is foreign to the {conflicting_tag_name} tag {conflicting} (i.e., it is not a child)" + "the accessed tag {accessed_str} is foreign to the {conflicting_tag_name} tag {conflicting} (i.e., it is not a child)" ), format!( "this {access} would cause the {conflicting_tag_name} tag {conflicting} (currently {before_disabled}) to become Disabled" @@ -343,7 +354,7 @@ impl TbError<'_> { let conflicting_tag_name = "strongly protected"; let details = vec![ format!( - "the allocation of the accessed tag {accessed} also contains the {conflicting_tag_name} tag {conflicting}" + "the allocation of the accessed tag {accessed_str} also contains the {conflicting_tag_name} tag {conflicting}" ), format!("the {conflicting_tag_name} tag {conflicting} disallows deallocations"), ]; @@ -351,8 +362,10 @@ impl TbError<'_> { } }; let mut history = HistoryData::default(); - if !accessed_is_conflicting { - history.extend(self.accessed_info.history.forget(), "accessed", false); + if let Some(accessed_info) = self.accessed_info + && !accessed_is_conflicting + { + history.extend(accessed_info.history.forget(), "accessed", false); } history.extend( self.conflicting_info.history.extract_relevant(self.error_offset, self.error_kind), @@ -363,6 +376,20 @@ impl TbError<'_> { } } +/// Cannot access this allocation with wildcard provenance, as there are no +/// valid exposed references for this access kind. +pub fn no_valid_exposed_references_error<'tcx>( + alloc_id: AllocId, + offset: u64, + access_cause: AccessCause, +) -> InterpErrorKind<'tcx> { + let title = + format!("{access_cause} through at {alloc_id:?}[{offset:#x}] is forbidden"); + let details = vec![format!("there are no exposed tags which may perform this access here")]; + let history = HistoryData::default(); + err_machine_stop!(TerminationInfo::TreeBorrowsUb { title, details, history }) +} + type S = &'static str; /// Pretty-printing details /// @@ -623,10 +650,10 @@ impl DisplayRepr { } else { // We take this node let rperm = tree - .rperms + .locations .iter_all() - .map(move |(_offset, perms)| { - let perm = perms.get(idx); + .map(move |(_offset, loc)| { + let perm = loc.perms.get(idx); perm.cloned() }) .collect::>(); @@ -788,7 +815,7 @@ impl<'tcx> Tree { show_unnamed: bool, ) -> InterpResult<'tcx> { let mut indenter = DisplayIndent::new(); - let ranges = self.rperms.iter_all().map(|(range, _perms)| range).collect::>(); + let ranges = self.locations.iter_all().map(|(range, _loc)| range).collect::>(); if let Some(repr) = DisplayRepr::from(self, show_unnamed) { repr.print( &DEFAULT_FORMATTER, diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 756ccc53222e7..2a1c98e5266bf 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -14,6 +14,7 @@ mod foreign_access_skipping; mod perms; mod tree; mod unimap; +mod wildcard; #[cfg(test)] mod exhaustive; @@ -54,16 +55,10 @@ impl<'tcx> Tree { interpret::Pointer::new(alloc_id, range.start), range.size.bytes(), ); - // TODO: for now we bail out on wildcard pointers. Eventually we should - // handle them as much as we can. - let tag = match prov { - ProvenanceExtra::Concrete(tag) => tag, - ProvenanceExtra::Wildcard => return interp_ok(()), - }; let global = machine.borrow_tracker.as_ref().unwrap(); let span = machine.current_user_relevant_span(); self.perform_access( - tag, + prov, Some((range, access_kind, diagnostics::AccessCause::Explicit(access_kind))), global, alloc_id, @@ -79,19 +74,9 @@ impl<'tcx> Tree { size: Size, machine: &MiriMachine<'tcx>, ) -> InterpResult<'tcx> { - // TODO: for now we bail out on wildcard pointers. Eventually we should - // handle them as much as we can. - let tag = match prov { - ProvenanceExtra::Concrete(tag) => tag, - ProvenanceExtra::Wildcard => return interp_ok(()), - }; let global = machine.borrow_tracker.as_ref().unwrap(); let span = machine.current_user_relevant_span(); - self.dealloc(tag, alloc_range(Size::ZERO, size), global, alloc_id, span) - } - - pub fn expose_tag(&mut self, _tag: BorTag) { - // TODO + self.dealloc(prov, alloc_range(Size::ZERO, size), global, alloc_id, span) } /// A tag just lost its protector. @@ -109,7 +94,11 @@ impl<'tcx> Tree { ) -> InterpResult<'tcx> { let span = machine.current_user_relevant_span(); // `None` makes it the magic on-protector-end operation - self.perform_access(tag, None, global, alloc_id, span) + self.perform_access(ProvenanceExtra::Concrete(tag), None, global, alloc_id, span)?; + + self.update_exposure_for_protector_release(tag); + + interp_ok(()) } } @@ -239,21 +228,22 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { assert_eq!(ptr_size, Size::ZERO); // we did the deref check above, size has to be 0 here // This pointer doesn't come with an AllocId, so there's no // memory to do retagging in. + let new_prov = place.ptr().provenance; trace!( - "reborrow of size 0: reference {:?} derived from {:?} (pointee {})", - new_tag, + "reborrow of size 0: reusing {:?} (pointee {})", place.ptr(), place.layout.ty, ); log_creation(this, None)?; // Keep original provenance. - return interp_ok(place.ptr().provenance); + return interp_ok(new_prov); } }; + log_creation(this, Some((alloc_id, base_offset, parent_prov)))?; let orig_tag = match parent_prov { - ProvenanceExtra::Wildcard => return interp_ok(place.ptr().provenance), // TODO: handle wildcard pointers + ProvenanceExtra::Wildcard => return interp_ok(place.ptr().provenance), // TODO: handle retagging wildcard pointers ProvenanceExtra::Concrete(tag) => tag, }; @@ -356,7 +346,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; tree_borrows.perform_access( - orig_tag, + parent_prov, Some((range_in_alloc, AccessKind::Read, diagnostics::AccessCause::Reborrow)), this.machine.borrow_tracker.as_ref().unwrap(), alloc_id, @@ -589,7 +579,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // uncovers a non-supported `extern static`. let alloc_extra = this.get_alloc_extra(alloc_id)?; trace!("Tree Borrows tag {tag:?} exposed in {alloc_id:?}"); - alloc_extra.borrow_tracker_tb().borrow_mut().expose_tag(tag); + + let global = this.machine.borrow_tracker.as_ref().unwrap(); + let protected_tags = &global.borrow().protected_tags; + let protected = protected_tags.contains_key(&tag); + alloc_extra.borrow_tracker_tb().borrow_mut().expose_tag(tag, protected); } AllocKind::Function | AllocKind::VTable | AllocKind::TypeId | AllocKind::Dead => { // No tree borrows on these allocations. diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index b84ebd51656c0..bd4573f94013e 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -53,6 +53,7 @@ enum PermissionPriv { } use self::PermissionPriv::*; use super::foreign_access_skipping::IdempotentForeignAccess; +use super::wildcard::WildcardAccessLevel; impl PartialOrd for PermissionPriv { /// PermissionPriv is ordered by the reflexive transitive closure of @@ -372,6 +373,23 @@ impl Permission { pub fn strongest_idempotent_foreign_access(&self, prot: bool) -> IdempotentForeignAccess { self.inner.strongest_idempotent_foreign_access(prot) } + + /// Returns the strongest access allowed from a child to this node without + /// causing UB (only considers possible transitions to this permission). + pub fn strongest_allowed_child_access(&self, protected: bool) -> WildcardAccessLevel { + match self.inner { + // Everything except disabled can be accessed by read access. + Disabled => WildcardAccessLevel::None, + // Frozen references cannot be written to by a child. + Frozen => WildcardAccessLevel::Read, + // If the `conflicted` flag is set, then there was a foreign read + // during the function call that is still ongoing (still `protected`), + // this is UB (`noalias` violation). + ReservedFrz { conflicted: true } if protected => WildcardAccessLevel::Read, + // Everything else allows writes. + _ => WildcardAccessLevel::Write, + } + } } impl PermTransition { @@ -772,4 +790,32 @@ mod propagation_optimization_checks { ); } } + + /// Checks that `strongest_allowed_child_access` correctly + /// represents which transitions are possible. + #[test] + fn strongest_allowed_child_access() { + for (permission, protected) in <(Permission, bool)>::exhaustive() { + let strongest_child_access = permission.strongest_allowed_child_access(protected); + + let is_read_valid = Permission::perform_access( + AccessKind::Read, + AccessRelatedness::LocalAccess, + permission, + protected, + ) + .is_some(); + + let is_write_valid = Permission::perform_access( + AccessKind::Write, + AccessRelatedness::LocalAccess, + permission, + protected, + ) + .is_some(); + + assert_eq!(is_read_valid, strongest_child_access >= WildcardAccessLevel::Read); + assert_eq!(is_write_valid, strongest_child_access >= WildcardAccessLevel::Write); + } + } } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index e337fe05e135d..7c30f76c29a1f 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -18,9 +18,11 @@ use rustc_data_structures::fx::FxHashSet; use rustc_span::Span; use smallvec::SmallVec; +use super::diagnostics::AccessCause; +use super::wildcard::WildcardState; use crate::borrow_tracker::tree_borrows::Permission; use crate::borrow_tracker::tree_borrows::diagnostics::{ - self, NodeDebugInfo, TbError, TransitionError, + self, NodeDebugInfo, TbError, TransitionError, no_valid_exposed_references_error, }; use crate::borrow_tracker::tree_borrows::foreign_access_skipping::IdempotentForeignAccess; use crate::borrow_tracker::tree_borrows::perms::PermTransition; @@ -30,7 +32,7 @@ use crate::*; mod tests; -/// Data for a single *location*. +/// Data for a reference at single *location*. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(super) struct LocationState { /// A location is "accessed" when it is child-accessed for the first time (and the initial @@ -81,6 +83,49 @@ impl LocationState { self.permission } + /// Performs an access on this index and updates node, + /// perm and wildcard_state to reflect the transition. + fn perform_transition( + &mut self, + idx: UniIndex, + nodes: &mut UniValMap, + wildcard_accesses: &mut UniValMap, + access_kind: AccessKind, + access_cause: AccessCause, + access_range: Option, + relatedness: AccessRelatedness, + span: Span, + location_range: Range, + protected: bool, + ) -> Result<(), TransitionError> { + // Call this function now (i.e. only if we know `relatedness`), which + // ensures it is only called when `skip_if_known_noop` returns + // `Recurse`, due to the contract of `traverse_this_parents_children_other`. + self.record_new_access(access_kind, relatedness); + + let transition = self.perform_access(access_kind, relatedness, protected)?; + if !transition.is_noop() { + let node = nodes.get_mut(idx).unwrap(); + // Record the event as part of the history. + node.debug_info.history.push(diagnostics::Event { + transition, + is_foreign: relatedness.is_foreign(), + access_cause, + access_range, + transition_range: location_range, + span, + }); + + // We need to update the wildcard state, if the permission + // of an exposed pointer changes. + if node.is_exposed { + let access_type = self.permission.strongest_allowed_child_access(protected); + WildcardState::update_exposure(idx, access_type, nodes, wildcard_accesses); + } + } + Ok(()) + } + /// Apply the effect of an access to one location, including /// - applying `Permission::perform_access` to the inner `Permission`, /// - emitting protector UB if the location is accessed, @@ -211,30 +256,44 @@ impl fmt::Display for LocationState { Ok(()) } } - +/// The state of the full tree for a particular location: for all nodes, the local permissions +/// of that node, and the tracking for wildcard accesses. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct LocationTree { + /// Maps a tag to a perm, with possible lazy initialization. + /// + /// NOTE: not all tags registered in `Tree::nodes` are necessarily in all + /// ranges of `perms`, because `perms` is in part lazily initialized. + /// Just because `nodes.get(key)` is `Some(_)` does not mean you can safely + /// `unwrap` any `perm.get(key)`. + /// + /// We do uphold the fact that `keys(perms)` is a subset of `keys(nodes)` + pub perms: UniValMap, + /// Maps a tag and a location to its wildcard access tracking information, + /// with possible lazy initialization. + /// + /// If this allocation doesn't have any exposed nodes, then this map doesn't get + /// initialized. This way we only need to allocate the map if we need it. + /// + /// NOTE: same guarantees on entry initialization as for `perms`. + pub wildcard_accesses: UniValMap, +} /// Tree structure with both parents and children since we want to be /// able to traverse the tree efficiently in both directions. #[derive(Clone, Debug)] pub struct Tree { /// Mapping from tags to keys. The key obtained can then be used in - /// any of the `UniValMap` relative to this allocation, i.e. both the - /// `nodes` and `rperms` of the same `Tree`. + /// any of the `UniValMap` relative to this allocation, i.e. + /// `nodes`, `LocationTree::perms` and `LocationTree::wildcard_accesses` + /// of the same `Tree`. /// The parent-child relationship in `Node` is encoded in terms of these same /// keys, so traversing the entire tree needs exactly one access to /// `tag_mapping`. pub(super) tag_mapping: UniKeyMap, /// All nodes of this tree. pub(super) nodes: UniValMap, - /// Maps a tag and a location to a perm, with possible lazy - /// initialization. - /// - /// NOTE: not all tags registered in `nodes` are necessarily in all - /// ranges of `rperms`, because `rperms` is in part lazily initialized. - /// Just because `nodes.get(key)` is `Some(_)` does not mean you can safely - /// `unwrap` any `perm.get(key)`. - /// - /// We do uphold the fact that `keys(perms)` is a subset of `keys(nodes)` - pub(super) rperms: DedupRangeMap>, + /// Associates with each location its state and wildcard access tracking. + pub(super) locations: DedupRangeMap, /// The index of the root node. pub(super) root: UniIndex, } @@ -260,7 +319,9 @@ pub(super) struct Node { /// in cases where there is no location state yet. See `foreign_access_skipping.rs`, /// and `LocationState::idempotent_foreign_access` for more information default_initial_idempotent_foreign_access: IdempotentForeignAccess, - /// Some extra information useful only for debugging purposes + /// Whether a wildcard access could happen through this node. + pub is_exposed: bool, + /// Some extra information useful only for debugging purposes. pub debug_info: NodeDebugInfo, } @@ -273,7 +334,7 @@ struct NodeAppArgs<'visit> { /// The node map of this tree. nodes: &'visit mut UniValMap, /// The permissions map of this tree. - perms: &'visit mut UniValMap, + loc: &'visit mut LocationTree, } /// Data given to the error handler struct ErrHandlerArgs<'node, InErr> { @@ -293,7 +354,7 @@ struct ErrHandlerArgs<'node, InErr> { struct TreeVisitor<'tree> { tag_mapping: &'tree UniKeyMap, nodes: &'tree mut UniValMap, - perms: &'tree mut UniValMap, + loc: &'tree mut LocationTree, } /// Whether to continue exploring the children recursively or not. @@ -350,7 +411,7 @@ where idx: UniIndex, rel_pos: AccessRelatedness, ) -> ContinueTraversal { - let args = NodeAppArgs { idx, rel_pos, nodes: this.nodes, perms: this.perms }; + let args = NodeAppArgs { idx, rel_pos, nodes: this.nodes, loc: this.loc }; (self.f_continue)(&args) } @@ -360,14 +421,15 @@ where idx: UniIndex, rel_pos: AccessRelatedness, ) -> Result<(), OutErr> { - (self.f_propagate)(NodeAppArgs { idx, rel_pos, nodes: this.nodes, perms: this.perms }) - .map_err(|error_kind| { + (self.f_propagate)(NodeAppArgs { idx, rel_pos, nodes: this.nodes, loc: this.loc }).map_err( + |error_kind| { (self.err_builder)(ErrHandlerArgs { error_kind, conflicting_info: &this.nodes.get(idx).unwrap().debug_info, accessed_info: &this.nodes.get(self.initial).unwrap().debug_info, }) - }) + }, + ) } fn go_upwards_from_accessed( @@ -577,6 +639,7 @@ impl Tree { default_initial_perm: root_default_perm, // The root may never be skipped, all accesses will be local. default_initial_idempotent_foreign_access: IdempotentForeignAccess::None, + is_exposed: false, debug_info, }, ); @@ -595,9 +658,10 @@ impl Tree { IdempotentForeignAccess::None, ), ); - DedupRangeMap::new(size, perms) + let wildcard_accesses = UniValMap::default(); + DedupRangeMap::new(size, LocationTree { perms, wildcard_accesses }) }; - Self { root: root_idx, nodes, rperms, tag_mapping } + Self { root: root_idx, nodes, locations: rperms, tag_mapping } } } @@ -633,11 +697,13 @@ impl<'tcx> Tree { children: SmallVec::default(), default_initial_perm: outside_perm, default_initial_idempotent_foreign_access: default_strongest_idempotent, + is_exposed: false, debug_info: NodeDebugInfo::new(new_tag, outside_perm, span), }, ); + let parent_node = self.nodes.get_mut(parent_idx).unwrap(); // Register new_tag as a child of parent_tag - self.nodes.get_mut(parent_idx).unwrap().children.push(idx); + parent_node.children.push(idx); // We need to know the weakest SIFA for `update_idempotent_foreign_access_after_retag`. let mut min_sifa = default_strongest_idempotent; @@ -651,11 +717,19 @@ impl<'tcx> Tree { ); min_sifa = cmp::min(min_sifa, perm.idempotent_foreign_access); - for (_perms_range, perms) in self - .rperms + for (_range, loc) in self + .locations .iter_mut(Size::from_bytes(start) + base_offset, Size::from_bytes(end - start)) { - perms.insert(idx, perm); + loc.perms.insert(idx, perm); + } + } + + // We need to ensure the consistency of the wildcard access tracking data structure. + // For this, we insert the correct entry for this tag based on its parent, if it exists. + for (_range, loc) in self.locations.iter_mut_all() { + if let Some(parent_access) = loc.wildcard_accesses.get(parent_idx) { + loc.wildcard_accesses.insert(idx, parent_access.for_new_child()); } } @@ -689,9 +763,9 @@ impl<'tcx> Tree { // as the default SIFA for not-yet-initialized locations. // Record whether we did any change; if not, the invariant is restored and we can stop the traversal. let mut any_change = false; - for (_, map) in self.rperms.iter_mut_all() { + for (_range, loc) in self.locations.iter_mut_all() { // Check if this node has a state for this location (or range of locations). - if let Some(perm) = map.get_mut(current) { + if let Some(perm) = loc.perms.get_mut(current) { // Update the per-location SIFA, recording if it changed. any_change |= perm.idempotent_foreign_access.ensure_no_stronger_than(strongest_allowed); @@ -720,28 +794,37 @@ impl<'tcx> Tree { /// - the absence of Strong Protectors anywhere in the allocation pub fn dealloc( &mut self, - tag: BorTag, + prov: ProvenanceExtra, access_range: AllocRange, global: &GlobalState, alloc_id: AllocId, // diagnostics span: Span, // diagnostics ) -> InterpResult<'tcx> { self.perform_access( - tag, + prov, Some((access_range, AccessKind::Write, diagnostics::AccessCause::Dealloc)), global, alloc_id, span, )?; - for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) { - TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms } + + // Check if this breaks any strong protector. + // (Weak protectors are already handled by `perform_access`.) + for (loc_range, loc) in self.locations.iter_mut(access_range.start, access_range.size) { + // The order in which we check if any nodes are invalidated only + // matters to diagnostics, so we use the root as a default tag. + let start_tag = match prov { + ProvenanceExtra::Concrete(tag) => tag, + ProvenanceExtra::Wildcard => self.nodes.get(self.root).unwrap().tag, + }; + TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, loc } .traverse_this_parents_children_other( - tag, - // visit all children, skipping none + start_tag, + // Visit all children, skipping none. |_| ContinueTraversal::Recurse, |args: NodeAppArgs<'_>| -> Result<(), TransitionError> { let node = args.nodes.get(args.idx).unwrap(); - let perm = args.perms.entry(args.idx); + let perm = args.loc.perms.entry(args.idx); let perm = perm.get().copied().unwrap_or_else(|| node.default_location_state()); @@ -764,9 +847,15 @@ impl<'tcx> Tree { conflicting_info, access_cause: diagnostics::AccessCause::Dealloc, alloc_id, - error_offset: perms_range.start, + error_offset: loc_range.start, error_kind, - accessed_info, + accessed_info: match prov { + ProvenanceExtra::Concrete(_) => Some(accessed_info), + // `accessed_info` contains the info of `start_tag`. + // On a wildcard access this is not the info of the accessed tag + // (as we don't know the accessed tag). + ProvenanceExtra::Wildcard => None, + }, } .build() }, @@ -795,12 +884,15 @@ impl<'tcx> Tree { /// - recording the history. pub fn perform_access( &mut self, - tag: BorTag, + prov: ProvenanceExtra, access_range_and_kind: Option<(AllocRange, AccessKind, diagnostics::AccessCause)>, global: &GlobalState, alloc_id: AllocId, // diagnostics span: Span, // diagnostics ) -> InterpResult<'tcx> { + let ProvenanceExtra::Concrete(tag) = prov else { + return self.perform_wildcard_access(access_range_and_kind, global, alloc_id, span); + }; use std::ops::Range; // Performs the per-node work: // - insert the permission if it does not exist @@ -814,7 +906,7 @@ impl<'tcx> Tree { // the `RangeMap` on which we are currently working). let node_skipper = |access_kind: AccessKind, args: &NodeAppArgs<'_>| -> ContinueTraversal { let node = args.nodes.get(args.idx).unwrap(); - let perm = args.perms.get(args.idx); + let perm = args.loc.perms.get(args.idx); let old_state = perm.copied().unwrap_or_else(|| node.default_location_state()); old_state.skip_if_known_noop(access_kind, args.rel_pos) @@ -825,29 +917,23 @@ impl<'tcx> Tree { args: NodeAppArgs<'_>| -> Result<(), TransitionError> { let node = args.nodes.get_mut(args.idx).unwrap(); - let mut perm = args.perms.entry(args.idx); - - let old_state = perm.or_insert(node.default_location_state()); + let mut perm = args.loc.perms.entry(args.idx); - // Call this function now, which ensures it is only called when - // `skip_if_known_noop` returns `Recurse`, due to the contract of - // `traverse_this_parents_children_other`. - old_state.record_new_access(access_kind, args.rel_pos); + let state = perm.or_insert(node.default_location_state()); let protected = global.borrow().protected_tags.contains_key(&node.tag); - let transition = old_state.perform_access(access_kind, args.rel_pos, protected)?; - // Record the event as part of the history - if !transition.is_noop() { - node.debug_info.history.push(diagnostics::Event { - transition, - is_foreign: args.rel_pos.is_foreign(), - access_cause, - access_range: access_range_and_kind.map(|x| x.0), - transition_range: perms_range, - span, - }); - } - Ok(()) + state.perform_transition( + args.idx, + args.nodes, + &mut args.loc.wildcard_accesses, + access_kind, + access_cause, + /* access_range */ access_range_and_kind.map(|x| x.0), + args.rel_pos, + span, + perms_range, + protected, + ) }; // Error handler in case `node_app` goes wrong. @@ -863,7 +949,7 @@ impl<'tcx> Tree { alloc_id, error_offset: perms_range.start, error_kind, - accessed_info, + accessed_info: Some(accessed_info), } .build() }; @@ -871,14 +957,13 @@ impl<'tcx> Tree { if let Some((access_range, access_kind, access_cause)) = access_range_and_kind { // Default branch: this is a "normal" access through a known range. // We iterate over affected locations and traverse the tree for each of them. - for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) - { - TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms } + for (loc_range, loc) in self.locations.iter_mut(access_range.start, access_range.size) { + TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, loc } .traverse_this_parents_children_other( tag, |args| node_skipper(access_kind, args), - |args| node_app(perms_range.clone(), access_kind, access_cause, args), - |args| err_handler(perms_range.clone(), access_cause, args), + |args| node_app(loc_range.clone(), access_kind, access_cause, args), + |args| err_handler(loc_range.clone(), access_cause, args), )?; } } else { @@ -891,21 +976,21 @@ impl<'tcx> Tree { // See the test case `returned_mut_is_usable` from // `tests/pass/tree_borrows/tree-borrows.rs` for an example of // why this is important. - for (perms_range, perms) in self.rperms.iter_mut_all() { + for (loc_range, loc) in self.locations.iter_mut_all() { let idx = self.tag_mapping.get(&tag).unwrap(); // Only visit accessed permissions - if let Some(p) = perms.get(idx) + if let Some(p) = loc.perms.get(idx) && let Some(access_kind) = p.permission.protector_end_access() && p.accessed { let access_cause = diagnostics::AccessCause::FnExit(access_kind); - TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms } + TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, loc } .traverse_nonchildren( - tag, - |args| node_skipper(access_kind, args), - |args| node_app(perms_range.clone(), access_kind, access_cause, args), - |args| err_handler(perms_range.clone(), access_cause, args), - )?; + tag, + |args| node_skipper(access_kind, args), + |args| node_app(loc_range.clone(), access_kind, access_cause, args), + |args| err_handler(loc_range.clone(), access_cause, args), + )?; } } } @@ -921,7 +1006,7 @@ impl Tree { // merge some adjacent ranges that were made equal by the removal of some // tags (this does not necessarily mean that they have identical internal representations, // see the `PartialEq` impl for `UniValMap`) - self.rperms.merge_adjacent_thorough(); + self.locations.merge_adjacent_thorough(); } /// Checks if a node is useless and should be GC'ed. @@ -953,10 +1038,14 @@ impl Tree { let child = self.nodes.get(child_idx).unwrap(); // Check that for that one child, `can_be_replaced_by_child` holds for the permission // on all locations. - for (_, data) in self.rperms.iter_all() { - let parent_perm = - data.get(idx).map(|x| x.permission).unwrap_or_else(|| node.default_initial_perm); - let child_perm = data + for (_range, loc) in self.locations.iter_all() { + let parent_perm = loc + .perms + .get(idx) + .map(|x| x.permission) + .unwrap_or_else(|| node.default_initial_perm); + let child_perm = loc + .perms .get(child_idx) .map(|x| x.permission) .unwrap_or_else(|| child.default_initial_perm); @@ -980,8 +1069,9 @@ impl Tree { // before we can safely apply `UniKeyMap::remove` to truly remove // this tag from the `tag_mapping`. let node = self.nodes.remove(this).unwrap(); - for (_perms_range, perms) in self.rperms.iter_mut_all() { - perms.remove(this); + for (_range, loc) in self.locations.iter_mut_all() { + loc.perms.remove(this); + loc.wildcard_accesses.remove(this); } self.tag_mapping.remove(&node.tag); } @@ -1058,6 +1148,126 @@ impl Tree { } } +/// Methods for wildcard accesses. +impl<'tcx> Tree { + /// Analogous to `perform_access`, but we do not know from which exposed + /// reference the access happens. + pub fn perform_wildcard_access( + &mut self, + access_range_and_kind: Option<(AllocRange, AccessKind, diagnostics::AccessCause)>, + global: &GlobalState, + alloc_id: AllocId, // diagnostics + span: Span, // diagnostics + ) -> InterpResult<'tcx> { + #[cfg(feature = "expensive-consistency-checks")] + self.verify_wildcard_consistency(global); + + if let Some((access_range, access_kind, access_cause)) = access_range_and_kind { + // This does a traversal starting from the root through the tree updating + // the permissions of each node. + // The difference to `perform_access` is that we take the access + // relatedness from the wildcard tracking state of the node instead of + // from the visitor itself. + for (loc_range, loc) in self.locations.iter_mut(access_range.start, access_range.size) { + let root_tag = self.nodes.get(self.root).unwrap().tag; + TreeVisitor { loc, nodes: &mut self.nodes, tag_mapping: &self.tag_mapping } + .traverse_this_parents_children_other( + root_tag, + |args: &NodeAppArgs<'_>| -> ContinueTraversal { + let node = args.nodes.get(args.idx).unwrap(); + let perm = args.loc.perms.get(args.idx); + let wildcard_state = args + .loc + .wildcard_accesses + .get(args.idx) + .cloned() + .unwrap_or_default(); + + let old_state = + perm.copied().unwrap_or_else(|| node.default_location_state()); + // If we know where, relative to this node, the wildcard access occurs, + // then check if we can skip the entire subtree. + if let Some(relatedness) = + wildcard_state.access_relatedness(access_kind) + && let Some(relatedness) = relatedness.to_relatedness() + { + // We can use the usual SIFA machinery to skip nodes. + old_state.skip_if_known_noop(access_kind, relatedness) + } else { + ContinueTraversal::Recurse + } + }, + |args| { + let node = args.nodes.get_mut(args.idx).unwrap(); + let mut entry = args.loc.perms.entry(args.idx); + let perm = entry.or_insert(node.default_location_state()); + + let protected = global.borrow().protected_tags.contains_key(&node.tag); + + let Some(wildcard_relatedness) = args + .loc + .wildcard_accesses + .get(args.idx) + .and_then(|s| s.access_relatedness(access_kind)) + else { + // There doesn't exist a valid exposed reference for this access to + // happen through. + // If this fails for one id, then it fails for all ids so this. + // Since we always check the root first, this means it should always + // fail on the root. + assert_eq!(self.root, args.idx); + return Err(no_valid_exposed_references_error( + alloc_id, + loc_range.start, + access_cause, + )); + }; + + let Some(relatedness) = wildcard_relatedness.to_relatedness() else { + // If the access type is Either, then we do not apply any transition + // to this node, but we still update each of its children. + // This is an imprecision! In the future, maybe we can still do some sort + // of best-effort update here. + return Ok(()); + }; + // We know the exact relatedness, so we can actually do precise checks. + perm.perform_transition( + args.idx, + args.nodes, + &mut args.loc.wildcard_accesses, + access_kind, + access_cause, + Some(access_range), + relatedness, + span, + loc_range.clone(), + protected, + ) + .map_err(|trans| { + let node = args.nodes.get(args.idx).unwrap(); + TbError { + conflicting_info: &node.debug_info, + access_cause, + alloc_id, + error_offset: loc_range.start, + error_kind: trans, + accessed_info: None, + } + .build() + }) + }, + |err| err.error_kind, + )?; + } + } else { + // This is for the special access when a protector gets released. + // Wildcard pointers are never protected, so this is unreachable. + unreachable!() + }; + interp_ok(()) + } +} + impl Node { pub fn default_location_state(&self) -> LocationState { LocationState::new_non_accessed( @@ -1071,7 +1281,15 @@ impl VisitProvenance for Tree { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { // To ensure that the root never gets removed, we visit it // (the `root` node of `Tree` is not an `Option<_>`) - visit(None, Some(self.nodes.get(self.root).unwrap().tag)) + visit(None, Some(self.nodes.get(self.root).unwrap().tag)); + + // We also need to keep around any exposed tags through which + // an access could still happen. + for (_id, node) in self.nodes.iter() { + if node.is_exposed { + visit(None, Some(node.tag)) + } + } } } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs index ad0a565dfd857..6400a62f444f0 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs @@ -12,6 +12,7 @@ #![allow(dead_code)] +use std::fmt::Debug; use std::hash::Hash; use std::mem; @@ -20,10 +21,15 @@ use rustc_data_structures::fx::FxHashMap; use crate::helpers::ToUsize; /// Intermediate key between a UniKeyMap and a UniValMap. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq)] pub struct UniIndex { idx: u32, } +impl Debug for UniIndex { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.idx.fmt(f) + } +} /// From K to UniIndex #[derive(Debug, Clone, Default)] @@ -201,6 +207,19 @@ impl UniValMap { mem::swap(&mut res, &mut self.data[idx.idx.to_usize()]); res } + + /// Returns true if the map is empty. + pub fn is_empty(&self) -> bool { + self.data.iter().all(|v| v.is_none()) + } + + /// Iterates over all key-value pairs in the map. + pub fn iter(&self) -> impl Iterator { + self.data + .iter() + .enumerate() + .filter_map(|(i, v)| v.as_ref().map(|r| (UniIndex { idx: i.try_into().unwrap() }, r))) + } } /// An access to a single value of the map. diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/wildcard.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/wildcard.rs new file mode 100644 index 0000000000000..56a85e6f4ced3 --- /dev/null +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/wildcard.rs @@ -0,0 +1,519 @@ +use std::cmp::max; +use std::fmt::Debug; + +use super::Tree; +use super::tree::{AccessRelatedness, Node}; +use super::unimap::{UniIndex, UniValMap}; +use crate::BorTag; +use crate::borrow_tracker::AccessKind; +#[cfg(feature = "expensive-consistency-checks")] +use crate::borrow_tracker::GlobalState; + +/// Represents the maximum access level that is possible. +/// +/// Note that we derive Ord and PartialOrd, so the order in which variants are listed below matters: +/// None < Read < Write. Do not change that order. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] +pub enum WildcardAccessLevel { + #[default] + None, + Read, + Write, +} + +/// Where the access happened relative to the current node. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum WildcardAccessRelatedness { + /// The access definitively happened through a local node. + LocalAccess, + /// The access definitively happened through a foreign node. + ForeignAccess, + /// We do not know if the access is foreign or local. + EitherAccess, +} +impl WildcardAccessRelatedness { + pub fn to_relatedness(self) -> Option { + match self { + Self::LocalAccess => Some(AccessRelatedness::LocalAccess), + Self::ForeignAccess => Some(AccessRelatedness::ForeignAccess), + Self::EitherAccess => None, + } + } +} + +/// State per location per node keeping track of where relative to this +/// node exposed nodes are and what access permissions they have. +/// +/// Designed to be completely determined by its parent, siblings and +/// direct children's max_local_access/max_foreign_access. +#[derive(Clone, Default, PartialEq, Eq)] +pub struct WildcardState { + /// How many of this node's direct children have `max_local_access()==Write`. + child_writes: u16, + /// How many of this node's direct children have `max_local_access()>=Read`. + child_reads: u16, + /// The maximum access level that could happen from an exposed node + /// that is foreign to this node. + /// + /// This is calculated as the `max()` of the parent's `max_foreign_access`, + /// `exposed_as` and the siblings' `max_local_access()`. + max_foreign_access: WildcardAccessLevel, + /// At what access level this node itself is exposed. + exposed_as: WildcardAccessLevel, +} +impl Debug for WildcardState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("WildcardState") + .field("child_r/w", &(self.child_reads, self.child_writes)) + .field("foreign", &self.max_foreign_access) + .field("exposed_as", &self.exposed_as) + .finish() + } +} +impl WildcardState { + /// The maximum access level that could happen from an exposed + /// node that is local to this node. + fn max_local_access(&self) -> WildcardAccessLevel { + use WildcardAccessLevel::*; + max( + self.exposed_as, + if self.child_writes > 0 { + Write + } else if self.child_reads > 0 { + Read + } else { + None + }, + ) + } + + /// From where relative to the node with this wildcard info a read or write access could happen. + pub fn access_relatedness(&self, kind: AccessKind) -> Option { + match kind { + AccessKind::Read => self.read_access_relatedness(), + AccessKind::Write => self.write_access_relatedness(), + } + } + + /// From where relative to the node with this wildcard info a read access could happen. + fn read_access_relatedness(&self) -> Option { + let has_foreign = self.max_foreign_access >= WildcardAccessLevel::Read; + let has_local = self.max_local_access() >= WildcardAccessLevel::Read; + use WildcardAccessRelatedness as E; + match (has_foreign, has_local) { + (true, true) => Some(E::EitherAccess), + (true, false) => Some(E::ForeignAccess), + (false, true) => Some(E::LocalAccess), + (false, false) => None, + } + } + + /// From where relative to the node with this wildcard info a write access could happen. + fn write_access_relatedness(&self) -> Option { + let has_foreign = self.max_foreign_access == WildcardAccessLevel::Write; + let has_local = self.max_local_access() == WildcardAccessLevel::Write; + use WildcardAccessRelatedness as E; + match (has_foreign, has_local) { + (true, true) => Some(E::EitherAccess), + (true, false) => Some(E::ForeignAccess), + (false, true) => Some(E::LocalAccess), + (false, false) => None, + } + } + + /// Gets the access tracking information for a new child node of a parent with this + /// wildcard info. + /// The new node doesn't have any child reads/writes, but calculates `max_foreign_access` + /// from its parent. + pub fn for_new_child(&self) -> Self { + Self { + max_foreign_access: max(self.max_foreign_access, self.max_local_access()), + ..Default::default() + } + } + + /// Pushes the nodes of `children` onto the stack who's `max_foreign_access` + /// needs to be updated. + /// + /// * `children`: A list of nodes with the same parent. `children` doesn't + /// necessarily have to contain all children of parent, but can just be + /// a subset. + /// + /// * `child_reads`, `child_writes`: How many of `children` have `max_local_access()` + /// of at least `read`/`write` + /// + /// * `new_foreign_access`, `old_foreign_access`: + /// The max possible access level that is foreign to all `children` + /// (i.e., it is not local to *any* of them). + /// This can be calculated as the max of the parent's `exposed_as()`, `max_foreign_access` + /// and of all `max_local_access()` of any nodes with the same parent that are + /// not listed in `children`. + /// + /// This access level changed from `old` to `new`, which is why we need to + /// update `children`. + fn push_relevant_children( + stack: &mut Vec<(UniIndex, WildcardAccessLevel)>, + new_foreign_access: WildcardAccessLevel, + old_foreign_access: WildcardAccessLevel, + child_reads: u16, + child_writes: u16, + children: impl Iterator, + + wildcard_accesses: &UniValMap, + ) { + use WildcardAccessLevel::*; + + // Nothing changed so we don't need to update anything. + if new_foreign_access == old_foreign_access { + return; + } + + // We need to consider that the children's `max_local_access()` affect each + // other's `max_foreign_access`, but do not affect their own `max_foreign_access`. + + // The new `max_foreign_acces` for children with `max_local_access()==Write`. + let write_foreign_access = max( + new_foreign_access, + if child_writes > 1 { + // There exists at least one more child with exposed write access. + // This means that a foreign write through that node is possible. + Write + } else if child_reads > 1 { + // There exists at least one more child with exposed read access, + // but no other with write access. + // This means that a foreign read but no write through that node + // is possible. + Read + } else { + // There are no other nodes with read or write access. + // This means no foreign writes through other children are possible. + None + }, + ); + + // The new `max_foreign_acces` for children with `max_local_access()==Read`. + let read_foreign_access = max( + new_foreign_access, + if child_writes > 0 { + // There exists at least one child with write access (and it's not this one). + Write + } else if child_reads > 1 { + // There exists at least one more child with exposed read access, + // but no other with write access. + Read + } else { + // There are no other nodes with read or write access, + None + }, + ); + + // The new `max_foreign_acces` for children with `max_local_access()==None`. + let none_foreign_access = max( + new_foreign_access, + if child_writes > 0 { + // There exists at least one child with write access (and it's not this one). + Write + } else if child_reads > 0 { + // There exists at least one child with read access (and it's not this one), + // but none with write access. + Read + } else { + // No children are exposed as read or write. + None + }, + ); + + stack.extend(children.filter_map(|child| { + let state = wildcard_accesses.get(child).cloned().unwrap_or_default(); + + let new_foreign_access = match state.max_local_access() { + Write => write_foreign_access, + Read => read_foreign_access, + None => none_foreign_access, + }; + + if new_foreign_access != state.max_foreign_access { + Some((child, new_foreign_access)) + } else { + Option::None + } + })); + } + + /// Update the tracking information of a tree, to reflect that the node specified by `id` is + /// now exposed with `new_exposed_as`. + /// + /// Propagates the Willard access information over the tree. This needs to be called every + /// time the access level of an exposed node changes, to keep the state in sync with + /// the rest of the tree. + pub fn update_exposure( + id: UniIndex, + new_exposed_as: WildcardAccessLevel, + nodes: &UniValMap, + wildcard_accesses: &mut UniValMap, + ) { + let mut entry = wildcard_accesses.entry(id); + let src_state = entry.or_insert(Default::default()); + let old_exposed_as = src_state.exposed_as; + + // If the exposure doesn't change, then we don't need to update anything. + if old_exposed_as == new_exposed_as { + return; + } + + let src_old_local_access = src_state.max_local_access(); + + src_state.exposed_as = new_exposed_as; + + let src_new_local_access = src_state.max_local_access(); + + // Stack of nodes for which the max_foreign_access field needs to be updated. + // Will be filled with the children of this node and its parents children before + // we begin downwards traversal. + let mut stack: Vec<(UniIndex, WildcardAccessLevel)> = Vec::new(); + + // Add the direct children of this node to the stack. + { + let node = nodes.get(id).unwrap(); + Self::push_relevant_children( + &mut stack, + // new_foreign_access + max(src_state.max_foreign_access, new_exposed_as), + // old_foreign_access + max(src_state.max_foreign_access, old_exposed_as), + // Consider all children. + src_state.child_reads, + src_state.child_writes, + node.children.iter().copied(), + wildcard_accesses, + ); + } + // We need to propagate the tracking info up the tree, for this we traverse + // up the parents. + // We can skip propagating info to the parent and siblings of a node if its + // access didn't change. + { + // The child from which we came. + let mut child = id; + // This is the `max_local_access()` of the child we came from, before + // this update... + let mut old_child_access = src_old_local_access; + // and after this update. + let mut new_child_access = src_new_local_access; + while let Some(parent_id) = nodes.get(child).unwrap().parent { + let parent_node = nodes.get(parent_id).unwrap(); + let mut entry = wildcard_accesses.entry(parent_id); + let parent_state = entry.or_insert(Default::default()); + + let old_parent_local_access = parent_state.max_local_access(); + use WildcardAccessLevel::*; + // Updating this node's tracking state for its children. + match (old_child_access, new_child_access) { + (None | Read, Write) => parent_state.child_writes += 1, + (Write, None | Read) => parent_state.child_writes -= 1, + _ => {} + } + match (old_child_access, new_child_access) { + (None, Read | Write) => parent_state.child_reads += 1, + (Read | Write, None) => parent_state.child_reads -= 1, + _ => {} + } + + let new_parent_local_access = parent_state.max_local_access(); + + { + // We need to update the `max_foreign_access` of `child`'s + // siblings. For this we can reuse the `push_relevant_children` + // function. + // + // We pass it just the siblings without child itself. Since + // `child`'s `max_local_access()` is foreign to all of its + // siblings we can pass it as part of the foreign access. + + let parent_access = + max(parent_state.exposed_as, parent_state.max_foreign_access); + // This is how many of `child`'s siblings have read/write local access. + // If `child` itself has access, then we need to subtract its access from the count. + let sibling_reads = + parent_state.child_reads - if new_child_access >= Read { 1 } else { 0 }; + let sibling_writes = + parent_state.child_writes - if new_child_access >= Write { 1 } else { 0 }; + Self::push_relevant_children( + &mut stack, + // new_foreign_access + max(parent_access, new_child_access), + // old_foreign_access + max(parent_access, old_child_access), + // Consider only siblings of child. + sibling_reads, + sibling_writes, + parent_node.children.iter().copied().filter(|id| child != *id), + wildcard_accesses, + ); + } + if old_parent_local_access == new_parent_local_access { + // We didn't change `max_local_access()` for parent, so we don't need to propagate further upwards. + break; + } + + old_child_access = old_parent_local_access; + new_child_access = new_parent_local_access; + child = parent_id; + } + } + // Traverses down the tree to update max_foreign_access fields of children and cousins who need to be updated. + while let Some((id, new_access)) = stack.pop() { + let node = nodes.get(id).unwrap(); + let mut entry = wildcard_accesses.entry(id); + let state = entry.or_insert(Default::default()); + + let old_access = state.max_foreign_access; + state.max_foreign_access = new_access; + + Self::push_relevant_children( + &mut stack, + // new_foreign_access + max(state.exposed_as, new_access), + // old_foreign_access + max(state.exposed_as, old_access), + // Consider all children. + state.child_reads, + state.child_writes, + node.children.iter().copied(), + wildcard_accesses, + ); + } + } +} + +impl Tree { + /// Marks the tag as exposed & updates the wildcard tracking data structure + /// to represent its access level. + /// Also takes as an argument whether the tag is protected or not. + pub fn expose_tag(&mut self, tag: BorTag, protected: bool) { + let id = self.tag_mapping.get(&tag).unwrap(); + let node = self.nodes.get_mut(id).unwrap(); + node.is_exposed = true; + let node = self.nodes.get(id).unwrap(); + + // When the first tag gets exposed then we initialize the + // wildcard state for every node and location in the tree. + for (_, loc) in self.locations.iter_mut_all() { + let perm = loc + .perms + .get(id) + .map(|p| p.permission()) + .unwrap_or_else(|| node.default_location_state().permission()); + + let access_type = perm.strongest_allowed_child_access(protected); + WildcardState::update_exposure( + id, + access_type, + &self.nodes, + &mut loc.wildcard_accesses, + ); + } + } + + /// This updates the wildcard tracking data structure to reflect the release of + /// the protector on `tag`. + pub(super) fn update_exposure_for_protector_release(&mut self, tag: BorTag) { + let idx = self.tag_mapping.get(&tag).unwrap(); + + // We check if the node is already exposed, as we don't want to expose any + // nodes which aren't already exposed. + + if self.nodes.get(idx).unwrap().is_exposed { + // Updates the exposure to the new permission on every location. + self.expose_tag(tag, /* protected */ false); + } + } +} + +#[cfg(feature = "expensive-consistency-checks")] +impl Tree { + /// Checks that the wildcard tracking data structure is internally consistent and + /// has the correct `exposed_as` values. + pub fn verify_wildcard_consistency(&self, global: &GlobalState) { + let protected_tags = &global.borrow().protected_tags; + for (_, loc) in self.locations.iter_all() { + let wildcard_accesses = &loc.wildcard_accesses; + let perms = &loc.perms; + // Checks if accesses is empty. + if wildcard_accesses.is_empty() { + return; + } + for (id, node) in self.nodes.iter() { + let state = wildcard_accesses.get(id).unwrap(); + + let expected_exposed_as = if node.is_exposed { + let perm = perms.get(id).unwrap(); + + perm.permission() + .strongest_allowed_child_access(protected_tags.contains_key(&node.tag)) + } else { + WildcardAccessLevel::None + }; + + // The foreign wildcard accesses possible at a node are determined by which + // accesses can originate from their siblings, their parent, and from above + // their parent. + let expected_max_foreign_access = if let Some(parent) = node.parent { + let parent_node = self.nodes.get(parent).unwrap(); + let parent_state = wildcard_accesses.get(parent).unwrap(); + + let max_sibling_access = parent_node + .children + .iter() + .copied() + .filter(|child| *child != id) + .map(|child| { + let state = wildcard_accesses.get(child).unwrap(); + state.max_local_access() + }) + .fold(WildcardAccessLevel::None, max); + + max_sibling_access + .max(parent_state.max_foreign_access) + .max(parent_state.exposed_as) + } else { + WildcardAccessLevel::None + }; + + // Count how many children can be the source of wildcard reads or writes + // (either directly, or via their children). + let child_accesses = node.children.iter().copied().map(|child| { + let state = wildcard_accesses.get(child).unwrap(); + state.max_local_access() + }); + let expected_child_reads = + child_accesses.clone().filter(|a| *a >= WildcardAccessLevel::Read).count(); + let expected_child_writes = + child_accesses.filter(|a| *a >= WildcardAccessLevel::Write).count(); + + assert_eq!( + expected_exposed_as, state.exposed_as, + "tag {:?} (id:{id:?}) should be exposed as {expected_exposed_as:?} but is exposed as {:?}", + node.tag, state.exposed_as + ); + assert_eq!( + expected_max_foreign_access, state.max_foreign_access, + "expected {:?}'s (id:{id:?}) max_foreign_access to be {:?} instead of {:?}", + node.tag, expected_max_foreign_access, state.max_foreign_access + ); + let child_reads: usize = state.child_reads.into(); + assert_eq!( + expected_child_reads, child_reads, + "expected {:?}'s (id:{id:?}) child_reads to be {} instead of {}", + node.tag, expected_child_reads, child_reads + ); + let child_writes: usize = state.child_writes.into(); + assert_eq!( + expected_child_writes, child_writes, + "expected {:?}'s (id:{id:?}) child_writes to be {} instead of {}", + node.tag, expected_child_writes, child_writes + ); + } + } + } +} diff --git a/src/tools/miri/src/shims/unix/linux_like/epoll.rs b/src/tools/miri/src/shims/unix/linux_like/epoll.rs index 52b761fa08a1c..b0383c1ba4a12 100644 --- a/src/tools/miri/src/shims/unix/linux_like/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux_like/epoll.rs @@ -181,13 +181,13 @@ impl EpollInterestTable { .borrow_mut() .extract_if(range_for_id(id), |_, _| true) // Consume the iterator. - .for_each(|_| ()); + .for_each(drop); epoll .ready_set .borrow_mut() .extract_if(range_for_id(id), |_| true) // Consume the iterator. - .for_each(|_| ()); + .for_each(drop); } } } diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/dealloc.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/dealloc.rs new file mode 100644 index 0000000000000..c314a96a44312 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/dealloc.rs @@ -0,0 +1,21 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks that deallocation through a wildcard ref fails, +/// if all exposed references are disabled. +pub fn main() { + use std::alloc::Layout; + let x = unsafe { std::alloc::alloc_zeroed(Layout::new::()) as *mut u32 }; + + let ref1 = unsafe { &mut *x }; + let ref2 = unsafe { &mut *x }; + + let int = ref1 as *mut u32 as usize; + let wild = int as *mut u32; + // Disables ref1 and therefore also wild. + *ref2 = 14; + + // Tries to dealloc through a wildcard reference even though all exposed + // references are disabled. + + unsafe { std::alloc::dealloc(wild as *mut u8, Layout::new::()) }; //~ ERROR: /deallocation through .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/dealloc.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/dealloc.stderr new file mode 100644 index 0000000000000..a30a45e64b306 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/dealloc.stderr @@ -0,0 +1,14 @@ +error: Undefined Behavior: deallocation through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/dealloc.rs:LL:CC + | +LL | unsafe { std::alloc::dealloc(wild as *mut u8, Layout::new::()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: there are no exposed tags which may perform this access here + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/gc.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/gc.rs new file mode 100644 index 0000000000000..b46f0670bee03 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/gc.rs @@ -0,0 +1,20 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +#[path = "../../../utils/mod.rs"] +mod utils; + +/// Checks that the garbage collector doesn't remove any exposed tags. +fn main() { + let mut _x: u32 = 4; + let int = { + let y = &_x; + y as *const u32 as usize + }; + // If y wasn't exposed, this would gc it. + utils::run_provenance_gc(); + // This should disable y. + _x = 5; + let wild = int as *const u32; + + let _fail = unsafe { *wild }; //~ ERROR: /read access through at .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/gc.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/gc.stderr new file mode 100644 index 0000000000000..4ca2735df592b --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/gc.stderr @@ -0,0 +1,14 @@ +error: Undefined Behavior: read access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/gc.rs:LL:CC + | +LL | let _fail = unsafe { *wild }; + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: there are no exposed tags which may perform this access here + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child.rs new file mode 100644 index 0000000000000..2187fca16ca19 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child.rs @@ -0,0 +1,64 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks that disabling an exposed reference correctly narrows the +/// possible locations a wildcard access could happen from. +/// Also checks that an access is treated as foreign, if all exposed +/// (non-disabled) references are ancestors. +pub fn main() { + let mut x: u32 = 42; + + let ref1 = &mut x; + let int1 = ref1 as *mut u32 as usize; + + let ref2 = &mut *ref1; + + let ref3 = &mut *ref2; + let _int3 = ref3 as *mut u32 as usize; + + // Write through ref3 so that all references are active. + *ref3 = 43; + + let wild = int1 as *mut u32; + + // ┌────────────┐ + // │ │ + // │ ref1(Act)* │ + // │ │ + // └──────┬─────┘ + // │ + // │ + // ▼ + // ┌────────────┐ + // │ │ + // │ ref2(Act) │ + // │ │ + // └──────┬─────┘ + // │ + // │ + // ▼ + // ┌────────────┐ + // │ │ + // │ ref3(Act)* │ + // │ │ + // └────────────┘ + + // Writes through either ref1 or ref3, which is either a child or foreign + // access to ref2. + unsafe { wild.write(42) }; + + // Reading from ref2 still works, since the previous access could have been + // through its child. + // This also freezes ref3. + let _x = *ref2; + + // We can still write through wild, as there is still the exposed ref1 with + // write permissions under proper exposed provenance, this would be UB as the + // only tag wild can assume to not invalidate ref2 is ref3, which we just + // invalidated. + // + // This disables ref2, ref3. + unsafe { wild.write(43) }; + + // Fails because ref2 is disabled. + let _fail = *ref2; //~ ERROR: /read access through .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child.stderr new file mode 100644 index 0000000000000..3d450cf784037 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child.stderr @@ -0,0 +1,25 @@ +error: Undefined Behavior: read access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/multi_exposed_child.rs:LL:CC + | +LL | let _fail = *ref2; + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the accessed tag has state Disabled which forbids this child read access +help: the accessed tag was created here, in the initial state Reserved + --> tests/fail/tree_borrows/wildcard/multi_exposed_child.rs:LL:CC + | +LL | let ref2 = &mut *ref1; + | ^^^^^^^^^^ +help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4] + --> tests/fail/tree_borrows/wildcard/multi_exposed_child.rs:LL:CC + | +LL | unsafe { wild.write(43) }; + | ^^^^^^^^^^^^^^ + = help: this transition corresponds to a loss of read and write permissions + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child_unique_writer.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child_unique_writer.rs new file mode 100644 index 0000000000000..39c6f315e1413 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child_unique_writer.rs @@ -0,0 +1,47 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks if we correctly determine the correct exposed reference a write +/// access could happen through, +/// if there are also exposed reference through which only a read could happen. +pub fn main() { + let mut x: u32 = 42; + + let ref1 = &mut x; + let int1 = ref1 as *mut u32 as usize; + + let ref2 = &mut *ref1; + + let ref3 = &*ref2; + let _int3 = ref3 as *const u32 as usize; + + let wild = int1 as *mut u32; + + // ┌────────────┐ + // │ │ + // │ ref1(Res)* │ + // │ │ + // └──────┬─────┘ + // │ + // │ + // ▼ + // ┌────────────┐ + // │ │ + // │ ref2(Res) │ + // │ │ + // └──────┬─────┘ + // │ + // │ + // ▼ + // ┌────────────┐ + // │ │ + // │ ref3(Frz)* │ + // │ │ + // └────────────┘ + + // Writes through ref1 as we cannot write through ref3 since it's frozen. + // Disables ref2, ref3. + unsafe { wild.write(42) }; + + // ref2 is disabled. + let _fail = *ref2; //~ ERROR: /read access through .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child_unique_writer.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child_unique_writer.stderr new file mode 100644 index 0000000000000..402529cbc3878 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_child_unique_writer.stderr @@ -0,0 +1,25 @@ +error: Undefined Behavior: read access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/multi_exposed_child_unique_writer.rs:LL:CC + | +LL | let _fail = *ref2; + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the accessed tag has state Disabled which forbids this child read access +help: the accessed tag was created here, in the initial state Reserved + --> tests/fail/tree_borrows/wildcard/multi_exposed_child_unique_writer.rs:LL:CC + | +LL | let ref2 = &mut *ref1; + | ^^^^^^^^^^ +help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4] + --> tests/fail/tree_borrows/wildcard/multi_exposed_child_unique_writer.rs:LL:CC + | +LL | unsafe { wild.write(42) }; + | ^^^^^^^^^^^^^^ + = help: this transition corresponds to a loss of read and write permissions + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_disable.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_disable.rs new file mode 100644 index 0000000000000..2622e9a62ab7d --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_disable.rs @@ -0,0 +1,38 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks with multiple exposed nodes, that if they are all disabled +/// then no wildcard accesses are possible. +pub fn main() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + let ref3 = unsafe { &mut *ptr_base }; + + // Both references get exposed. + let int1 = ref1 as *mut u32 as usize; + let _int2 = ref2 as *mut u32 as usize; + + let wild = int1 as *mut u32; + + // ┌────────────┐ + // │ │ + // │ ptr_base ├──────────────┬───────────────────┐ + // │ │ │ │ + // └──────┬─────┘ │ │ + // │ │ │ + // │ │ │ + // ▼ ▼ ▼ + // ┌────────────┐ ┌────────────┐ ┌───────────┐ + // │ │ │ │ │ │ + // │ ref1(Res)* │ │ ref2(Res)* │ │ ref3(Res) │ + // │ │ │ │ │ │ + // └────────────┘ └────────────┘ └───────────┘ + + // Disables ref1,ref2. + *ref3 = 13; + + // Both exposed references are disabled so this fails. + let _fail = unsafe { *wild }; //~ ERROR: /read access through .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_disable.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_disable.stderr new file mode 100644 index 0000000000000..bc659d7febf3a --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_disable.stderr @@ -0,0 +1,14 @@ +error: Undefined Behavior: read access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_disable.rs:LL:CC + | +LL | let _fail = unsafe { *wild }; + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: there are no exposed tags which may perform this access here + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_foreign.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_foreign.rs new file mode 100644 index 0000000000000..c889f57552d66 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_foreign.rs @@ -0,0 +1,38 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks that if for a node all exposed references are foreign, +/// that a wildcard access gets treated as foreign to it. +pub fn main() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + let ref3 = unsafe { &mut *ptr_base }; + + // Both references get exposed. + let int1 = ref1 as *mut u32 as usize; + let _int2 = ref2 as *mut u32 as usize; + + let wild = int1 as *mut u32; + + // ┌────────────┐ + // │ │ + // │ ptr_base ├──────────────┬───────────────────┐ + // │ │ │ │ + // └──────┬─────┘ │ │ + // │ │ │ + // │ │ │ + // ▼ ▼ ▼ + // ┌────────────┐ ┌────────────┐ ┌───────────┐ + // │ │ │ │ │ │ + // │ ref1(Res)* │ │ ref2(Res)* │ │ ref3(Res) │ + // │ │ │ │ │ │ + // └────────────┘ └────────────┘ └───────────┘ + + // Disables ref3 as both exposed pointers are foreign to it. + unsafe { wild.write(13) }; + + // Fails because ref3 is disabled. + let _fail = *ref3; //~ ERROR: /read access through .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_foreign.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_foreign.stderr new file mode 100644 index 0000000000000..85c836b4b36f1 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_foreign.stderr @@ -0,0 +1,25 @@ +error: Undefined Behavior: read access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_foreign.rs:LL:CC + | +LL | let _fail = *ref3; + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the accessed tag has state Disabled which forbids this child read access +help: the accessed tag was created here, in the initial state Reserved + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_foreign.rs:LL:CC + | +LL | let ref3 = unsafe { &mut *ptr_base }; + | ^^^^^^^^^^^^^^ +help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4] + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_foreign.rs:LL:CC + | +LL | unsafe { wild.write(13) }; + | ^^^^^^^^^^^^^^ + = help: this transition corresponds to a loss of read and write permissions + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.rs new file mode 100644 index 0000000000000..b47eaf839ced1 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.rs @@ -0,0 +1,50 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks if a local access gets correctly triggered, if we know that +/// all exposed references are local to a node. +pub fn main() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + + // Both references get exposed. + let int1 = ref1 as *mut u32 as usize; + let _int2 = ref2 as *mut u32 as usize; + + let wild = int1 as *mut u32; + + // Activates ptr_base. + unsafe { wild.write(41) }; + + // ┌─────────────┐ + // │ │ + // │ x (Act) │ + // │ │ + // └──────┬──────┘ + // │ + // │ + // ▼ + // ┌────────────────┐ + // │ │ + // │ ptr_base (Act) ├──────────┐ + // │ │ │ + // └──────┬─────────┘ │ + // │ │ + // │ │ + // ▼ ▼ + // ┌────────────┐ ┌────────────┐ + // │ │ │ │ + // │ ref1(Res)* │ │ ref2(Res)* │ + // │ │ │ │ + // └────────────┘ └────────────┘ + + // We read from x causing a foreign access to ptr_base, freezing it + // (as the previous wildcard access has made it active). + let _y = x; + + // While both exposed references are still enabled for writes, any write + // through them would cause UB at ptr_base. + unsafe { wild.write(0) }; //~ ERROR: /write access through at .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.stderr new file mode 100644 index 0000000000000..ca4a2533f7b68 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.stderr @@ -0,0 +1,32 @@ +error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.rs:LL:CC + | +LL | unsafe { wild.write(0) }; + | ^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the accessed tag is a child of the conflicting tag + = help: the conflicting tag has state Frozen which forbids this child write access +help: the conflicting tag was created here, in the initial state Reserved + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.rs:LL:CC + | +LL | let ptr_base = &mut x as *mut u32; + | ^^^^^^ +help: the conflicting tag later transitioned to Unique due to a child write access at offsets [0x0..0x4] + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.rs:LL:CC + | +LL | unsafe { wild.write(41) }; + | ^^^^^^^^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference +help: the conflicting tag later transitioned to Frozen due to a foreign read access at offsets [0x0..0x4] + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_local.rs:LL:CC + | +LL | let _y = x; + | ^ + = help: this transition corresponds to a loss of write permissions + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_unique_writer.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_unique_writer.rs new file mode 100644 index 0000000000000..fb0b43f20dc15 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_unique_writer.rs @@ -0,0 +1,38 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks if we correctly determine the correct exposed reference a write +/// access could happen through, if there are also exposed reference +/// through which only a read access could happen. +pub fn main() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &*ptr_base }; + + // Both references get exposed. + let int1 = ref1 as *mut u32 as usize; + let _int2 = ref2 as *const u32 as usize; + + let wild = int1 as *mut u32; + + // ┌────────────┐ + // │ │ + // │ ptr_base ├──────────────┐ + // │ │ │ + // └──────┬─────┘ │ + // │ │ + // │ │ + // ▼ ▼ + // ┌────────────┐ ┌────────────┐ + // │ │ │ │ + // │ ref1(Res)* │ │ ref2(Frz)* │ + // │ │ │ │ + // └────────────┘ └────────────┘ + + // Disables ref2 as the only write could happen through ref1. + unsafe { wild.write(13) }; + + // Fails because ref2 is disabled. + let _fail = *ref2; //~ ERROR: /read access through .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_unique_writer.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_unique_writer.stderr new file mode 100644 index 0000000000000..a07febaa84c94 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/multi_exposed_siblings_unique_writer.stderr @@ -0,0 +1,25 @@ +error: Undefined Behavior: read access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_unique_writer.rs:LL:CC + | +LL | let _fail = *ref2; + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the accessed tag has state Disabled which forbids this child read access +help: the accessed tag was created here, in the initial state Frozen + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_unique_writer.rs:LL:CC + | +LL | let ref2 = unsafe { &*ptr_base }; + | ^^^^^^^^^^ +help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4] + --> tests/fail/tree_borrows/wildcard/multi_exposed_siblings_unique_writer.rs:LL:CC + | +LL | unsafe { wild.write(13) }; + | ^^^^^^^^^^^^^^ + = help: this transition corresponds to a loss of read permissions + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/protector_conflicted.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/protector_conflicted.rs new file mode 100644 index 0000000000000..620cf34d2a088 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/protector_conflicted.rs @@ -0,0 +1,26 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks that wildcard accesses correctly infers the allowed permissions +/// on protected conflicted pointers. +pub fn main() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + + let protect = |arg: &mut u32| { + // Expose arg. + let int = arg as *mut u32 as usize; + let wild = int as *mut u32; + + // Does a foreign read to arg marking it as conflicted and making child + // writes UB while it's protected. + let _x = *ref2; + + // The only exposed reference (arg) doesn't allow child writes, so this is UB. + unsafe { *wild = 4 }; //~ ERROR: /write access through at .* is forbidden/ + }; + + protect(ref1); +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/protector_conflicted.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/protector_conflicted.stderr new file mode 100644 index 0000000000000..5486eee4f063f --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/protector_conflicted.stderr @@ -0,0 +1,21 @@ +error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/protector_conflicted.rs:LL:CC + | +LL | unsafe { *wild = 4 }; + | ^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: there are no exposed tags which may perform this access here + = note: BACKTRACE: + = note: inside closure at tests/fail/tree_borrows/wildcard/protector_conflicted.rs:LL:CC +note: inside `main` + --> tests/fail/tree_borrows/wildcard/protector_conflicted.rs:LL:CC + | +LL | protect(ref1); + | ^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_disable.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_disable.rs new file mode 100644 index 0000000000000..1f2236a70f59f --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_disable.rs @@ -0,0 +1,35 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks that with only one exposed reference, that if this reference gets +/// disabled no wildcard accesses are possible. +pub fn main() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + + let int1 = ref1 as *mut u32 as usize; + let wild = int1 as *mut u32; + + // ┌────────────┐ + // │ │ + // │ ptr_base ├───────────┐ + // │ │ │ + // └──────┬─────┘ │ + // │ │ + // │ │ + // ▼ ▼ + // ┌────────────┐ ┌───────────┐ + // │ │ │ │ + // │ ref1(Res)* │ │ ref2(Res) │ + // │ │ │ │ + // └────────────┘ └───────────┘ + + // Disables ref1. + *ref2 = 13; + + // Tries to do a wildcard access through the only exposed reference ref1, + // which is disabled. + let _fail = unsafe { *wild }; //~ ERROR: /read access through .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_disable.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_disable.stderr new file mode 100644 index 0000000000000..170d00694d10a --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_disable.stderr @@ -0,0 +1,14 @@ +error: Undefined Behavior: read access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/single_exposed_disable.rs:LL:CC + | +LL | let _fail = unsafe { *wild }; + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: there are no exposed tags which may perform this access here + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_foreign.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_foreign.rs new file mode 100644 index 0000000000000..d8f2ab16eeb76 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_foreign.rs @@ -0,0 +1,34 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks that with only one exposed reference, wildcard accesses +/// correctly cause foreign accesses. +pub fn main() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + + let int1 = ref1 as *mut u32 as usize; + let wild = int1 as *mut u32; + + // ┌────────────┐ + // │ │ + // │ ptr_base ├───────────┐ + // │ │ │ + // └──────┬─────┘ │ + // │ │ + // │ │ + // ▼ ▼ + // ┌────────────┐ ┌───────────┐ + // │ │ │ │ + // │ ref1(Res)* │ │ ref2(Res) │ + // │ │ │ │ + // └────────────┘ └───────────┘ + + // Write through the wildcard to the only exposed reference ref1, + // disabling ref2. + unsafe { wild.write(13) }; + + let _fail = *ref2; //~ ERROR: /read access through .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_foreign.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_foreign.stderr new file mode 100644 index 0000000000000..98d22598d6580 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_foreign.stderr @@ -0,0 +1,25 @@ +error: Undefined Behavior: read access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/single_exposed_foreign.rs:LL:CC + | +LL | let _fail = *ref2; + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the accessed tag has state Disabled which forbids this child read access +help: the accessed tag was created here, in the initial state Reserved + --> tests/fail/tree_borrows/wildcard/single_exposed_foreign.rs:LL:CC + | +LL | let ref2 = unsafe { &mut *ptr_base }; + | ^^^^^^^^^^^^^^ +help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4] + --> tests/fail/tree_borrows/wildcard/single_exposed_foreign.rs:LL:CC + | +LL | unsafe { wild.write(13) }; + | ^^^^^^^^^^^^^^ + = help: this transition corresponds to a loss of read and write permissions + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_local.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_local.rs new file mode 100644 index 0000000000000..e5a246c505473 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_local.rs @@ -0,0 +1,22 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// Checks if a local access gets correctly triggered during wildcard access, +/// if we know that the only exposed reference is local to the node. +pub fn main() { + let mut x: u32 = 0; + + let ref1 = &mut x; + + let int = ref1 as *mut u32 as usize; + let wild = int as *mut u32; + + // Activates ref1. + unsafe { wild.write(41) }; + + // Reads from x causing a foreign read on ref1, freezing it + // (because it was active). + let _y = x; + + // The only exposed reference (ref1) is frozen, so wildcard writes are UB. + unsafe { wild.write(0) }; //~ ERROR: /write access through at .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_local.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_local.stderr new file mode 100644 index 0000000000000..a33cd5519da4d --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_local.stderr @@ -0,0 +1,14 @@ +error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/single_exposed_local.rs:LL:CC + | +LL | unsafe { wild.write(0) }; + | ^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: there are no exposed tags which may perform this access here + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_only_ro.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_only_ro.rs new file mode 100644 index 0000000000000..c8e75636a07dd --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_only_ro.rs @@ -0,0 +1,11 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +/// If we have only exposed read-only pointers, doing a write through a +/// wildcard ptr should fail. +fn main() { + let mut x = 0; + let _fool = &mut x as *mut i32; // this would have fooled the old untagged pointer logic + let addr = (&x as *const i32).expose_provenance(); + let ptr = std::ptr::with_exposed_provenance_mut::(addr); + unsafe { *ptr = 0 }; //~ ERROR: /write access through at .* is forbidden/ +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_only_ro.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_only_ro.stderr new file mode 100644 index 0000000000000..2d643a852e4cd --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/single_exposed_only_ro.stderr @@ -0,0 +1,14 @@ +error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden + --> tests/fail/tree_borrows/wildcard/single_exposed_only_ro.rs:LL:CC + | +LL | unsafe { *ptr = 0 }; + | ^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: there are no exposed tags which may perform this access here + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.rs b/src/tools/miri/tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.rs new file mode 100644 index 0000000000000..71e98e7056021 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.rs @@ -0,0 +1,15 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance +//@error-in-other-file: /deallocation through .* is forbidden/ + +fn inner(x: &mut i32, f: fn(usize)) { + // `f` may mutate, but it may not deallocate! + // `f` takes a raw pointer so that the only protector + // is that on `x` + f(x as *mut i32 as usize) +} + +fn main() { + inner(Box::leak(Box::new(0)), |raw| { + drop(unsafe { Box::from_raw(raw as *mut i32) }); + }); +} diff --git a/src/tools/miri/tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.stderr b/src/tools/miri/tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.stderr new file mode 100644 index 0000000000000..de92cf91e3e85 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.stderr @@ -0,0 +1,42 @@ +error: Undefined Behavior: deallocation through at ALLOC[0x0] is forbidden + --> RUSTLIB/alloc/src/boxed.rs:LL:CC + | +LL | self.1.deallocate(From::from(ptr.cast()), layout); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the allocation of the accessed tag also contains the strongly protected tag + = help: the strongly protected tag disallows deallocations +help: the strongly protected tag was created here, in the initial state Reserved + --> tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.rs:LL:CC + | +LL | fn inner(x: &mut i32, f: fn(usize)) { + | ^ + = note: BACKTRACE (of the first span): + = note: inside ` as std::ops::Drop>::drop` at RUSTLIB/alloc/src/boxed.rs:LL:CC + = note: inside `std::ptr::drop_in_place::> - shim(Some(std::boxed::Box))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC + = note: inside `std::mem::drop::>` at RUSTLIB/core/src/mem/mod.rs:LL:CC +note: inside closure + --> tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.rs:LL:CC + | +LL | drop(unsafe { Box::from_raw(raw as *mut i32) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: inside `<{closure@tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.rs:LL:CC} as std::ops::FnOnce<(usize,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC +note: inside `inner` + --> tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.rs:LL:CC + | +LL | f(x as *mut i32 as usize) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: inside `main` + --> tests/fail/tree_borrows/wildcard/strongly_protected_wildcard.rs:LL:CC + | +LL | / inner(Box::leak(Box::new(0)), |raw| { +LL | | drop(unsafe { Box::from_raw(raw as *mut i32) }); +LL | | }); + | |______^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/stacked_borrows/int-to-ptr.rs b/src/tools/miri/tests/pass/both_borrows/int-to-ptr.rs similarity index 97% rename from src/tools/miri/tests/pass/stacked_borrows/int-to-ptr.rs rename to src/tools/miri/tests/pass/both_borrows/int-to-ptr.rs index 8a05fca3f312f..830feed7e2b01 100644 --- a/src/tools/miri/tests/pass/stacked_borrows/int-to-ptr.rs +++ b/src/tools/miri/tests/pass/both_borrows/int-to-ptr.rs @@ -1,4 +1,6 @@ +//@revisions: stack tree //@compile-flags: -Zmiri-permissive-provenance +//@[tree]compile-flags: -Zmiri-tree-borrows use std::ptr; // Just to make sure that casting a ref to raw, to int and back to raw diff --git a/src/tools/miri/tests/pass/stacked_borrows/issue-miri-2389.rs b/src/tools/miri/tests/pass/both_borrows/issue-miri-2389.rs similarity index 86% rename from src/tools/miri/tests/pass/stacked_borrows/issue-miri-2389.rs rename to src/tools/miri/tests/pass/both_borrows/issue-miri-2389.rs index 469122095e512..f9d87b7dea8fe 100644 --- a/src/tools/miri/tests/pass/stacked_borrows/issue-miri-2389.rs +++ b/src/tools/miri/tests/pass/both_borrows/issue-miri-2389.rs @@ -1,3 +1,6 @@ +//@revisions: stack tree +//@compile-flags: -Zmiri-permissive-provenance +//@[tree]compile-flags: -Zmiri-tree-borrows use std::cell::Cell; fn main() { diff --git a/src/tools/miri/tests/pass/issues/issue-miri-4698-stashed-diagnostic.rs b/src/tools/miri/tests/pass/issues/issue-miri-4698-stashed-diagnostic.rs new file mode 100644 index 0000000000000..3467d2d273797 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-miri-4698-stashed-diagnostic.rs @@ -0,0 +1,10 @@ +// This test seems to involve a "stashed diagnostic" (or at least it used to at the time of +// writing). Ensure we handle that correctly. + +pub trait Trait { + type Assoc: Assoc; +} + +pub trait Assoc {} + +fn main() {} diff --git a/src/tools/miri/tests/pass/stacked_borrows/issue-miri-2389.stderr b/src/tools/miri/tests/pass/stacked_borrows/issue-miri-2389.stderr deleted file mode 100644 index 363f8a20f8daa..0000000000000 --- a/src/tools/miri/tests/pass/stacked_borrows/issue-miri-2389.stderr +++ /dev/null @@ -1,12 +0,0 @@ -warning: integer-to-pointer cast - --> tests/pass/stacked_borrows/issue-miri-2389.rs:LL:CC - | -LL | let wildcard = &root0 as *const Cell as usize as *const Cell; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast - | - = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program - = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation - = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead - = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics - = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning - diff --git a/src/tools/miri/tests/pass/tree_borrows/wildcard/undetected_ub.rs b/src/tools/miri/tests/pass/tree_borrows/wildcard/undetected_ub.rs new file mode 100644 index 0000000000000..c34fbcb50119b --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/wildcard/undetected_ub.rs @@ -0,0 +1,145 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance +// NOTE: This file documents UB that is not detected by wildcard provenance. + +pub fn main() { + uncertain_provenance(); + protected_exposed(); + protected_wildcard(); +} + +/// Currently, if we do not know for a tag if an access is local or foreign, +/// then we do not do any state transitions on that tag. However, to implement +/// proper provenance we would have to instead pick the correct transition +/// non-deterministically. +/// +/// This test contains such UB that will not be detectable with wildcard provenance, +/// but would be detectable if we implemented this behavior correctly. +pub fn uncertain_provenance() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + // We create 2 mutable references, each with a unique tag. + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + + // Both references get exposed. + let int1 = ref1 as *mut u32 as usize; + let _int2 = ref2 as *mut u32 as usize; + //ref1 : Reserved + //ref2 : Reserved + + // We need to pick the "correct" tag for wild from the exposed tags. + let wild = int1 as *mut u32; + // wild=ref1 wild=ref2 + //ref1 : Reserved Reserved + //ref2 : Reserved Reserved + + // We write to wild, disabling the other tag. + unsafe { wild.write(13) }; + // wild=ref1 wild=ref2 + //ref1 : Unique Disabled + //ref2 : Disabled Unique + + // We access both references, even though one of them should be + // disabled under proper exposed provenance. + // This is UB, however, wildcard provenance cannot detect this. + assert_eq!(*ref1, 13); + // wild=ref1 wild=ref2 + //ref1 : Unique UB + //ref2 : Disabled Frozen + assert_eq!(*ref2, 13); + // wild=ref1 wild=ref2 + //ref1 : Frozen UB + //ref2 : UB Frozen +} + +/// If a reference is protected, then all foreign writes to it cause UB. +/// This effectively means any write needs to happen through a child of +/// the protected reference. +/// With this information we could further narrow the possible candidates +/// for a wildcard write. +/// However, currently tree borrows doesn't do this, so this test has UB +/// that isn't detected. +pub fn protected_exposed() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + + let _int2 = ref2 as *mut u32 as usize; + + fn protect(ref3: &mut u32) { + let int3 = ref3 as *mut u32 as usize; + + // ┌────────────┐ + // │ │ + // │ ptr_base ├──────────────┐ + // │ │ │ + // └──────┬─────┘ │ + // │ │ + // │ │ + // ▼ ▼ + // ┌────────────┐ ┌────────────┐ + // │ │ │ │ + // │ ref1(Res) │ │ ref2(Res)* │ + // │ │ │ │ + // └──────┬─────┘ └────────────┘ + // │ + // │ + // ▼ + // ┌────────────┐ + // │ │ + // │ ref3(Res)* │ + // │ │ + // └────────────┘ + + // Since ref3 is protected, we could know that every write from outside it will be UB. + // This means we know that the access is through ref3, disabling ref2. + let wild = int3 as *mut u32; + unsafe { wild.write(13) } + } + protect(ref1); + + // ref2 is disabled, so this read causes UB, but we currently don't protect this. + let _fail = *ref2; +} + +/// Currently, we do not assign protectors to wildcard references. +/// This test has UB because it does a foreign write to a protected reference. +/// However, that reference is a wildcard, so this doesn't get detected. +#[allow(unused_variables)] +pub fn protected_wildcard() { + let mut x: u32 = 32; + let ref1 = &mut x; + let ref2 = &mut *ref1; + + let int = ref2 as *mut u32 as usize; + let wild = int as *mut u32; + let wild_ref = unsafe { &mut *wild }; + + let mut protect = |arg: &mut u32| { + // arg is a protected pointer with wildcard provenance. + + // ┌────────────┐ + // │ │ + // │ ref1(Res) │ + // │ │ + // └──────┬─────┘ + // │ + // │ + // ▼ + // ┌────────────┐ + // │ │ + // │ ref2(Res)* │ + // │ │ + // └────────────┘ + + // Writes to ref1, disabling ref2, i.e. disabling all exposed references. + // Since a wildcard reference is protected, this is UB. But we currently don't detect this. + *ref1 = 13; + }; + + // We pass a pointer with wildcard provenance to the function. + protect(wild_ref); +} diff --git a/src/tools/miri/tests/pass/tree_borrows/wildcard/wildcard.rs b/src/tools/miri/tests/pass/tree_borrows/wildcard/wildcard.rs new file mode 100644 index 0000000000000..c406bfe01f62c --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/wildcard/wildcard.rs @@ -0,0 +1,171 @@ +//@compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance + +pub fn main() { + multiple_exposed_siblings(); + multiple_exposed_child(); + dealloc(); + protector(); + protector_conflicted_release(); + returned_mut_is_usable(); +} + +/// Checks that an access through a wildcard reference +/// doesn't disable any exposed references. +/// It tests this with exposed references that are siblings of each other. +pub fn multiple_exposed_siblings() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + + // Both references get exposed. + let int1 = ref1 as *mut u32 as usize; + let _int2 = ref2 as *mut u32 as usize; + + let wild = int1 as *mut u32; + + // ┌────────────┐ + // │ │ + // │ ptr_base ├────────────┐ + // │ │ │ + // └──────┬─────┘ │ + // │ │ + // │ │ + // ▼ ▼ + // ┌────────────┐ ┌────────────┐ + // │ │ │ │ + // │ ref1(Res)* │ │ ref2(Res)* │ + // │ │ │ │ + // └────────────┘ └────────────┘ + + // Writes through either of the two exposed references. + // We do not know which so we cannot disable the other. + unsafe { wild.write(13) }; + + // Reading through either of these references should be valid. + assert_eq!(*ref2, 13); +} + +/// Checks that an access through a wildcard reference +/// doesn't disable any exposed references. +/// It tests this with exposed references where one is the ancestor of the other. +pub fn multiple_exposed_child() { + let mut x: u32 = 42; + + let ref1 = &mut x; + let int1 = ref1 as *mut u32 as usize; + + let ref2 = &mut *ref1; + + let ref3 = &mut *ref2; + let _int3 = ref3 as *mut u32 as usize; + + let wild = int1 as *mut u32; + + // ┌────────────┐ + // │ │ + // │ ref1(Res)* │ + // │ │ + // └──────┬─────┘ + // │ + // │ + // ▼ + // ┌────────────┐ + // │ │ + // │ ref2(Res) │ + // │ │ + // └──────┬─────┘ + // │ + // │ + // ▼ + // ┌────────────┐ + // │ │ + // │ ref3(Res)* │ + // │ │ + // └────────────┘ + + // This writes either through ref1 or ref3, which is either a child or foreign access to ref2. + unsafe { wild.write(42) }; + + // Reading from ref2 still works, since the previous access could have been through its child. + // This also freezes ref3. + let _x = *ref2; + + // We can still write through wild, as there is still the exposed ref1 with write permissions. + unsafe { wild.write(43) }; +} + +/// Checks that we can deallocate through a wildcard reference. +fn dealloc() { + use std::alloc::Layout; + let x = unsafe { std::alloc::alloc_zeroed(Layout::new::()) as *mut u32 }; + let ref1 = unsafe { &mut *x }; + let int = ref1 as *mut u32 as usize; + let wild = int as *mut u32; + + unsafe { std::alloc::dealloc(wild as *mut u8, Layout::new::()) }; +} + +/// Checks that we can pass a wildcard reference to a function. +fn protector() { + fn protect(arg: &mut u32) { + *arg = 4; + } + let mut x: u32 = 32; + let ref1 = &mut x; + let int = ref1 as *mut u32 as usize; + let wild = int as *mut u32; + let wild_ref = unsafe { &mut *wild }; + + protect(wild_ref); + + assert_eq!(*ref1, 4); +} + +/// Checks whether we correctly handle the protector being released on +/// a conflicted exposed reference. +fn protector_conflicted_release() { + let mut x: u32 = 42; + + let ptr_base = &mut x as *mut u32; + let ref1 = unsafe { &mut *ptr_base }; + let ref2 = unsafe { &mut *ptr_base }; + + let protect = |arg: &mut u32| { + // Expose arg. + let int = arg as *mut u32 as usize; + let wild = int as *mut u32; + + // Do a foreign read to arg marking it as conflicted and making child_writes UB while its protected. + let _x = *ref2; + + return wild; + }; + + let wild = protect(ref1); + + // The protector on arg got released so writes through arg should work again. + unsafe { *wild = 4 }; +} + +/// Analogous to same test in `../tree-borrows.rs` but with a protected wildcard reference. +fn returned_mut_is_usable() { + // NOTE: Currently we ignore protectors on wildcard references. + fn reborrow(x: &mut u8) -> &mut u8 { + let y = &mut *x; + // Activate the reference so that it is vulnerable to foreign reads. + *y = *y; + y + // An implicit read through `x` is inserted here. + } + let mut x: u8 = 0; + let ref1 = &mut x; + let int = ref1 as *mut u8 as usize; + let wild = int as *mut u8; + let wild_ref = unsafe { &mut *wild }; + + let y = reborrow(wild_ref); + + *y = 1; +}