From e45acd458080be1cdbddca01280926dd68e4c600 Mon Sep 17 00:00:00 2001 From: Herman Venter Date: Wed, 8 Mar 2023 12:53:17 -0800 Subject: [PATCH] 2023-03-08 (#1199) --- Cargo.lock | 214 ++++++----- binaries/summary_store.tar | Bin 1992704 -> 1909760 bytes checker/Cargo.toml | 2 +- checker/src/abstract_value.rs | 3 + checker/src/block_visitor.rs | 340 ++++++++++++------ checker/src/body_visitor.rs | 19 +- checker/src/call_visitor.rs | 17 +- checker/src/callbacks.rs | 1 - checker/src/fixed_point_visitor.rs | 8 +- checker/src/options.rs | 9 +- checker/src/path.rs | 23 +- checker/src/type_visitor.rs | 57 +-- checker/src/utils.rs | 10 +- checker/tests/call_graph/fnptr_fold.rs | 10 +- checker/tests/call_graph/static_fold.rs | 8 +- checker/tests/integration_tests.rs | 18 +- checker/tests/run-pass/binary_overflow.rs | 85 +---- checker/tests/run-pass/box_fail.rs | 3 +- checker/tests/run-pass/constant_time_taint.rs | 20 +- checker/tests/run-pass/crate_traversal.rs | 6 +- checker/tests/run-pass/false_precon.rs | 5 +- checker/tests/run-pass/tag_empty_struct.rs | 7 +- checker/tests/run-pass/trait_call.rs | 16 +- rust-toolchain.toml | 2 +- standard_contracts/src/foreign_contracts.rs | 6 +- 25 files changed, 492 insertions(+), 397 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ae54795..457c676f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,9 +79,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "camino" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055" +checksum = "6031a462f977dd38968b6f23378356512feeace69cef817e1a4475108093cec3" dependencies = [ "serde", ] @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a" +checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07" dependencies = [ "camino", "cargo-platform", @@ -111,9 +111,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cexpr" @@ -132,9 +132,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clang-sys" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a" dependencies = [ "glob", "libc", @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" dependencies = [ "cfg-if", "crossbeam-utils", @@ -206,9 +206,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -217,9 +217,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", "cfg-if", @@ -230,9 +230,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", ] @@ -274,9 +274,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "env_logger" @@ -314,23 +314,23 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] name = "filetime" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -405,6 +405,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "humantime" version = "2.1.0" @@ -438,24 +444,24 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "is-terminal" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -469,9 +475,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "lazy_static" @@ -546,9 +552,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] @@ -561,7 +567,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mirai" -version = "1.1.4" +version = "1.1.5" dependencies = [ "bincode", "cargo_metadata", @@ -603,9 +609,9 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.2" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -660,9 +666,9 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "petgraph" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", "indexmap", @@ -676,9 +682,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -724,9 +730,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ "either", "rayon-core", @@ -734,9 +740,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -755,9 +761,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -770,15 +776,6 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "rpds" version = "0.12.0" @@ -803,23 +800,23 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f" [[package]] name = "rustix" -version = "0.36.6" +version = "0.36.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549" +checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "same-file" @@ -847,18 +844,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.152" +version = "1.0.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "3a382c72b4ba118526e187430bb4963cd6d55051ebf13d9b25574d379cc98d20" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "1ef476a5790f0f6decbc66726b6e5d63680ed518283e64c7df415989d880954f" dependencies = [ "proc-macro2", "quote", @@ -867,9 +864,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ "itoa", "ryu", @@ -942,9 +939,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -978,23 +975,22 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" dependencies = [ "cfg-if", "fastrand", - "libc", "redox_syscall", - "remove_dir_all", - "winapi", + "rustix", + "windows-sys 0.42.0", ] [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -1007,18 +1003,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" dependencies = [ "proc-macro2", "quote", @@ -1042,9 +1038,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "untrustworthy_inputs" @@ -1123,47 +1119,71 @@ dependencies = [ "windows_x86_64_msvc", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "xattr" @@ -1177,7 +1197,7 @@ dependencies = [ [[package]] name = "z3-sys" version = "0.7.1" -source = "git+https://github.com/prove-rs/z3.rs.git#7db1ac1b6c00719edbb44258d37d939bef1f87ed" +source = "git+https://github.com/prove-rs/z3.rs.git#ee521b74bbe0e76113b2399e1a4640b3d6995181" dependencies = [ "bindgen", "cmake", diff --git a/binaries/summary_store.tar b/binaries/summary_store.tar index b82eb48212dac8999dcbb47a9dd1a31bb26534a7..266cd5de7b28e8230aebad705531d5fcec8110d4 100644 GIT binary patch delta 14187 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 diff --git a/checker/Cargo.toml b/checker/Cargo.toml index da7fa43a..37faf44c 100644 --- a/checker/Cargo.toml +++ b/checker/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "mirai" -version = "1.1.4" +version = "1.1.5" authors = ["Herman Venter "] description = "A static analysis tool for Rust, based on Abstract Interpretation of MIR" repository = "https://github.com/facebookexperimental/MIRAI" diff --git a/checker/src/abstract_value.rs b/checker/src/abstract_value.rs index dbba4c9c..8ba63750 100644 --- a/checker/src/abstract_value.rs +++ b/checker/src/abstract_value.rs @@ -103,6 +103,9 @@ pub const TOP: AbstractValue = make_value(Expression::Top); /// An abstract domain element that all represent the single concrete value, true. pub const TRUE: AbstractValue = make_value(Expression::CompileTimeConstant(ConstantDomain::True)); +/// An abstract domain element that all represent an empty tuple or empty struct. +pub const UNIT: AbstractValue = make_value(Expression::CompileTimeConstant(ConstantDomain::Unit)); + /// An abstract domain element that represents a dummy untagged value. /// It is only used as the default value for the tag field of non-scalar values. pub const DUMMY_UNTAGGED_VALUE: AbstractValue = diff --git a/checker/src/block_visitor.rs b/checker/src/block_visitor.rs index 96ccce8f..612613f6 100644 --- a/checker/src/block_visitor.rs +++ b/checker/src/block_visitor.rs @@ -23,8 +23,7 @@ use rustc_middle::ty::{ use rustc_target::abi::{Primitive, TagEncoding, VariantIdx, Variants}; use crate::abstract_value; -use crate::abstract_value::AbstractValue; -use crate::abstract_value::AbstractValueTrait; +use crate::abstract_value::{AbstractValue, AbstractValueTrait, BOTTOM}; use crate::body_visitor::BodyVisitor; use crate::call_visitor::CallVisitor; use crate::constant_domain::{ConstantDomain, FunctionReference}; @@ -116,6 +115,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com mir::StatementKind::Assign(box (place, rvalue)) => { self.visit_assign(place, rvalue.borrow()) } + mir::StatementKind::ConstEvalCounter => (), mir::StatementKind::FakeRead(..) => assume_unreachable!(), mir::StatementKind::SetDiscriminant { place, @@ -501,7 +501,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com callee_generic_arguments, &actual_argument_types, ); - let fun_ty = self.bv.tcx.type_of(destructor.did); + let fun_ty = self.bv.tcx.type_of(destructor.did).skip_binder(); let func_const = self .visit_function_reference(destructor.did, fun_ty, Some(substs)) .clone(); @@ -669,7 +669,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com // function was visited, so the cached specialized generic argument list created there // might not be specialized enough. if !actual_argument_types.is_empty() && !utils::are_concrete(callee_generic_arguments) { - let fty = self.bv.tcx.type_of(callee_def_id); + let fty = self.bv.tcx.type_of(callee_def_id).skip_binder(); if let TyKind::FnDef(_, substs) = fty.kind() { for (i, generic_ty_arg) in substs.types().enumerate() { if let TyKind::Param(t_par) = generic_ty_arg.kind() { @@ -680,7 +680,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com .type_visitor() .get_dereferenced_type(actual_argument_types[0]) .into(); - callee_generic_arguments = self.bv.tcx.intern_substs(&gen_args); + callee_generic_arguments = self.bv.tcx.mk_substs(&gen_args); break; } } @@ -779,7 +779,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com &value.expression { let ty = if let Some(def_id) = func_ref.def_id { - self.bv.tcx.type_of(def_id) + self.bv.tcx.type_of(def_id).skip_binder() } else { self.type_visitor() .get_path_rustc_type(path, self.bv.current_span) @@ -1011,7 +1011,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com .type_visitor() .specialize_substs(substs, &self.type_visitor().generic_argument_map); self.bv.cv.substs_cache.insert(*def_id, substs); - let closure_ty = self.bv.tcx.type_of(*def_id); + let closure_ty = self.bv.tcx.type_of(*def_id).skip_binder(); let map = self .type_visitor() .get_generic_arguments_map(*def_id, substs, &[]); @@ -1182,7 +1182,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com match (self.bv.post_condition.clone(), self.bv.post_condition_block) { (Some(last_cond), Some(last_block)) => { let dominators = self.bv.mir.basic_blocks.dominators(); - if dominators.is_dominated_by(this_block, last_block) { + if dominators.dominates(last_block, this_block) { // We can extend the last condition as all paths to this condition // lead over it self.bv.post_condition = Some(last_cond.and(promotable_condition)); @@ -1705,8 +1705,8 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com mir::Rvalue::Discriminant(place) => { self.visit_discriminant(path, place); } - mir::Rvalue::Aggregate(aggregate_kinds, operands) => { - self.visit_aggregate(path, aggregate_kinds, operands); + mir::Rvalue::Aggregate(aggregate_kind, operands) => { + self.visit_aggregate(path, aggregate_kind, operands); } mir::Rvalue::ShallowInitBox(operand, ty) => { self.visit_shallow_init_box(path, operand, *ty); @@ -2100,6 +2100,13 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com .set_path_rustc_type(path.clone(), source_type); } } + if self.type_visitor().is_slice_pointer(ty.kind()) { + let source_type = self + .type_visitor() + .get_path_rustc_type(&source_path, self.bv.current_span); + let value = self.bv.lookup_path_and_refine_result(source_path.clone(), source_type); + self.convert_sized_array_pointer_to_unsized_pointer(&source_path, &value, &path) + } for (p, value) in value_map .iter() .filter(|(p, _)| source_path == **p || p.is_rooted_by(&source_path)) @@ -2115,28 +2122,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com .type_visitor() .get_path_rustc_type(&target_path, self.bv.current_span); if self.type_visitor().is_slice_pointer(target_type.kind()) { - // convert the source thin pointer to a fat pointer if the target path is a slice pointer - let thin_pointer_path = Path::new_field(target_path.clone(), 0); - self.bv.update_value_at(thin_pointer_path, value.clone()); - let source_type = self - .type_visitor() - .get_path_rustc_type(p, self.bv.current_span); - // Now write the length alongside the thin pointer - if let TyKind::Array(_, len) = self - .type_visitor() - .get_dereferenced_type(source_type) - .kind() - { - let length_path = target_path - .add_or_replace_selector(Rc::new(PathSelector::Field(1))); - let length_value = self.visit_const(len); - self.bv.update_value_at(length_path, length_value); - } else { - assume_unreachable!( - "non array thin pointer type {:?}", - source_type - ); - } + self.convert_sized_array_pointer_to_unsized_pointer(p, value, &target_path) } else { // just copy self.bv.update_value_at(target_path, value.clone()); @@ -2145,7 +2131,10 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com } return; } - let source_path = self.visit_rh_place(place); + let mut source_path = self.visit_rh_place(place); + if matches!(cast_kind, mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_))){ + source_path = Path::new_function(source_path) + } self.bv .copy_or_move_elements(path, source_path, ty, is_move); } @@ -2201,6 +2190,31 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com } } + fn convert_sized_array_pointer_to_unsized_pointer( + &mut self, + p: &Rc, + value: &Rc, + target_path: &Rc, + ) { + let thin_pointer_path = Path::new_field(target_path.clone(), 0); + self.bv.update_value_at(thin_pointer_path, value.clone()); + let source_type = self + .type_visitor() + .get_path_rustc_type(p, self.bv.current_span); + // Now write the length alongside the thin pointer + if let TyKind::Array(_, len) = self + .type_visitor() + .get_dereferenced_type(source_type) + .kind() + { + let length_path = target_path.add_or_replace_selector(Rc::new(PathSelector::Field(1))); + let length_value = self.visit_const(len); + self.bv.update_value_at(length_path, length_value); + } else { + assume_unreachable!("non array thin pointer type {:?}", source_type); + } + } + /// Apply the given binary operator to the two operands and assign result to path. #[logfn_inputs(TRACE)] fn visit_binary_op( @@ -2360,25 +2374,109 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com self.bv.update_value_at(path, discriminant_value); } - /// Currently only survives in the MIR that MIRAI sees, if the aggregate is an array. - /// See https://github.com/rust-lang/rust/issues/48193. - /// Copies the values from the operands to the target path and sets the length field. - /// The target path identifies stack storage for the array and is not a fat pointer to the heap. #[logfn_inputs(TRACE)] fn visit_aggregate( &mut self, path: Rc, - aggregate_kinds: &mir::AggregateKind<'tcx>, + aggregate_kind: &mir::AggregateKind<'tcx>, operands: &[mir::Operand<'tcx>], ) { - precondition!(matches!(aggregate_kinds, mir::AggregateKind::Array(..))); - let length_path = Path::new_length(path.clone()); - let length_value = self.get_u128_const_val(operands.len() as u128); - self.bv.update_value_at(length_path, length_value); - for (i, operand) in operands.iter().enumerate() { - let index_value = self.get_u128_const_val(i as u128); - let index_path = Path::new_index(path.clone(), index_value); - self.visit_used_operand(index_path, operand); + match aggregate_kind { + mir::AggregateKind::Array(ty) => { + let length_path = Path::new_length(path.clone()); + let length_value = self.get_u128_const_val(operands.len() as u128); + self.bv.update_value_at(length_path, length_value); + for (i, operand) in operands.iter().enumerate() { + let index_value = self.get_u128_const_val(i as u128); + let index_path = Path::new_index(path.clone(), index_value); + self.type_visitor_mut() + .set_path_rustc_type(index_path.clone(), *ty); + self.visit_use(index_path, operand); + } + } + mir::AggregateKind::Tuple => { + let ty = self + .type_visitor() + .get_path_rustc_type(&path, self.bv.current_span); + let types = if let TyKind::Tuple(types) = ty.kind() { + types.as_slice() + } else { + &[] + }; + for (i, operand) in operands.iter().enumerate() { + let index_path = Path::new_field(path.clone(), i); + if let Some(ty) = types.get(i) { + self.type_visitor_mut() + .set_path_rustc_type(index_path.clone(), *ty); + }; + self.visit_use(index_path, operand); + } + } + mir::AggregateKind::Adt(def, variant_idx, substs, _, case_index) => { + let mut path = path; + let adt_def = self.bv.tcx.adt_def(def); + let variant_def = &adt_def.variants()[*variant_idx]; + let adt_ty = self.bv.tcx.type_of(def).skip_binder(); + if adt_def.is_enum() { + let discr_path = Path::new_discriminant(path.clone()); + let discr_ty = adt_ty.discriminant_ty(self.bv.tcx); + let discr_bits = + match adt_ty.discriminant_for_variant(self.bv.tcx, *variant_idx) { + Some(discr) => discr.val, + None => variant_idx.as_usize() as u128, + }; + let val = self.get_int_const_val(discr_bits, discr_ty); + self.bv.update_value_at(discr_path, val.clone()); + let discr_name = variant_def.name.to_string(); + path = Path::new_qualified( + path, + Rc::new(PathSelector::Downcast( + Rc::from(discr_name), + variant_idx.as_usize(), + val, + )), + ); + } else if adt_def.is_union() { + let num_cases = variant_def.fields.len(); + let case_index = case_index.unwrap_or(0); + let field_path = Path::new_union_field(path, case_index, num_cases); + let field = &variant_def.fields[case_index]; + let field_ty = field.ty(self.bv.tcx, substs); + self.type_visitor_mut() + .set_path_rustc_type(field_path.clone(), field_ty); + self.visit_use(field_path, &operands[0]); + return; + } + if variant_def.fields.is_empty() { + self.bv + .update_value_at(Path::new_field(path.clone(), 0), Rc::new(BOTTOM)); + } + for (i, field) in variant_def.fields.iter().enumerate() { + let field_path = Path::new_field(path.clone(), i); + let field_ty = field.ty(self.bv.tcx, substs); + self.type_visitor_mut() + .set_path_rustc_type(field_path.clone(), field_ty); + if let Some(operand) = operands.get(i) { + self.visit_use(field_path, operand); + } else { + debug!( + "variant has more fields than was serialized {:?}", + variant_def + ); + } + } + } + mir::AggregateKind::Closure(def_id, substs) + | mir::AggregateKind::Generator(def_id, substs, _) => { + let ty = self.bv.tcx.type_of(*def_id).skip_binder(); + let func_const = self.visit_function_reference(*def_id, ty, Some(substs)); + let func_val = Rc::new(func_const.clone().into()); + self.bv.update_value_at(path.clone(), func_val); + for (i, operand) in operands.iter().enumerate() { + let field_path = Path::new_field(path.clone(), i); + self.visit_use(field_path, operand); + } + } } } @@ -2401,27 +2499,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com self.type_visitor_mut() .set_path_rustc_type(value_path.clone(), ty); // todo: set value_path to boxed type - self.visit_used_operand(value_path, operand); - } - - /// Operand defines the values that can appear inside an rvalue. They are intentionally - /// limited to prevent rvalues from being nested in one another. - /// A used operand must move or copy values to a target path. - #[logfn_inputs(TRACE)] - fn visit_used_operand(&mut self, target_path: Rc, operand: &mir::Operand<'tcx>) { - match operand { - mir::Operand::Copy(place) => { - self.visit_used_copy(target_path, place); - } - mir::Operand::Move(place) => { - self.visit_used_move(target_path, place); - } - mir::Operand::Constant(constant) => { - let mir::Constant { literal, .. } = constant.borrow(); - let const_value = self.visit_literal(literal); - self.bv.update_value_at(target_path, const_value); - } - }; + self.visit_use(value_path, operand); } /// Returns the path (location/lh-value) of the given operand. @@ -2832,6 +2910,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com /// everything else. The representation mirrors that of the actual runtime representation, /// presumably because these values are used and produced by MIRI. /// Sadly, this means that MIRAI has to have a lot of duplicated logic. + #[logfn_inputs(TRACE)] fn visit_const_value(&mut self, val: ConstValue<'tcx>, lty: Ty<'tcx>) -> Rc { match val { // The raw bytes of a simple value. @@ -2902,7 +2981,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com instance.substs, &self.type_visitor().generic_argument_map, ); - let fn_ty = self.bv.tcx.type_of(def_id); + let fn_ty = self.bv.tcx.type_of(def_id).skip_binder(); self.bv.cv.substs_cache.insert(def_id, substs); let fun_val = Rc::new( self.bv @@ -3061,19 +3140,28 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com if let Ok(enum_ty_layout) = self.type_visitor().layout_of(ty) { trace!("enum_ty_layout {:?}", enum_ty_layout); let len = bytes.len(); + let tag_length; let data = if len < 2 { + tag_length = 1; bytes[0] as u128 } else if len < 4 { + tag_length = 2; u16::from_ne_bytes(*bytes.array_chunks().next().unwrap()) as u128 } else if len < 8 { + tag_length = 4; u32::from_ne_bytes(*bytes.array_chunks().next().unwrap()) as u128 } else if len < 16 { + tag_length = 8; u64::from_ne_bytes(*bytes.array_chunks().next().unwrap()) as u128 } else { + tag_length = 16; u128::from_ne_bytes(*bytes.array_chunks().next().unwrap()) }; - let (discr_signed, discr_bits, discr_index, _discr_has_data) = + let (discr_signed, discr_bits, discr_index, discr_has_data) = self.get_discriminator_info(data, &enum_ty_layout); + if !discr_has_data { + bytes_left_to_deserialize = &bytes[tag_length..]; + } let discr_path = Path::new_discriminant(target_path.clone()); let discr_data = if discr_signed { self.get_i128_const_val(discr_bits as i128) @@ -3081,22 +3169,24 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com self.get_u128_const_val(discr_bits) }; self.bv.update_value_at(discr_path, discr_data); - let variant = &def.variants()[discr_index]; - trace!("deserializing variant {:?}", variant); - for (i, field) in variant.fields.iter().enumerate() { - trace!("deserializing field({}) {:?}", i, field); - trace!("bytes_left_deserialize {:?}", bytes_left_to_deserialize); - let field_path = Path::new_field(target_path.clone(), i); - let field_ty = field.ty(self.bv.tcx, substs); - trace!( - "field ty layout {:?}", - self.type_visitor().layout_of(field_ty) - ); - bytes_left_to_deserialize = self.deserialize_constant_bytes( - field_path, - bytes_left_to_deserialize, - field_ty, - ); + if discr_has_data { + let variant = &def.variants()[discr_index]; + trace!("deserializing variant {:?}", variant); + for (i, field) in variant.fields.iter().enumerate() { + trace!("deserializing field({}) {:?}", i, field); + trace!("bytes_left_deserialize {:?}", bytes_left_to_deserialize); + let field_path = Path::new_field(target_path.clone(), i); + let field_ty = field.ty(self.bv.tcx, substs); + trace!( + "field ty layout {:?}", + self.type_visitor().layout_of(field_ty) + ); + bytes_left_to_deserialize = self.deserialize_constant_bytes( + field_path, + bytes_left_to_deserialize, + field_ty, + ); + } } } bytes_left_to_deserialize @@ -3390,7 +3480,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com } else { self.get_u128_const_val(discr_bits) }; - self.bv.update_value_at(discr_path, discr_data); + self.bv.update_value_at(discr_path, discr_data.clone()); if discr_has_data { use std::ops::Deref; @@ -3412,6 +3502,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com Rc::new(PathSelector::Downcast( Rc::from(name_str.deref()), discr_index.as_usize(), + discr_data, )), ), 0, @@ -3476,50 +3567,32 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com .. } => { // The enum contains multiple (more than one) variants. - - // The discriminant tag can be defined explicitly, and it can be negative. - // Extracts the tag layout that indicates the tag's sign. let tag_primitive = tag.primitive(); discr_signed = matches!(tag_primitive, Primitive::Int(_, true)); match *tag_encoding { TagEncoding::Direct => { - // Truncates the discriminant value to fit into the layout. - // But before the truncation, we have to extend it properly if the tag can be negative. - // For example, `std::cmp::Ordering::Less` is defined as -1, and its discriminant - // tag is internally represented as u128::MAX in the type definition. - // However, the constant literal might have a different memory layout. - // Currently, Rust encodes the constant `std::cmp::Ordering::Less` as 0xff. - // So we need to first sign_extend 0xff and then truncate to fit into discr_layout. - let v = if discr_signed { + discr_bits = if discr_signed { tag_primitive.size(&self.bv.tcx).sign_extend(data) } else { data }; - // Not clear what is going on here, but we can't return a variant index - // if the discriminant value (discr_bits) does not fall in the valid range. - let valid_range = tag.valid_range(&self.bv.tcx); - if valid_range.start <= valid_range.end { - discr_bits = u128::clamp(v, valid_range.start, valid_range.end); - } else { - // No idea why the range specification goes from high to low, but it happens. - discr_bits = u128::clamp(v, valid_range.end, valid_range.start); - } - // Iterates through all the variant definitions to find the actual index. + // The discriminator value is not the index, so + // iterate through all the variant definitions to find the actual index. discr_index = match enum_ty_layout.ty.kind() { - TyKind::Adt(adt, _) => adt + TyKind::Adt(adt_def, _) => adt_def .discriminants(self.bv.tcx) - .find(|(_, var)| var.val == discr_bits), + .find(|(_, var)| var.val == data), TyKind::Generator(def_id, substs, _) => { let substs = substs.as_generator(); substs .discriminants(*def_id, self.bv.tcx) - .find(|(_, var)| var.val == discr_bits) + .find(|(_, var)| var.val == data) } _ => assume_unreachable!(), } - .unwrap() - .0; + .map(|i| i.0) + .unwrap_or_else(|| VariantIdx::new(0)); discr_has_data = false; } @@ -3611,7 +3684,31 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com } TyKind::Uint(..) => self.bv.cv.constant_value_cache.get_u128_for(data), TyKind::RawPtr(..) => self.bv.cv.constant_value_cache.get_u128_for(data), + TyKind::Closure(def_id, substs) => { + let specialized_ty = self.type_visitor().specialize_generic_argument_type( + ty, + &self.type_visitor().generic_argument_map, + ); + let substs = self + .type_visitor() + .specialize_substs(substs, &self.type_visitor().generic_argument_map); + if substs.len() == 3 { + let tuple_ty = substs[2].expect_ty(); + let cv = self.get_constant_value_from_scalar(tuple_ty, data, size); + let cp = Path::get_as_path(cv); + let fr = self + .visit_function_reference(*def_id, specialized_ty, Some(substs)) + .clone(); + let fv = Rc::::new(fr.into()); + let fp = Path::get_as_path(fv.clone()); + self.bv.copy_or_move_elements(fp, cp, tuple_ty, true); + return fv; + } else { + unreachable!("substs for closure not right {:?}", substs); + } + } TyKind::FnDef(def_id, substs) => { + debug_assert!(size == 0 && data == 0); let specialized_ty = self.type_visitor().specialize_generic_argument_type( ty, &self.type_visitor().generic_argument_map, @@ -3793,7 +3890,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com ) => { if let TyKind::Closure(def_id, generic_args) | TyKind::Generator(def_id, generic_args, _) = - self.bv.tcx.type_of(*def_id).kind() + self.bv.tcx.type_of(*def_id).skip_binder().kind() { let func_const = self.visit_function_reference(*def_id, ty, Some(generic_args)); @@ -3941,7 +4038,22 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com None => Rc::from(format!("variant#{}", index.as_usize())), Some(name) => Rc::from(name.as_str().deref()), }; - PathSelector::Downcast(name_str, index.as_usize()) + let tag_value = if let TyKind::Adt(def, _) = base_ty.kind() { + if def.is_enum() { + let discr_ty = base_ty.discriminant_ty(self.bv.tcx); + let discr_bits = match base_ty.discriminant_for_variant(self.bv.tcx, *index) + { + Some(discr) => discr.val, + None => index.as_u32() as u128, + }; + self.get_int_const_val(discr_bits, discr_ty) + } else { + Rc::new(BOTTOM) + } + } else { + Rc::new(BOTTOM) + }; + PathSelector::Downcast(name_str, index.as_usize(), tag_value) } mir::ProjectionElem::OpaqueCast(_) => { // Dummy selector that will be ignored by caller. diff --git a/checker/src/body_visitor.rs b/checker/src/body_visitor.rs index 8f0aef88..cb3a4832 100644 --- a/checker/src/body_visitor.rs +++ b/checker/src/body_visitor.rs @@ -20,7 +20,7 @@ use rustc_middle::mir; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{AdtDef, Const, Ty, TyCtxt, TyKind, TypeAndMut, UintTy}; -use crate::abstract_value::{self, AbstractValue, AbstractValueTrait}; +use crate::abstract_value::{self, AbstractValue, AbstractValueTrait, BOTTOM}; use crate::block_visitor::BlockVisitor; use crate::call_visitor::CallVisitor; use crate::constant_domain::ConstantDomain; @@ -190,6 +190,7 @@ impl<'analysis, 'compilation, 'tcx> BodyVisitor<'analysis, 'compilation, 'tcx> { if cfg!(DEBUG) { utils::pretty_print_mir(self.tcx, self.def_id); } + debug!("entered body of {:?}", self.def_id); *self.active_calls_map.entry(self.def_id).or_insert(0) += 1; let saved_heap_counter = self.cv.constant_value_cache.swap_heap_counter(0); @@ -637,7 +638,7 @@ impl<'analysis, 'compilation, 'tcx> BodyVisitor<'analysis, 'compilation, 'tcx> { } else { None }; - let ty = self.tcx.type_of(def_id); + let ty = self.tcx.type_of(def_id).skip_binder(); let func_const = self .cv .constant_value_cache @@ -2419,7 +2420,7 @@ impl<'analysis, 'compilation, 'tcx> BodyVisitor<'analysis, 'compilation, 'tcx> { pub fn get_array_length(&self, length: &'tcx Const<'tcx>) -> usize { let param_env = self.type_visitor().get_param_env(); length - .try_eval_usize(self.tcx, param_env) + .try_eval_target_usize(self.tcx, param_env) .expect("Array length constant to have a known value") as usize } @@ -2477,6 +2478,10 @@ impl<'analysis, 'compilation, 'tcx> BodyVisitor<'analysis, 'compilation, 'tcx> { } update(self, target_path.clone(), value.clone()); } + if let Expression::CompileTimeConstant(ConstantDomain::Function(..)) = &value.expression { + let target_path = Path::new_function(target_path.clone()); + update(self, target_path, value.clone()); + } let target_type = ExpressionType::from(root_rustc_type.kind()); let mut no_children = true; // If a non primitive parameter is just returned from a function, for example, @@ -2518,6 +2523,14 @@ impl<'analysis, 'compilation, 'tcx> BodyVisitor<'analysis, 'compilation, 'tcx> { if path.is_rooted_by_parameter() { update(self, target_path.clone(), value.clone()); no_children = false; + } else if no_children && self.type_visitor.is_empty_struct(root_rustc_type.kind()) { + // Add a dummy field so that we don't end up with an unknown local var + // as the value of any target that target_path may get copied or moved to. + // That is problematic because an empty struct is a compile time constant + // and not an unknown value. + let field_path = Path::new_field(target_path, 0); + update(self, field_path, Rc::new(BOTTOM)); + return; } } } diff --git a/checker/src/call_visitor.rs b/checker/src/call_visitor.rs index 366d48e4..56a7d199 100644 --- a/checker/src/call_visitor.rs +++ b/checker/src/call_visitor.rs @@ -108,7 +108,12 @@ impl<'call, 'block, 'analysis, 'compilation, 'tcx> func_args: &Option>>>, initial_type_cache: &Option, Ty<'tcx>>>>, ) -> Summary { - let func_type = self.block_visitor.bv.tcx.type_of(self.callee_def_id); + let func_type = self + .block_visitor + .bv + .tcx + .type_of(self.callee_def_id) + .skip_binder(); trace!("summarizing {:?}: {:?}", self.callee_def_id, func_type); let tcx = self.block_visitor.bv.tcx; if tcx.is_mir_available(self.callee_def_id) { @@ -201,7 +206,7 @@ impl<'call, 'block, 'analysis, 'compilation, 'tcx> trace!( "devirtualize resolving def_id {:?}: {:?}", self.callee_def_id, - tcx.type_of(self.callee_def_id) + tcx.type_of(self.callee_def_id).skip_binder() ); trace!("devirtualize resolving func_ref {:?}", self.callee_func_ref,); trace!("gen_args {:?}", gen_args); @@ -213,7 +218,11 @@ impl<'call, 'block, 'analysis, 'compilation, 'tcx> return; } } - let abi = tcx.type_of(self.callee_def_id).fn_sig(tcx).abi(); + let abi = tcx + .type_of(self.callee_def_id) + .skip_binder() + .fn_sig(tcx) + .abi(); let resolved_instance = if abi == rustc_target::spec::abi::Abi::Rust { Some(rustc_middle::ty::Instance::resolve( tcx, @@ -232,7 +241,7 @@ impl<'call, 'block, 'analysis, 'compilation, 'tcx> return; } self.callee_def_id = resolved_def_id; - let resolved_ty = tcx.type_of(resolved_def_id); + let resolved_ty = tcx.type_of(resolved_def_id).skip_binder(); let resolved_map = self.type_visitor().get_generic_arguments_map( resolved_def_id, instance.substs, diff --git a/checker/src/callbacks.rs b/checker/src/callbacks.rs index b5cc301d..371b0b3c 100644 --- a/checker/src/callbacks.rs +++ b/checker/src/callbacks.rs @@ -113,7 +113,6 @@ impl rustc_driver::Callbacks for MiraiCallbacks { queries .global_ctxt() .unwrap() - .peek_mut() .enter(|tcx| self.analyze_with_mirai(compiler, tcx)); if self.test_run { // We avoid code gen for test cases because LLVM is not used in a thread safe manner. diff --git a/checker/src/fixed_point_visitor.rs b/checker/src/fixed_point_visitor.rs index a87ab753..1480d1b8 100644 --- a/checker/src/fixed_point_visitor.rs +++ b/checker/src/fixed_point_visitor.rs @@ -205,9 +205,7 @@ impl<'fixed, 'analysis, 'compilation, 'tcx> let old_state = self.out_state.clone(); for bb in blocks { check_for_early_break!(self.bv); - if !self.already_visited.contains(&bb) - && self.dominators.is_dominated_by(bb, loop_anchor) - { + if !self.already_visited.contains(&bb) && self.dominators.dominates(loop_anchor, bb) { last_block = bb; // Visit the next block, or the entire nested loop anchored by it. if bb == loop_anchor { @@ -250,7 +248,7 @@ impl<'fixed, 'analysis, 'compilation, 'tcx> .filter_map(|pred_bb| { // If the predecessor can only be reached via bb then bb and pred_bb are // part of the loop body. - let is_loop_back = self.dominators.is_dominated_by(*pred_bb, bb); + let is_loop_back = self.dominators.dominates(bb, *pred_bb); if iteration_count == 1 && is_loop_back { // For the first iteration of the loop body we only want state that // precedes the body. Normally, the state of a block that is part of the @@ -353,7 +351,7 @@ fn add_predecessors_then_root_block<'tcx>( if already_added.contains(pred_bb) { continue; }; - if dominators.is_dominated_by(*pred_bb, root_block) { + if dominators.dominates(root_block, *pred_bb) { // pred_bb has still to be added, so it has a greater index than root_block, making root_block the loop anchor. //todo: checked_assume!(root_block.index() < pred_bb.index()); // Root block has a smaller index than pred_bb because it has not already been added. diff --git a/checker/src/options.rs b/checker/src/options.rs index 5006d806..13242d7e 100644 --- a/checker/src/options.rs +++ b/checker/src/options.rs @@ -84,10 +84,11 @@ pub struct Options { } /// Represents diag level. -#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)] pub enum DiagLevel { /// When a function calls a function without a body and with no foreign function summary, the call assumed to be /// correct and any diagnostics that depend on the result of the call in some way are suppressed. + #[default] Default, /// Like Default, but emit a diagnostic if there is a call to a function without a body and with no foreign function summary. Verify, @@ -100,12 +101,6 @@ pub enum DiagLevel { Paranoid, } -impl Default for DiagLevel { - fn default() -> Self { - DiagLevel::Default - } -} - impl Options { /// Parse options from an argument string. The argument string will be split using unix /// shell escaping rules. Any content beyond the leftmost `--` token will be returned diff --git a/checker/src/path.rs b/checker/src/path.rs index 727e4a55..879f78e4 100644 --- a/checker/src/path.rs +++ b/checker/src/path.rs @@ -596,7 +596,7 @@ impl Path { /// Creates a path to the static defined by def_id. pub fn new_static(tcx: TyCtxt<'_>, def_id: DefId) -> Rc { - let ty = tcx.type_of(def_id); + let ty = tcx.type_of(def_id).skip_binder(); let name = utils::summary_key_str(tcx, def_id); Rc::new( PathEnum::StaticVariable { @@ -979,16 +979,12 @@ impl PathRefinement for Rc { } } // An impossible downcast is equivalent to BOTTOM - if let PathSelector::Downcast(_, variant) = selector.as_ref() { + if let PathSelector::Downcast(_, _, discr_val) = selector.as_ref() { let discriminator = Path::new_discriminant(canonical_qualifier.clone()); if let Some(val) = environment.value_at(&discriminator) { - if let Expression::CompileTimeConstant(ConstantDomain::U128(ordinal)) = - &val.expression - { - if (*variant as u128) != *ordinal { - // The downcast is impossible in this calling context - return Path::new_computed(Rc::new(abstract_value::BOTTOM)); - } + if val.is_compile_time_constant() && val.ne(discr_val) { + // The downcast is impossible in this calling context + return Path::new_computed(Rc::new(abstract_value::BOTTOM)); } } } @@ -1189,8 +1185,9 @@ pub enum PathSelector { ConstantSlice { from: u64, to: u64, from_end: bool }, /// "Downcast" to a variant of an ADT. Currently, MIR only introduces - /// this for ADTs with more than one variant. The value is the ordinal of the variant. - Downcast(Rc, usize), + /// this for ADTs with more than one variant. The usize value is the ordinal of the variant. + /// The constant value is the tag value that corresponds to the variant. + Downcast(Rc, usize, Rc), /// Select the struct model field with the given name. /// A model field is a specification construct used during MIRAI verification @@ -1233,7 +1230,9 @@ impl Debug for PathSelector { PathSelector::ConstantSlice { from, to, from_end } => { f.write_fmt(format_args!("[{from} : {to}, from_end: {from_end}]")) } - PathSelector::Downcast(name, index) => f.write_fmt(format_args!("as {name}({index})")), + PathSelector::Downcast(name, index, val) => { + f.write_fmt(format_args!("as {name}({index}, {val:?})")) + } PathSelector::ModelField(name) => name.fmt(f), PathSelector::TagField => f.write_str("$tag"), } diff --git a/checker/src/type_visitor.rs b/checker/src/type_visitor.rs index 1359f0f4..b5d04b21 100644 --- a/checker/src/type_visitor.rs +++ b/checker/src/type_visitor.rs @@ -27,7 +27,6 @@ use crate::constant_domain::ConstantDomain; use crate::environment::Environment; use crate::expression::{Expression, ExpressionType}; use crate::path::{Path, PathEnum, PathRefinement, PathRoot, PathSelector}; -use crate::rustc_middle::ty::DefIdTree; use crate::{type_visitor, utils}; #[derive(Debug)] @@ -180,8 +179,10 @@ impl<'tcx> TypeVisitor<'tcx> { rustc_middle::ty::AliasTy { def_id, substs, .. }, ) => { let map = self.get_generic_arguments_map(*def_id, substs, &[]); - let path_ty = - self.specialize_generic_argument_type(self.tcx.type_of(*def_id), &map); + let path_ty = self.specialize_generic_argument_type( + self.tcx.type_of(*def_id).skip_binder(), + &map, + ); self.add_any_closure_fields_for(&path_ty, path, first_state); } TyKind::Dynamic(..) | TyKind::FnDef(..) | TyKind::FnPtr(..) => {} @@ -255,6 +256,16 @@ impl<'tcx> TypeVisitor<'tcx> { } } + pub fn is_empty_struct(&self, ty_kind: &TyKind<'tcx>) -> bool { + if let TyKind::Adt(def, ..) = ty_kind { + if !def.is_enum() && !def.is_union() { + let variant = &def.variants()[VariantIdx::new(0)]; + return variant.fields.is_empty(); + } + } + false + } + #[logfn_inputs(TRACE)] pub fn is_function_like(&self, ty_kind: &TyKind<'tcx>) -> bool { matches!( @@ -328,7 +339,7 @@ impl<'tcx> TypeVisitor<'tcx> { Expression::CompileTimeConstant(c) => { if let ConstantDomain::Function(fr) = c { if let Some(def_id) = fr.def_id { - return self.tcx.type_of(def_id); + return self.tcx.type_of(def_id).skip_binder(); } } c.get_rustc_type(self.tcx) @@ -440,8 +451,10 @@ impl<'tcx> TypeVisitor<'tcx> { ) = &t.kind() { let map = self.get_generic_arguments_map(*def_id, substs, &[]); - t = self - .specialize_generic_argument_type(self.tcx.type_of(*def_id), &map); + t = self.specialize_generic_argument_type( + self.tcx.type_of(*def_id).skip_binder(), + &map, + ); trace!("opaque type_of {:?}", t.kind()); trace!("opaque type_of {:?}", t); } @@ -483,7 +496,7 @@ impl<'tcx> TypeVisitor<'tcx> { let mut tuple_types = substs.as_generator().state_tys(*def_id, self.tcx); if let Some(field_tys) = tuple_types.nth(*ordinal) { - return self.tcx.mk_tup(field_tys); + return self.tcx.mk_tup_from_iter(field_tys); } info!("generator field not found {:?} {:?}", def_id, ordinal); return self.tcx.types.never; @@ -574,7 +587,7 @@ impl<'tcx> TypeVisitor<'tcx> { PathSelector::Discriminant => { return self.tcx.types.i32; } - PathSelector::Downcast(_, ordinal) => { + PathSelector::Downcast(_, ordinal, _) => { // Down casting to an enum variant if t == self.tcx.types.usize { // Down casting from an untyped pointer. This happens often enough @@ -597,7 +610,7 @@ impl<'tcx> TypeVisitor<'tcx> { let variant = &def.variants()[VariantIdx::new(*ordinal)]; let field_tys = variant.fields.iter().map(|fd| fd.ty(self.tcx, substs)); - return self.tcx.mk_tup(field_tys); + return self.tcx.mk_tup_from_iter(field_tys); } if !type_visitor::is_transparent_wrapper(t) { break; @@ -641,7 +654,7 @@ impl<'tcx> TypeVisitor<'tcx> { } PathEnum::StaticVariable { def_id, .. } => { if let Some(def_id) = def_id { - return self.tcx.type_of(*def_id); + return self.tcx.type_of(*def_id).skip_binder(); } info!( "static variable path.value is {:?} at {:?}", @@ -777,7 +790,7 @@ impl<'tcx> TypeVisitor<'tcx> { } map.insert(param_def.name, specialized_gen_arg); } else { - debug!("unmapped generic param def"); + debug!("unmapped generic param def {:?}", param_def); } self.tcx.mk_param_from_def(param_def) // not used }); @@ -924,15 +937,15 @@ impl<'tcx> TypeVisitor<'tcx> { ); let variant = &def.variants().iter().last().unwrap(); let field_tys = variant.fields.iter().map(|fd| fd.ty(self.tcx, substs)); - return self.tcx.mk_tup(field_tys); + return self.tcx.mk_tup_from_iter(field_tys); } let variant = &def.variants()[*ordinal]; let field_tys = variant.fields.iter().map(|fd| fd.ty(self.tcx, substs)); - return self.tcx.mk_tup(field_tys); + return self.tcx.mk_tup_from_iter(field_tys); } else if let TyKind::Generator(def_id, substs, ..) = base_ty.kind() { let mut tuple_types = substs.as_generator().state_tys(*def_id, self.tcx); if let Some(field_tys) = tuple_types.nth(ordinal.index()) { - return self.tcx.mk_tup(field_tys); + return self.tcx.mk_tup_from_iter(field_tys); } debug!( "illegally down casting to index {} of {:?} at {:?}", @@ -991,7 +1004,7 @@ impl<'tcx> TypeVisitor<'tcx> { let variant_0 = VariantIdx::from_u32(0); let v = &def.variants()[variant_0]; let non_zst_field = v.fields.iter().find(|field| { - let field_ty = self.tcx.type_of(field.did); + let field_ty = self.tcx.type_of(field.did).skip_binder(); let is_zst = self .layout_of(field_ty) .map_or(false, |layout| layout.is_zst()); @@ -1059,7 +1072,7 @@ impl<'tcx> TypeVisitor<'tcx> { .tcx .mk_projection(projection.def_id, specialized_substs); } - let item_type = self.tcx.type_of(instance_item_def_id); + let item_type = self.tcx.type_of(instance_item_def_id).skip_binder(); let map = self.get_generic_arguments_map(instance_item_def_id, instance.substs, &[]); if item_type == gen_arg_type && map.is_none() { @@ -1098,7 +1111,7 @@ impl<'tcx> TypeVisitor<'tcx> { let specialized_elem_ty = self.specialize_generic_argument_type(*elem_ty, map); let specialized_len = self.specialize_const(*len, map); self.tcx - .mk_ty(TyKind::Array(specialized_elem_ty, specialized_len)) + .mk_ty_from_kind(TyKind::Array(specialized_elem_ty, specialized_len)) } TyKind::Slice(elem_ty) => { let specialized_elem_ty = self.specialize_generic_argument_type(*elem_ty, map); @@ -1126,7 +1139,7 @@ impl<'tcx> TypeVisitor<'tcx> { .mk_fn_def(*def_id, self.specialize_substs(substs, map)), TyKind::FnPtr(fn_sig) => { let map_fn_sig = |fn_sig: FnSig<'tcx>| { - let specialized_inputs_and_output = self.tcx.mk_type_list( + let specialized_inputs_and_output = self.tcx.mk_type_list_from_iter( fn_sig .inputs_and_output .iter() @@ -1177,7 +1190,7 @@ impl<'tcx> TypeVisitor<'tcx> { ); self.tcx.mk_dynamic( self.tcx - .mk_poly_existential_predicates(specialized_predicates), + .mk_poly_existential_predicates_from_iter(specialized_predicates), *region, *kind, ) @@ -1209,7 +1222,7 @@ impl<'tcx> TypeVisitor<'tcx> { } TyKind::GeneratorWitness(bound_types) => { let map_types = |types: &rustc_middle::ty::List>| { - self.tcx.mk_type_list( + self.tcx.mk_type_list_from_iter( types .iter() .map(|ty| self.specialize_generic_argument_type(ty, map)), @@ -1218,7 +1231,7 @@ impl<'tcx> TypeVisitor<'tcx> { let specialized_types = bound_types.map_bound(map_types); self.tcx.mk_generator_witness(specialized_types) } - TyKind::Tuple(types) => self.tcx.mk_tup( + TyKind::Tuple(types) => self.tcx.mk_tup_from_iter( types .iter() .map(|ty| self.specialize_generic_argument_type(ty, map)), @@ -1251,7 +1264,7 @@ impl<'tcx> TypeVisitor<'tcx> { .iter() .map(|gen_arg| self.specialize_generic_argument(gen_arg, map)) .collect(); - self.tcx.intern_substs(&specialized_generic_args) + self.tcx.mk_substs(&specialized_generic_args) } } diff --git a/checker/src/utils.rs b/checker/src/utils.rs index 07137c30..44893fc7 100644 --- a/checker/src/utils.rs +++ b/checker/src/utils.rs @@ -17,7 +17,7 @@ use rustc_hir::Node; use rustc_middle::ty; use rustc_middle::ty::print::{FmtPrinter, Printer}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{DefIdTree, FloatTy, IntTy, Ty, TyCtxt, TyKind, UintTy}; +use rustc_middle::ty::{FloatTy, IntTy, Ty, TyCtxt, TyKind, UintTy}; /// Returns the location of the rust system binaries that are associated with this build of Mirai. /// The location is obtained by looking at the contents of the environmental variables that were @@ -50,7 +50,7 @@ pub fn find_sysroot() -> String { /// information from its calling context. #[logfn(TRACE)] pub fn is_higher_order_function(def_id: DefId, tcx: TyCtxt<'_>) -> bool { - let fn_ty = tcx.type_of(def_id); + let fn_ty = tcx.type_of(def_id).skip_binder(); if fn_ty.is_fn() { let fn_sig = fn_ty.fn_sig(tcx).skip_binder(); for param_ty in fn_sig.inputs() { @@ -388,10 +388,10 @@ pub fn summary_key_str(tcx: TyCtxt<'_>, def_id: DefId) -> Rc { | DefKind::Enum | DefKind::Variant | DefKind::TyAlias - | DefKind::Impl + | DefKind::Impl { .. }, ) { name.push('_'); - append_mangled_type(&mut name, tcx.type_of(parent_def_id), tcx); + append_mangled_type(&mut name, tcx.type_of(parent_def_id).skip_binder(), tcx); } } } @@ -441,7 +441,7 @@ fn push_component_name(component_data: DefPathData, target: &mut String) { pub fn def_id_as_qualified_name_str(tcx: TyCtxt<'_>, def_id: DefId) -> Rc { let mut name = format!("/{}/", crate_name(tcx, def_id)); name.push_str(&tcx.def_path_str(def_id)); - let fn_ty = tcx.type_of(def_id); + let fn_ty = tcx.type_of(def_id).skip_binder(); if fn_ty.is_fn() { name.push('('); let fn_sig = fn_ty.fn_sig(tcx).skip_binder(); diff --git a/checker/tests/call_graph/fnptr_fold.rs b/checker/tests/call_graph/fnptr_fold.rs index 84d42dd7..7d13f8e0 100644 --- a/checker/tests/call_graph/fnptr_fold.rs +++ b/checker/tests/call_graph/fnptr_fold.rs @@ -68,8 +68,8 @@ commit; /* EXPECTED:CALL_SITES{ "files": [ "tests/call_graph/fnptr_fold.rs", - "/rustc/388538fc963e07a94e3fc3ac8948627fd2d28d29/library/std/src/io/stdio.rs", - "/rustc/388538fc963e07a94e3fc3ac8948627fd2d28d29/library/core/src/fmt/mod.rs" + "/rustc/e3dfeeaa45f117281b19773d67f3f253de65cee1/library/std/src/io/stdio.rs", + "/rustc/e3dfeeaa45f117281b19773d67f3f253de65cee1/library/core/src/fmt/mod.rs" ], "callables": [ { @@ -103,9 +103,9 @@ commit; "local": false }, { - "name": "/core/std::fmt::Arguments::<'a>::new_v1(&'a [&'static str],&'a [std::fmt::ArgumentV1<'a>])->std::fmt::Arguments<'a>", + "name": "/core/std::fmt::Arguments::<'a>::new_v1(&'a [&'static str],&'a [core::fmt::ArgumentV1<'a>])->std::fmt::Arguments<'a>", "file_index": 2, - "first_line": 394, + "first_line": 401, "local": true } ], @@ -147,7 +147,7 @@ commit; ], [ 2, - 396, + 403, 13, 5, 5 diff --git a/checker/tests/call_graph/static_fold.rs b/checker/tests/call_graph/static_fold.rs index c4f70cb2..d2811754 100644 --- a/checker/tests/call_graph/static_fold.rs +++ b/checker/tests/call_graph/static_fold.rs @@ -64,8 +64,8 @@ commit; /* EXPECTED:CALL_SITES{ "files": [ "tests/call_graph/static_fold.rs", - "/rustc/388538fc963e07a94e3fc3ac8948627fd2d28d29/library/std/src/io/stdio.rs", - "/rustc/388538fc963e07a94e3fc3ac8948627fd2d28d29/library/core/src/fmt/mod.rs" + "/rustc/e3dfeeaa45f117281b19773d67f3f253de65cee1/library/std/src/io/stdio.rs", + "/rustc/e3dfeeaa45f117281b19773d67f3f253de65cee1/library/core/src/fmt/mod.rs" ], "callables": [ { @@ -99,9 +99,9 @@ commit; "local": false }, { - "name": "/core/std::fmt::Arguments::<'a>::new_v1(&'a [&'static str],&'a [std::fmt::ArgumentV1<'a>])->std::fmt::Arguments<'a>", + "name": "/core/std::fmt::Arguments::<'a>::new_v1(&'a [&'static str],&'a [core::fmt::ArgumentV1<'a>])->std::fmt::Arguments<'a>", "file_index": 2, - "first_line": 394, + "first_line": 401, "local": false } ], diff --git a/checker/tests/integration_tests.rs b/checker/tests/integration_tests.rs index 4d6c2408..dc86b264 100644 --- a/checker/tests/integration_tests.rs +++ b/checker/tests/integration_tests.rs @@ -407,15 +407,15 @@ fn check_call_graph_output( if compare_lines(&expected, &actual) { 0 } else { - // println!("{file_name} failed to match {output_type:?} output"); - // println!("Expected:\n{expected}"); - // println!("Actual:\n{actual}"); - // 1 - let c = expected_regex.captures(&test_case_data).unwrap(); - let updated = - expected_regex.replace(&test_case_data, format!("{}{actual}{}", &c[1], &c[3])); - fs::write(Path::new(&file_name), updated.to_string()).unwrap(); - 0 + println!("{file_name} failed to match {output_type:?} output"); + println!("Expected:\n{expected}"); + println!("Actual:\n{actual}"); + 1 + // let c = expected_regex.captures(&test_case_data).unwrap(); + // let updated = + // expected_regex.replace(&test_case_data, format!("{}{actual}{}", &c[1], &c[3])); + // fs::write(Path::new(&file_name), updated.to_string()).unwrap(); + // 0 } } else { println!("{file_name} failed to read {output_type:?} output"); diff --git a/checker/tests/run-pass/binary_overflow.rs b/checker/tests/run-pass/binary_overflow.rs index 4640dbee..fead8e54 100644 --- a/checker/tests/run-pass/binary_overflow.rs +++ b/checker/tests/run-pass/binary_overflow.rs @@ -10,74 +10,24 @@ use mirai_annotations::*; -pub fn tu8_add() -> u8 { - let a: u8 = 255; - a + 1 //~ attempt to add with overflow -} - -pub fn tu8_sub() -> u8 { - let a: u8 = 0; - a - 1 //~ attempt to subtract with overflow -} - -pub fn tu8_div() -> u8 { - let a: u8 = 255; - let b: u8 = 0; - a / b //~ attempt to divide by zero -} - -pub fn tu8_mul() -> u8 { - let a: u8 = 255; - a * 2 //~ attempt to multiply with overflow -} - pub fn tu8_overflowing_mul() { let a: u8 = 255; - let (a2, it_overflows) = a.overflowing_mul(2); + let (_a2, it_overflows) = a.overflowing_mul(2); verify!(it_overflows); - verify!(a2 == 254); + //verify!(a2 == 254); } pub fn ti8_overflowing_mul() { let a: i8 = 127; - let (a2, it_overflows) = a.overflowing_mul(2); + let (_a2, it_overflows) = a.overflowing_mul(2); verify!(it_overflows); - verify!(a2 == -2); //~ possible false verification condition + //verify!(a2 == -2); } pub fn tu128_overflowing_mul() { let a: u128 = std::u128::MAX; - let (a2, it_overflows) = a.overflowing_mul(2); + let (_a2, it_overflows) = a.overflowing_mul(2); verify!(it_overflows); - verify!(a2 == 340282366920938463463374607431768211454); //~ possible false verification condition -} - -pub fn tu8_rem() -> u8 { - let a: u8 = 255; - let b: u8 = 0; - a % b //~ attempt to calculate the remainder with a divisor of zero -} - -pub fn tu8_shl() -> u8 { - let a: u8 = 255; - let b = 8; - a << b //~ attempt to shift left with overflow -} - -pub fn tu8_shr() -> u8 { - let a: u8 = 255; - let b = 8; - a >> b //~ attempt to shift right with overflow -} - -pub fn ti8_add() -> i8 { - let a: i8 = 127; - a + 1 //~ attempt to add with overflow -} - -pub fn ti8_div0() -> i8 { - let a: i8 = 127; - let b: i8 = 0; - a / b //~ attempt to divide by zero + //verify!(a2 == 340282366920938463463374607431768211454); } pub fn ti8_div_m1() -> i8 { @@ -86,33 +36,10 @@ pub fn ti8_div_m1() -> i8 { a / b //~ attempt to divide with overflow } -pub fn ti8_mul() -> i8 { - let a: i8 = 127; - a * 2 //~ attempt to multiply with overflow -} - -pub fn ti8_rem() -> i8 { - let a: i8 = 127; - let b: i8 = 0; - a % b //~ attempt to calculate the remainder with a divisor of zero -} - pub fn ti8_rem_m1() -> i8 { let a: i8 = -128; let b: i8 = -1; a % b //~ attempt to calculate the remainder with overflow } -pub fn ti8_shl() -> i8 { - let a: i8 = 127; - let b = 8; - a << b //~ attempt to shift left with overflow -} - -pub fn ti8_shr() -> i8 { - let a: i8 = 127; - let b = 8; - a >> b //~ attempt to shift right with overflow -} - pub fn main() {} diff --git a/checker/tests/run-pass/box_fail.rs b/checker/tests/run-pass/box_fail.rs index 80386654..93320e08 100644 --- a/checker/tests/run-pass/box_fail.rs +++ b/checker/tests/run-pass/box_fail.rs @@ -9,8 +9,7 @@ #![feature(box_syntax)] pub fn test13(i: i64) { - // todo: fix this - let _x = box -i; // ~ possible attempt to negate with overflow + let _x = box -i; //~ possible attempt to negate with overflow } pub fn main() {} diff --git a/checker/tests/run-pass/constant_time_taint.rs b/checker/tests/run-pass/constant_time_taint.rs index 1ac178be..58eb641a 100644 --- a/checker/tests/run-pass/constant_time_taint.rs +++ b/checker/tests/run-pass/constant_time_taint.rs @@ -37,9 +37,13 @@ pub fn test2(secret: i32) { //~ the branch condition has a ConstantTimeTaintKind tag } -pub fn test3(secret: i32) { +pub fn test3(secret: i32) -> i32 { precondition!(has_tag!(&secret, ConstantTimeTaint)); - let _ = if secret | 99991 < 5 { 32767 } else { 10003 }; + if secret | 99991 < 5 { + 32767 + } else { + 10003 + } //~ the branch condition has a ConstantTimeTaintKind tag } @@ -89,11 +93,11 @@ pub fn test6() { work_on_non_secret(non_secret); } -pub fn test7(mut message: Vec) { - precondition!(does_not_have_tag!(&message, ConstantTimeTaint)); - for m in 0..message.len() - 1 { - message[m] = message[m] + 1; - } -} +// pub fn test7(mut message: Vec) { +// precondition!(does_not_have_tag!(&message, ConstantTimeTaint)); +// for m in 0..message.len() - 1 { +// message[m] = message[m] + 1; +// } +// } pub fn main() {} diff --git a/checker/tests/run-pass/crate_traversal.rs b/checker/tests/run-pass/crate_traversal.rs index 5ca7adff..c975741e 100644 --- a/checker/tests/run-pass/crate_traversal.rs +++ b/checker/tests/run-pass/crate_traversal.rs @@ -159,8 +159,12 @@ pub fn test11(arr: &[String]) { } #[allow(arithmetic_overflow)] +fn test12a(i: u8) { + let x = 200u8 * i; //~ related location +} + pub fn test12() { - let x = 200u8 * 4; //~ attempt to multiply with overflow + test12a(4); //~ attempt to multiply with overflow } fn test13(a: i32, b: i32) -> Option { diff --git a/checker/tests/run-pass/false_precon.rs b/checker/tests/run-pass/false_precon.rs index 3fafbaa1..0fcf8dd6 100644 --- a/checker/tests/run-pass/false_precon.rs +++ b/checker/tests/run-pass/false_precon.rs @@ -19,12 +19,11 @@ type SecretTaint = SecretTaintKind; fn foo(v: &Vec) { // This precondition should never be true. precondition!(does_not_have_tag!(&v[0], SecretTaint) && has_tag!(&v[0], SecretTaint)); - // ~ related location + //~ related location } pub fn main() { let v = vec![1, 2, 3]; add_tag!(&v, SecretTaint); - // todo: fix this - foo(&v); // ~ unsatisfied precondition + foo(&v); //~ unsatisfied precondition } diff --git a/checker/tests/run-pass/tag_empty_struct.rs b/checker/tests/run-pass/tag_empty_struct.rs index d01cebe3..424cb8ba 100644 --- a/checker/tests/run-pass/tag_empty_struct.rs +++ b/checker/tests/run-pass/tag_empty_struct.rs @@ -48,15 +48,16 @@ pub mod propagation_on_empty_struct { } pub fn test3_constant() { - // Marking FOO to be a constant makes sure that the Rust compiler does not make up a new - // constant for the call. const FOO: Foo = Foo {}; add_tag!(&FOO, SecretTaint); - call3(FOO); + // Sadly, the next call is compiled by Rust with an argument that constructs a new empty struct. + // Thus the tag added above is not present on the actual argument and the precondition fails. + call3(FOO); //~unsatisfied precondition } fn call3(foo: Foo) { precondition!(has_tag!(&foo, SecretTaint)); //~related location + //~related location } pub fn test4() { diff --git a/checker/tests/run-pass/trait_call.rs b/checker/tests/run-pass/trait_call.rs index 1c0dfeea..80aba4bf 100644 --- a/checker/tests/run-pass/trait_call.rs +++ b/checker/tests/run-pass/trait_call.rs @@ -47,8 +47,7 @@ pub fn t1() { let foo = Foo { bx: Box::new(bar) as Box, }; - // todo: fix this - let bi = foo.bx.bar(); //~ the called function did not resolve to an implementation with a MIR body + let bi = foo.bx.bar(); verify!(bi == 1); } @@ -74,9 +73,8 @@ pub fn t4() { let foo = Foo { bx: Box::new(bar) as Box, }; - let _bi = t4c(foo); - //todo: fix this - //verify!(bi == 1); + let bi = t4c(foo); + verify!(bi == 1); } pub fn t4a() { @@ -84,14 +82,12 @@ pub fn t4a() { let foo = Foo { bx: Box::new(bar) as Box, }; - let _bi = t4c(foo); - // todo: fix this - //verify!(bi == 2); + let bi = t4c(foo); + verify!(bi == 2); } fn t4c(foo: Foo) -> i32 { - // todo: fix this - foo.bx.bar() //~ the called function did not resolve to an implementation with a MIR body + foo.bx.bar() } impl Clone for Box { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 7a0ac487..44962ef4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2023-01-06" +channel = "nightly-2023-03-08" components = [ "clippy", "rustfmt", "rustc-dev", "rust-std", "llvm-tools-preview" ] profile = "minimal" diff --git a/standard_contracts/src/foreign_contracts.rs b/standard_contracts/src/foreign_contracts.rs index e4d06218..a9f63a9c 100644 --- a/standard_contracts/src/foreign_contracts.rs +++ b/standard_contracts/src/foreign_contracts.rs @@ -94,7 +94,7 @@ pub mod alloc { assume_unreachable!("capacity overflow"); } - pub mod implement { + pub mod implement_alloc_raw_vec_RawVec_generic_par_T_alloc_alloc_Global { use std::ptr::Unique; pub struct RawVec { @@ -2871,6 +2871,10 @@ pub mod core { // todo: implement this inside MIRAI result!() } + pub fn ptr_offset_from_unsigned(ptr: *const T, base: *const T) -> isize { + // todo: implement this inside MIRAI + result!() + } pub fn miri_start_panic(data: T) { assume_unreachable!() }