Unverified Commit d84f5170 by Enkelmann Committed by GitHub

Generate context information for CWE-416 warnings (#408)

parent cdb6359f
......@@ -11,18 +11,67 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "0.7.18"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is-terminal",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
[[package]]
name = "anstyle-parse"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.44"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]]
name = "apint"
......@@ -42,7 +91,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
"winapi",
]
......@@ -60,6 +109,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
......@@ -67,40 +122,51 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.0.9"
version = "4.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30607dd93c420c6f1f80b544be522a0238a7db35e6a12968d28910983fee0df0"
checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62"
dependencies = [
"atty",
"bitflags",
"clap_builder",
"clap_derive",
"clap_lex",
"once_cell",
]
[[package]]
name = "clap_builder"
version = "4.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749"
dependencies = [
"anstream",
"anstyle",
"bitflags",
"clap_lex",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.0.9"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a307492e1a34939f79d3b6b9650bd2b971513cd775436bf2b78defeb5af00b"
checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
"syn 2.0.15",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "colored"
......@@ -121,9 +187,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "crossbeam-channel"
version = "0.5.4"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
......@@ -131,12 +197,11 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.8"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]]
......@@ -185,15 +250,15 @@ dependencies = [
[[package]]
name = "derive_more"
version = "0.99.16"
version = "0.99.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df"
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"rustc_version",
"syn",
"syn 1.0.109",
]
[[package]]
......@@ -207,9 +272,9 @@ dependencies = [
[[package]]
name = "dirs-sys"
version = "0.3.6"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
......@@ -218,15 +283,36 @@ dependencies = [
[[package]]
name = "either"
version = "1.6.1"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "errno"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "fixedbitset"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "fnv"
......@@ -242,18 +328,15 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "gcd"
version = "2.1.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37978dab2ca789938a83b2f8bc1ef32db6633af9051a6cd409eff72cbaaa79a"
dependencies = [
"paste",
]
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
[[package]]
name = "getrandom"
version = "0.2.3"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [
"cfg-if",
"libc",
......@@ -262,9 +345,9 @@ dependencies = [
[[package]]
name = "goblin"
version = "0.5.2"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfeb764aa29a0774d290c2df134a37ab2e3c1ba59009162626658aabefda321a"
checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143"
dependencies = [
"log",
"plain",
......@@ -279,9 +362,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
......@@ -293,35 +376,58 @@ dependencies = [
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "indexmap"
version = "1.9.1"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "itertools"
version = "0.10.3"
name = "io-lifetimes"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
"either",
"hermit-abi 0.3.1",
"libc",
"windows-sys",
]
[[package]]
name = "itoa"
version = "0.4.8"
name = "is-terminal"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.3"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "lazy_static"
......@@ -331,15 +437,21 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.139"
version = "0.2.142"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
[[package]]
name = "linux-raw-sys"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf"
[[package]]
name = "log"
version = "0.4.14"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
......@@ -352,9 +464,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memchr"
version = "2.4.1"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
......@@ -367,9 +479,9 @@ dependencies = [
[[package]]
name = "nix"
version = "0.26.1"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46a58d1d356c6597d08cde02c2f09d785b09e28711837b1ed667dc652c08a694"
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
dependencies = [
"bitflags",
"cfg-if",
......@@ -381,36 +493,15 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
[[package]]
name = "os_str_bytes"
version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
[[package]]
name = "paste"
version = "1.0.7"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "petgraph"
version = "0.6.0"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f"
checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
dependencies = [
"fixedbitset",
"indexmap",
......@@ -431,43 +522,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.46"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.9"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
......@@ -511,28 +578,29 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.2.10"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.0"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"redox_syscall",
"thiserror",
]
[[package]]
name = "regex"
version = "1.5.6"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
dependencies = [
"aho-corasick",
"memchr",
......@@ -541,24 +609,38 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.6.26"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
[[package]]
name = "rustc_version"
version = "0.3.3"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "0.37.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0661814f891c57c930a610266415528da53c4933e6dea5fb350cbfe048a9ece"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "ryu"
version = "1.0.5"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "same-file"
......@@ -586,66 +668,54 @@ checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
name = "semver"
version = "0.11.0"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
dependencies = [
"pest",
]
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
[[package]]
name = "serde"
version = "1.0.145"
version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.145"
version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.15",
]
[[package]]
name = "serde_json"
version = "1.0.68"
version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
dependencies = [
"itoa 0.4.8",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.9.13"
version = "0.9.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8613d593412a0deb7bbd8de9d908efff5a0cb9ccd8f62c641e7b2ed2f57291d1"
checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c"
dependencies = [
"indexmap",
"itoa 1.0.3",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
......@@ -674,9 +744,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.101"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
......@@ -684,54 +754,69 @@ dependencies = [
]
[[package]]
name = "termcolor"
version = "1.1.3"
name = "syn"
version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [
"winapi-util",
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "ucd-trie"
version = "0.1.3"
name = "thiserror"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "unsafe-libyaml"
version = "0.2.4"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68"
checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6"
[[package]]
name = "version_check"
version = "0.9.3"
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "walkdir"
version = "2.3.2"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
......@@ -763,3 +848,69 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
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.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
FROM rust:1.63 AS builder
FROM rust:1.69 AS builder
WORKDIR /cwe_checker
......
......@@ -55,7 +55,7 @@ The prebuilt Docker images are currently only x86-based.
### Local installation ###
The following dependencies must be installed in order to build and install the *cwe_checker* locally:
- [Rust](https://www.rust-lang.org) >= 1.63
- [Rust](https://www.rust-lang.org) >= 1.69
- [Ghidra](https://ghidra-sre.org/) >= 10.2 (**Warning:** This applies to the master branch, the v0.6 stable release needs Ghidra 10.1.5)
Run `make all GHIDRA_PATH=/path/to/ghidra_folder` (with the correct path to the local Ghidra installation inserted) to compile and install the cwe_checker.
......
......@@ -105,6 +105,16 @@ impl AbstractIdentifier {
}
}
/// Create a new abstract identifier by removing the last path hint from the path hint array of `self`.
/// Return the new identifier together with the removed path hint (or none if `self` has no path hints).
pub fn without_last_path_hint(&self) -> (Self, Option<Tid>) {
let mut new_id = self.clone();
let inner = Arc::make_mut(&mut new_id.0);
let last_path_hint = inner.path_hints.pop();
(new_id, last_path_hint)
}
/// Get the path hints array of `self`.
pub fn get_path_hints(&self) -> &[Tid] {
&self.path_hints
......
......@@ -261,7 +261,7 @@ fn test_push_constant_subsequences_before_and_between_specifiers() {
let mut specifier_ends: Vec<usize> = vec![0];
specifier_ends.push(matches.get(0).unwrap().end());
for (index, (mat, spec_end)) in itertools::zip(matches, specifier_ends)
for (index, (mat, spec_end)) in std::iter::zip(matches, specifier_ends)
.into_iter()
.enumerate()
{
......
use super::State;
use super::WarningContext;
use super::CWE_MODULE;
use crate::abstract_domain::AbstractDomain;
use crate::abstract_domain::AbstractIdentifier;
use crate::analysis::function_signature::FunctionSignature;
use crate::analysis::graph::Graph;
use crate::analysis::pointer_inference::PointerInference;
......@@ -9,7 +11,6 @@ use crate::intermediate_representation::*;
use crate::prelude::*;
use crate::utils::log::CweWarning;
use crate::utils::log::LogMessage;
use crate::utils::log::LogThreadMsg;
use std::collections::BTreeMap;
/// The context struct for the fixpoint algorithm that contains references to the analysis results
......@@ -23,8 +24,10 @@ pub struct Context<'a> {
pub pointer_inference: &'a PointerInference<'a>,
/// A pointer to the computed function signatures for all internal functions.
pub function_signatures: &'a BTreeMap<Tid, FunctionSignature>,
/// A sender channel that can be used to collect logs in the corresponding logging thread.
pub log_collector: crossbeam_channel::Sender<LogThreadMsg>,
/// A sender channel that can be used to collect context objects for CWEwarnings.
pub cwe_warning_collector: crossbeam_channel::Sender<WarningContext>,
/// A sender channel that can be used to collect log messages.
pub log_collector: crossbeam_channel::Sender<LogMessage>,
/// Generic function arguments assumed for calls to functions where the real number of parameters are unknown.
generic_function_parameter: Vec<Arg>,
}
......@@ -33,7 +36,8 @@ impl<'a> Context<'a> {
/// Generate a new context struct from the given analysis results and a channel for gathering log messages and CWE warnings.
pub fn new<'b>(
analysis_results: &'b AnalysisResults<'a>,
log_collector: crossbeam_channel::Sender<LogThreadMsg>,
cwe_warning_collector: crossbeam_channel::Sender<WarningContext>,
log_collector: crossbeam_channel::Sender<LogMessage>,
) -> Context<'a>
where
'a: 'b,
......@@ -53,6 +57,7 @@ impl<'a> Context<'a> {
graph: analysis_results.control_flow_graph,
pointer_inference: analysis_results.pointer_inference.unwrap(),
function_signatures: analysis_results.function_signatures.unwrap(),
cwe_warning_collector,
log_collector,
generic_function_parameter,
}
......@@ -65,7 +70,7 @@ impl<'a> Context<'a> {
state: &mut State,
call_tid: &Tid,
call_params: impl IntoIterator<Item = &'b Arg>,
) -> Option<Vec<String>> {
) -> Option<Vec<(AbstractIdentifier, Tid)>> {
let mut warnings = Vec::new();
for arg in call_params {
if let Some(arg_value) = self
......@@ -96,37 +101,32 @@ impl<'a> Context<'a> {
Some(fn_sig) => fn_sig,
None => return,
};
let mut warnings = Vec::new();
let mut warning_causes = Vec::new();
for (arg, access_pattern) in &function_signature.parameters {
if access_pattern.is_dereferenced() {
if let Some(arg_value) = self
.pointer_inference
.eval_parameter_arg_at_call(call_tid, arg)
{
if let Some(mut warning_causes) =
state.check_address_for_use_after_free(&arg_value)
{
warnings.append(&mut warning_causes);
if let Some(mut warnings) = state.check_address_for_use_after_free(&arg_value) {
warning_causes.append(&mut warnings);
}
}
}
}
let callee_sub_name = &self.project.program.term.subs[callee_sub_tid].term.name;
if !warnings.is_empty() {
let cwe_warning = CweWarning {
name: "CWE416".to_string(),
version: CWE_MODULE.version.to_string(),
addresses: vec![call_tid.address.clone()],
tids: vec![format!("{call_tid}")],
symbols: Vec::new(),
other: vec![warnings],
description: format!(
if !warning_causes.is_empty() {
self.generate_cwe_warning(
"CWE416",
format!(
"(Use After Free) Call to {} at {} may access dangling pointers through its parameters",
callee_sub_name,
call_tid.address
),
};
self.log_collector.send(cwe_warning.into()).unwrap();
),
call_tid,
warning_causes,
&state.current_fn_tid
);
}
}
......@@ -136,7 +136,7 @@ impl<'a> Context<'a> {
let error_msg = LogMessage::new_error("free symbol without parameter encountered.")
.location(call_tid.clone())
.source(CWE_MODULE.name);
self.log_collector.send(error_msg.into()).unwrap();
self.log_collector.send(error_msg).unwrap();
return;
}
if let Some(param) = self
......@@ -147,23 +147,47 @@ impl<'a> Context<'a> {
if let Some(warning_causes) =
state.handle_param_of_free_call(call_tid, &param, pi_state)
{
let cwe_warning = CweWarning {
name: "CWE415".to_string(),
version: CWE_MODULE.version.to_string(),
addresses: vec![call_tid.address.clone()],
tids: vec![format!("{call_tid}")],
symbols: Vec::new(),
other: vec![warning_causes],
description: format!(
self.generate_cwe_warning(
"CWE415",
format!(
"(Double Free) Object may have been freed before at {}",
call_tid.address
),
};
self.log_collector.send(cwe_warning.into()).unwrap();
call_tid,
warning_causes,
&state.current_fn_tid,
);
}
}
}
}
/// Generate a CWE warning and send it to the warning collector channel.
fn generate_cwe_warning(
&self,
name: &str,
description: String,
location: &Tid,
warning_causes: Vec<(AbstractIdentifier, Tid)>,
root_function: &Tid,
) {
let cwe_warning = CweWarning {
name: name.to_string(),
version: CWE_MODULE.version.to_string(),
addresses: vec![location.address.clone()],
tids: vec![format!("{location}")],
symbols: Vec::new(),
other: Vec::new(),
description,
};
self.cwe_warning_collector
.send(WarningContext::new(
cwe_warning,
warning_causes,
root_function.clone(),
))
.unwrap();
}
}
impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Context<'a> {
......@@ -185,19 +209,16 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
let mut state = state.clone();
if let Some(address) = self.pointer_inference.eval_address_at_def(&def.tid) {
if let Some(warning_causes) = state.check_address_for_use_after_free(&address) {
let cwe_warning = CweWarning {
name: "CWE416".to_string(),
version: CWE_MODULE.version.to_string(),
addresses: vec![def.tid.address.clone()],
tids: vec![format!("{}", def.tid)],
symbols: Vec::new(),
other: vec![warning_causes],
description: format!(
self.generate_cwe_warning(
"CWE416",
format!(
"(Use After Free) Access through a dangling pointer at {}",
def.tid.address
),
};
self.log_collector.send(cwe_warning.into()).unwrap();
&def.tid,
warning_causes,
&state.current_fn_tid,
);
}
}
Some(state)
......@@ -293,46 +314,40 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
match extern_symbol.name.as_str() {
"free" => self.handle_call_to_free(&mut state, &call.tid, extern_symbol),
extern_symbol_name => {
if let Some(warnings) = self.collect_cwe_warnings_of_call_params(
if let Some(warning_causes) = self.collect_cwe_warnings_of_call_params(
&mut state,
&call.tid,
&extern_symbol.parameters,
) {
let cwe_warning = CweWarning {
name: "CWE416".to_string(),
version: CWE_MODULE.version.to_string(),
addresses: vec![call.tid.address.clone()],
tids: vec![format!("{}", call.tid)],
symbols: Vec::new(),
other: vec![warnings],
description: format!(
self.generate_cwe_warning(
"CWE416",
format!(
"(Use After Free) Call to {} at {} may access dangling pointers through its parameters",
extern_symbol_name,
call.tid.address
),
};
self.log_collector.send(cwe_warning.into()).unwrap();
&call.tid,
warning_causes,
&state.current_fn_tid,
);
}
}
}
} else if let Some(warnings) = self.collect_cwe_warnings_of_call_params(
} else if let Some(warning_causes) = self.collect_cwe_warnings_of_call_params(
&mut state,
&call.tid,
&self.generic_function_parameter,
) {
let cwe_warning = CweWarning {
name: "CWE416".to_string(),
version: CWE_MODULE.version.to_string(),
addresses: vec![call.tid.address.clone()],
tids: vec![format!("{}", call.tid)],
symbols: Vec::new(),
other: vec![warnings],
description: format!(
self.generate_cwe_warning(
"CWE416",
format!(
"(Use After Free) Call at {} may access dangling pointers through its parameters",
call.tid.address
),
};
self.log_collector.send(cwe_warning.into()).unwrap();
&call.tid,
warning_causes,
&state.current_fn_tid,
);
}
Some(state)
}
......
......@@ -33,10 +33,19 @@
//! - The analysis currently only tracks pointers to objects that were freed by a call to `free`.
//! If a memory object is freed by another external function then this may lead to false negatives in this check.
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::collections::HashSet;
use crate::abstract_domain::AbstractDomain;
use crate::abstract_domain::AbstractIdentifier;
use crate::analysis::fixpoint::Computation;
use crate::analysis::forward_interprocedural_fixpoint::GeneralizedContext;
use crate::analysis::graph::Node;
use crate::analysis::interprocedural_fixpoint_generic::NodeValue;
use crate::prelude::*;
use crate::utils::log::CweWarning;
use crate::utils::log::LogMessage;
use crate::utils::log::LogThread;
use crate::CweModule;
/// The module name and version
......@@ -61,8 +70,9 @@ pub fn check_cwe(
analysis_results: &AnalysisResults,
_config: &serde_json::Value,
) -> (Vec<LogMessage>, Vec<CweWarning>) {
let log_thread = LogThread::spawn(LogThread::collect_and_deduplicate);
let context = Context::new(analysis_results, log_thread.get_msg_sender());
let (cwe_warning_sender, cwe_warning_receiver) = crossbeam_channel::unbounded();
let (log_sender, log_receiver) = crossbeam_channel::unbounded();
let context = Context::new(analysis_results, cwe_warning_sender, log_sender);
let mut fixpoint_computation =
crate::analysis::forward_interprocedural_fixpoint::create_computation(context, None);
......@@ -78,6 +88,208 @@ pub fn check_cwe(
}
fixpoint_computation.compute_with_max_steps(100);
let (logs, cwe_warnings) = log_thread.collect();
(logs, cwe_warnings)
let mut warnings = HashSet::new();
while let Ok(warning) = cwe_warning_receiver.try_recv() {
warnings.insert(warning);
}
let return_site_states = collect_return_site_states(&fixpoint_computation);
let cwes = generate_context_information_for_warnings(return_site_states, warnings);
let mut logs = BTreeSet::new();
while let Ok(log_msg) = log_receiver.try_recv() {
logs.insert(log_msg);
}
(logs.into_iter().collect(), cwes.into_iter().collect())
}
/// A struct for collecting CWE warnings together with context information
/// that can be used to post-process the warning after the fixpoint has been computed.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct WarningContext {
/// The CWE warning.
cwe: CweWarning,
/// The TID of the function in which the CWE warning was generated.
root_function: Tid,
/// Pairs of object IDs and the sites where the object was freed.
/// If the free-site is the same function call from which the object ID originates
/// then the CWE needs to be post-processed to give more exact information about the
/// free-site inside the function call.
object_and_free_ids: Vec<(AbstractIdentifier, Tid)>,
}
impl WarningContext {
/// Generate a new warning context object.
pub fn new(
cwe: CweWarning,
object_and_free_ids: Vec<(AbstractIdentifier, Tid)>,
root_function: Tid,
) -> Self {
WarningContext {
cwe,
root_function,
object_and_free_ids,
}
}
}
/// For each function call TID collect the state of the callee just before returning to the caller.
fn collect_return_site_states<'a>(
fixpoint: &Computation<GeneralizedContext<'a, Context<'a>>>,
) -> HashMap<Tid, State> {
let mut call_tid_to_return_state_map: HashMap<Tid, State> = HashMap::new();
let graph = fixpoint.get_graph();
for node in graph.node_indices() {
let call_tid = match graph[node] {
Node::CallReturn { call, return_: _ } => call.0.term.jmps[0].tid.clone(),
_ => continue,
};
let node_value = match fixpoint.get_node_value(node) {
Some(value) => value,
None => continue,
};
let return_state = match node_value {
NodeValue::CallFlowCombinator {
call_stub: _,
interprocedural_flow,
} => {
if let Some(state) = interprocedural_flow {
state.clone()
} else {
continue;
}
}
_ => panic!("Unexpexted NodeValue type encountered."),
};
// There exists one CallReturn node for each return instruction in the callee,
// so we have to merge the corresponding states here.
call_tid_to_return_state_map
.entry(call_tid)
.and_modify(|saved_return_state| {
*saved_return_state = saved_return_state.merge(&return_state)
})
.or_insert(return_state);
}
call_tid_to_return_state_map
}
/// If the ID of the "free"-site is the same call from which the object ID originates from
/// then (recursively) identify the real "free"-site inside the call.
/// Also return a list of call TIDs that lead to the real "free"-site.
///
/// The function returns an error if the source object was already flagged in some of the callees.
/// In such a case the corresponding CWE warning should be removed,
/// since there already exists another CWE warning with the same root cause.
fn get_source_of_free(
object_id: &AbstractIdentifier,
free_id: &Tid,
return_site_states: &HashMap<Tid, State>,
) -> Result<(Tid, Vec<Tid>), ()> {
if let (inner_object, Some(path_hint_id)) = object_id.without_last_path_hint() {
if path_hint_id == *free_id {
if let Some(return_state) = return_site_states.get(free_id) {
if return_state.is_id_already_flagged(&inner_object) {
return Err(());
}
if let Some(inner_free) = return_state.get_free_tid_if_dangling(&inner_object) {
let (root_free, mut callgraph_ids) =
get_source_of_free(&inner_object, inner_free, return_site_states)?;
callgraph_ids.push(path_hint_id);
return Ok((root_free, callgraph_ids));
}
}
}
}
// No inner source apart from the given free_id could be identified
Ok((free_id.clone(), Vec::new()))
}
/// Generate context information for CWE warnings.
/// E.g. relevant callgraph addresses are added to each CWE here.
fn generate_context_information_for_warnings(
return_site_states: HashMap<Tid, State>,
warnings: HashSet<WarningContext>,
) -> BTreeSet<CweWarning> {
let mut processed_warnings = BTreeSet::new();
for mut warning in warnings {
let mut context_infos = Vec::new();
let mut relevant_callgraph_tids = Vec::new();
for (object_id, free_id) in warning.object_and_free_ids.iter() {
if let Ok((root_free_id, mut callgraph_ids_to_free)) =
get_source_of_free(object_id, free_id, &return_site_states)
{
relevant_callgraph_tids.append(&mut callgraph_ids_to_free);
context_infos.push(format!(
"Accessed ID {object_id} may have been freed before at {root_free_id}."
));
}
}
if context_infos.is_empty() {
// Skip (delete) this CWE warning,
// since another warning with the same root cause was already generated in some callee.
continue;
}
let mut callgraph_tids_as_string = format!("{}", warning.root_function);
for id in relevant_callgraph_tids {
callgraph_tids_as_string += &format!(", {id}");
}
context_infos.push(format!(
"Relevant callgraph TIDs: [{callgraph_tids_as_string}]"
));
warning.cwe.other = vec![context_infos];
processed_warnings.insert(warning.cwe);
}
processed_warnings
}
#[cfg(test)]
pub mod tests {
use super::*;
use crate::{
abstract_domain::{AbstractIdentifier, AbstractLocation},
checkers::cwe_416::WarningContext,
intermediate_representation::*,
utils::log::CweWarning,
variable,
};
#[test]
fn test_warning_context_generation() {
let id = AbstractIdentifier::new(
Tid::new("object_origin_tid"),
AbstractLocation::Register(variable!("RAX:8")),
);
let path_id = id.with_path_hint(Tid::new("call_tid")).unwrap();
let object_and_free_ids = vec![(path_id, Tid::new("call_tid"))];
let cwe = CweWarning::new("CWE416", "test", "mock_cwe");
let warning_context =
WarningContext::new(cwe, object_and_free_ids, Tid::new("root_func_tid"));
let warnings = HashSet::from([warning_context]);
// Test warning context generation
let return_state = State::mock(
Tid::new("callee_tid"),
&[(id.clone(), Tid::new("free_tid"))],
&[],
);
let return_site_states = HashMap::from([(Tid::new("call_tid"), return_state)]);
let processed_warnings =
generate_context_information_for_warnings(return_site_states, warnings.clone());
assert_eq!(processed_warnings.len(), 1);
let processed_cwe = processed_warnings.iter().next().unwrap();
assert_eq!(&processed_cwe.other[0], &[
"Accessed ID object_origin_tid(->call_tid) @ RAX may have been freed before at free_tid.".to_string(),
"Relevant callgraph TIDs: [root_func_tid, call_tid]".to_string(),
]);
// Test warning filtering
let return_state = State::mock(Tid::new("callee_tid"), &[], &[id.clone()]);
let return_site_states = HashMap::from([(Tid::new("call_tid"), return_state)]);
let processed_warnings =
generate_context_information_for_warnings(return_site_states, warnings);
assert_eq!(processed_warnings.len(), 0)
}
}
......@@ -25,8 +25,8 @@ impl AbstractDomain for ObjectState {
(ObjectState::AlreadyFlagged, _) | (_, ObjectState::AlreadyFlagged) => {
ObjectState::AlreadyFlagged
}
(ObjectState::Dangling(tid), ObjectState::Dangling(_)) => {
ObjectState::Dangling(tid.clone())
(ObjectState::Dangling(tid), ObjectState::Dangling(other_tid)) => {
ObjectState::Dangling(std::cmp::min(tid, other_tid).clone())
}
}
}
......@@ -54,17 +54,34 @@ impl State {
}
}
/// Return whether the given object ID is already flagged in this state,
/// i.e. whether a CWE warning was already generated for this object.
pub fn is_id_already_flagged(&self, object_id: &AbstractIdentifier) -> bool {
self.dangling_objects.get(object_id) == Some(&ObjectState::AlreadyFlagged)
}
/// If the given `object_id` represents a dangling object, return the TID of the site where it was freed.
pub fn get_free_tid_if_dangling(&self, object_id: &AbstractIdentifier) -> Option<&Tid> {
if let Some(ObjectState::Dangling(free_tid)) = self.dangling_objects.get(object_id) {
Some(free_tid)
} else {
None
}
}
/// Check the given address on whether it may point to already freed memory.
/// For each possible dangling pointer target a string describing the root cause is returnen.
/// For each possible dangling pointer target the abstract ID of the object
/// and the TID of the corresponding site where the object was freed is returned.
/// The object states of corresponding memory objects are set to [`ObjectState::AlreadyFlagged`]
/// to prevent reporting duplicate CWE messages with the same root cause.
pub fn check_address_for_use_after_free(&mut self, address: &Data) -> Option<Vec<String>> {
pub fn check_address_for_use_after_free(
&mut self,
address: &Data,
) -> Option<Vec<(AbstractIdentifier, Tid)>> {
let mut free_ids_of_dangling_pointers = Vec::new();
for id in address.get_relative_values().keys() {
if let Some(ObjectState::Dangling(free_id)) = self.dangling_objects.get(id) {
free_ids_of_dangling_pointers.push(format!(
"Accessed ID {id} may have been already freed at {free_id}"
));
free_ids_of_dangling_pointers.push((id.clone(), free_id.clone()));
self.dangling_objects
.insert(id.clone(), ObjectState::AlreadyFlagged);
......@@ -84,7 +101,7 @@ impl State {
call_tid: &Tid,
param: &Data,
pi_state: &PiState,
) -> Option<Vec<String>> {
) -> Option<Vec<(AbstractIdentifier, Tid)>> {
// FIXME: This function could also generate debug log messages whenever nonsensical information is detected.
// E.g. stack frame IDs or non-zero ID offsets can be indicators of other bugs.
let mut warnings = Vec::new();
......@@ -99,9 +116,7 @@ impl State {
.dangling_objects
.insert(id.clone(), ObjectState::Dangling(call_tid.clone()))
{
warnings.push(format!(
"Object {id} may have been freed before at {old_free_id}."
));
warnings.push((id.clone(), old_free_id.clone()));
}
}
if !warnings.is_empty() {
......@@ -164,12 +179,61 @@ impl AbstractDomain for State {
}
}
impl State {
/// Get a more compact json-representation of the state.
/// Intended for pretty printing, not useable for serialization/deserialization.
#[allow(dead_code)]
pub fn to_json_compact(&self) -> serde_json::Value {
use serde_json::*;
let mut state_map = Map::new();
state_map.insert(
"current_function".to_string(),
Value::String(format!("{}", self.current_fn_tid)),
);
for (id, object_state) in self.dangling_objects.iter() {
if let ObjectState::Dangling(free_tid) = object_state {
state_map.insert(
format!("{id}"),
Value::String(format!("Dangling({free_tid})")),
);
} else {
state_map.insert(
format!("{id}"),
Value::String("Already flagged".to_string()),
);
}
}
Value::Object(state_map)
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use crate::{bitvec, intermediate_representation::parsing, variable};
use std::collections::BTreeSet;
impl State {
pub fn mock(
current_fn_tid: Tid,
dangling_ids: &[(AbstractIdentifier, Tid)],
already_flagged_ids: &[AbstractIdentifier],
) -> Self {
let mut state = State::new(current_fn_tid);
for (id, free_id) in dangling_ids.iter() {
state
.dangling_objects
.insert(id.clone(), ObjectState::Dangling(free_id.clone()));
}
for id in already_flagged_ids.iter() {
state
.dangling_objects
.insert(id.clone(), ObjectState::AlreadyFlagged);
}
state
}
}
#[test]
fn test_check_address_for_use_after_free() {
let mut state = State::new(Tid::new("current_fn"));
......
......@@ -193,7 +193,7 @@ pub mod parsing {
r"^((0x(-)?[[:alnum:]]+)|^(-)?([0-9])+)+:[0-9]+$", // Constant
r"^[^\+]*\+{1}[^\+]*$", // BinOp (IntAdd)
r"^[[:ascii:]]+ \-{1} [[:ascii:]]+$", // BinOp (IntSub)
r"^-\([[:ascii:]]*\)$", // UnOp (IntNegate)
r"^-\([[:ascii:]]*\)$", // UnOp (IntNegate)
r"^¬\([[:ascii:]]*\)$", // UnOp (BoolNegate)
])
.unwrap();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment