mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge remote-tracking branch 'upstream/main' into cert-checks
This commit is contained in:
9
rust/ql/.generated.list
generated
9
rust/ql/.generated.list
generated
@@ -235,7 +235,6 @@ lib/codeql/rust/elements/internal/AwaitExprConstructor.qll 44ff1653e73d5b9f6885c
|
||||
lib/codeql/rust/elements/internal/BecomeExprConstructor.qll ba073aaa256cb8827a0307c3128d50f62b11aac0b1f324e48c95f30351a9b942 3a787ded505c3158fa4f4923f66e8ecdcb7b5f86f27f64c5412dc32dca031f18
|
||||
lib/codeql/rust/elements/internal/BinaryExprConstructor.qll 7f9b17757f78b9fb7c46e21d2040a77fa50083bef4911c8464991c3d1ad91d87 a59390cd8e896c0bfbdc9ba0674e06d980ffcefa710fbc9886be52ed427e9717
|
||||
lib/codeql/rust/elements/internal/BlockExprConstructor.qll 438337c807645e98a01440f3f4610d68b0567ba15c8f51dc43bf5a30c9af3696 48ce7a546910c884619762349b8ada9836284f8008298fdb0070a38f7ddf25a0
|
||||
lib/codeql/rust/elements/internal/BlockExprImpl.qll 36ac09e4a6eeeec22919b62b1d004bdb5bb2527e67932c308aec383a770768d6 3b4b2a2014f6fe075c63a2d633b297566b548ef2e4343cadf067a9edbcadc876
|
||||
lib/codeql/rust/elements/internal/BoxPatConstructor.qll 153f110ba25fd6c889092bfd16f73bb610fa60d6e0c8965d5f44d2446fcd48a2 9324cf0d8aa29945551bf8ab64801d598f57aab8cd4e19bcd4e9ef8a4a4e06eb
|
||||
lib/codeql/rust/elements/internal/BreakExprConstructor.qll 356be043c28e0b34fdf925a119c945632ee883c6f5ebb9a27003c6a8d250afd9 bb77e66b04bb9489340e7506931559b94285c6904b6f9d2f83b214cba4f3cfd5
|
||||
lib/codeql/rust/elements/internal/CallExprConstructor.qll 742b38e862e2cf82fd1ecc4d4fc5b4782a9c7c07f031452b2bae7aa59d5aa13a cad6e0a8be21d91b20ac2ec16cab9c30eae810b452c0f1992ed87d5c7f4144dc
|
||||
@@ -247,7 +246,6 @@ lib/codeql/rust/elements/internal/ConstArgImpl.qll dc7e7b5fe1a6eeb61dd30a55a3ed2
|
||||
lib/codeql/rust/elements/internal/ConstBlockPatConstructor.qll ddb4a0045635d477e87360ecafec0ba90ddcffc6e62996eb6e7edd5a5d65b860 442061d0497a615b3f008b990f5e3c4f045110f76500eff81a7f44ffd1319acf
|
||||
lib/codeql/rust/elements/internal/ConstBlockPatImpl.qll 2082a3244c21e03b6dadfba9b3f97a00981324e10d1465d3a51cf3c921eb89e4 889e347834d8c6e90dfef9714af073b3b2193f6830f1c8356cee9c6573b3ecb4
|
||||
lib/codeql/rust/elements/internal/ConstConstructor.qll 72a31fd9b8b3fd910e35af1b2b30fa54cc4d9e14e7eabdb94b4cd2af95b2df38 3edc0a82a7b446fdfd3e71947801f3c7cac010b2a217b8accb69980387bdd67a
|
||||
lib/codeql/rust/elements/internal/ConstImpl.qll 058b474b9aaf2ad687ab1e62ebc8a51ba93d9ea4340c2f41768b71613ac330c1 c2c5d4746a588096cbbdfa4355ee73d806c7a4ac9507930a120e49060f9d5347
|
||||
lib/codeql/rust/elements/internal/ConstParamConstructor.qll f6645f952aac87c7e00e5e9661275312a1df47172088b4de6b5a253d5c4ed048 eda737470a7b89cf6a02715c9147d074041d6d00fd50d5b2d70266add6e4b571
|
||||
lib/codeql/rust/elements/internal/ConstParamImpl.qll c6995be58f84d1df65897c80f7ee3dd8eb410bb3e634ff1bfe1be94dfb3fdf32 bcfb5547b40f24bcec20056fe1d36724b734c920b0bc7538fe2974b03f4478fe
|
||||
lib/codeql/rust/elements/internal/ContinueExprConstructor.qll cd93f1b35ccdb031d7e8deba92f6a76187f6009c454f3ea07e89ba459de57ca6 6f658e7d580c4c9068b01d6dd6f72888b8800860668a6653f8c3b27dc9996935
|
||||
@@ -288,7 +286,6 @@ lib/codeql/rust/elements/internal/ImplConstructor.qll 24edccca59f70d812d1458b412
|
||||
lib/codeql/rust/elements/internal/ImplTraitTypeReprConstructor.qll 1ed355e5e56f432b24b6f4778e4dc45c6e65095190cacb7a5015529e0c9d01f8 c8505185a042da4eb20a0cc32323194a0290c4bf821c7e0fce7351b194b10f31
|
||||
lib/codeql/rust/elements/internal/IndexExprConstructor.qll 99bdc3d793c4dbd993860da60abe2b7c604345d645e86916462bc55a6939a5d1 3fe9d7da725956903707806aadbecac8d5b3874e8bed63c9bab54fff630e75dd
|
||||
lib/codeql/rust/elements/internal/InferTypeReprConstructor.qll bc5f16853401617fc9c5af8a1287a23c5921df1b615cfbe2d7c7a70145ecfcbd da93bd28ea2daade2cbb0a729be3fbf05f72bc02009565c7bb062e4f68fdb9e7
|
||||
lib/codeql/rust/elements/internal/ItemImpl.qll e3fb78d572ce1c3cc857d2671bd71ff4d7850321acfddc5f15533ff87accda79 fbabc2081e4b2773b04938d57bb51af908c80b7bc53c3127c74ab5d4fb9837bc
|
||||
lib/codeql/rust/elements/internal/ItemListConstructor.qll 08af3bd12536941c3dd4a43c81cc861be24325e242e2593c087a3ce632674291 2fa166159c409d2aaffa73a30babb40829a6de580bd40894d909ee6152801082
|
||||
lib/codeql/rust/elements/internal/ItemListImpl.qll 195dbe93c334ad2bfc29db530bda9aaea88fc31696b2f230faae9e6c2ecb74a8 e498983a5b2f7a91e2fd336e85ac17e521a18c677784a0788d95bb283f3652e7
|
||||
lib/codeql/rust/elements/internal/LabelConstructor.qll 1f814c94251e664bfa1b1a606aef995382e40e78d4f953350ec951ee0bc8bd34 3157fb8c7c6bd365a739f217ad73ba1e0b65ccd59b922e5ab034e3449915b36c
|
||||
@@ -569,7 +566,7 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll eaa0cd4402d3665013d47e
|
||||
lib/codeql/rust/elements/internal/generated/ParenExpr.qll 812d2ff65079277f39f15c084657a955a960a7c1c0e96dd60472a58d56b945eb eb8c607f43e1fcbb41f37a10de203a1db806690e10ff4f04d48ed874189cb0eb
|
||||
lib/codeql/rust/elements/internal/generated/ParenPat.qll 24f9dc7fce75827d6fddb856cd48f80168143151b27295c0bab6db5a06567a09 ebadbc6f5498e9ed754b39893ce0763840409a0721036a25b56e1ead7dcc09aa
|
||||
lib/codeql/rust/elements/internal/generated/ParenTypeRepr.qll 03f5c5b96a37adeb845352d7fcea3e098da9050e534972d14ac0f70d60a2d776 ed3d6e5d02086523087adebce4e89e35461eb95f2a66d1d4100fe23fc691b126
|
||||
lib/codeql/rust/elements/internal/generated/ParentChild.qll 6e86fd9b6d5ec1b4aeeb5472cc6d2ebf3328bbaa8605cf52c9add56652cc47dc 3cf2a8e12ffb6631221c7b94fa112e8e3be96efba697996862685a87b2c9aff7
|
||||
lib/codeql/rust/elements/internal/generated/ParentChild.qll f04ca3d02170f7e532a480cc81748cf04f1b022d5e0e32ffcdf0f15c8f1961aa 999104d69a5435c9cab594e04b82ed26ae38b1b1d2ac1dbbb315a433c586f941
|
||||
lib/codeql/rust/elements/internal/generated/ParenthesizedArgList.qll d901fdc8142a5b8847cc98fc2afcfd16428b8ace4fbffb457e761b5fd3901a77 5dbb0aea5a13f937da666ccb042494af8f11e776ade1459d16b70a4dd193f9fb
|
||||
lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4
|
||||
lib/codeql/rust/elements/internal/generated/Path.qll 9b12afb46fc5a9ad3a811b05472621bbecccb900c47504feb7f29d96b28421ca bcacbffc36fb3e0c9b26523b5963af0ffa9fd6b19f00a2a31bdb2316071546bd
|
||||
@@ -584,7 +581,7 @@ lib/codeql/rust/elements/internal/generated/PtrTypeRepr.qll 8d0ea4f6c7f8203340bf
|
||||
lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f
|
||||
lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9
|
||||
lib/codeql/rust/elements/internal/generated/RangePat.qll 80826a6a6868a803aa2372e31c52a03e1811a3f1f2abdb469f91ca0bfdd9ecb6 34ee1e208c1690cba505dff2c588837c0cd91e185e2a87d1fe673191962276a9
|
||||
lib/codeql/rust/elements/internal/generated/Raw.qll f50925f4925848cef73003adf01420566ca3efa16f491eadac62a30972ee9204 17d62252413618e1fa162c6c0b303ccfcac5f7f70cc170d739b20cc95f57035b
|
||||
lib/codeql/rust/elements/internal/generated/Raw.qll 14758dc2e2a9af251f24e24516eab0fc95d334c1da06f418ea5da3c5521642c9 a8b6637f57293a85714cc8761f8fd1e23780d58f3873acaa3c77acd9cbfcf19f
|
||||
lib/codeql/rust/elements/internal/generated/RefExpr.qll 7d995884e3dc1c25fc719f5d7253179344d63650e217e9ff6530285fe7a57f64 f2c3c12551deea4964b66553fb9b6423ee16fec53bd63db4796191aa60dc6c66
|
||||
lib/codeql/rust/elements/internal/generated/RefPat.qll 456ede39837463ee22a630ec7ab6c8630d3664a8ea206fcc6e4f199e92fa564c 5622062765f32930465ba6b170e986706f159f6070f48adee3c20e24e8df4e05
|
||||
lib/codeql/rust/elements/internal/generated/RefTypeRepr.qll 5b0663a6d234572fb3e467e276d019415caa95ef006438cc59b7af4e1783161e 0e27c8a8f0e323c0e4d6db01fca821bf07c0864d293cdf96fa891b10820c1e4b
|
||||
@@ -609,7 +606,7 @@ lib/codeql/rust/elements/internal/generated/StructFieldList.qll 5da528a51a6a5db9
|
||||
lib/codeql/rust/elements/internal/generated/StructPat.qll c76fa005c2fd0448a8803233e1e8818c4123301eb66ac5cf69d0b9eaafc61e98 6e0dffccdce24bca20e87d5ba0f0995c9a1ae8983283e71e7dbfcf6fffc67a58
|
||||
lib/codeql/rust/elements/internal/generated/StructPatField.qll 5b5c7302dbc4a902ca8e69ff31875c867e295a16a626ba3cef29cd0aa248f179 4e192a0df79947f5cb0d47fdbbba7986137a6a40a1be92ae119873e2fad67edf
|
||||
lib/codeql/rust/elements/internal/generated/StructPatFieldList.qll 1a95a1bd9f64fb18e9571657cf2d02a8b13c747048a1f0f74baf31b91f0392ad fc274e414ff4ed54386046505920de92755ad0b4d39a7523cdffa4830bd53b37
|
||||
lib/codeql/rust/elements/internal/generated/Synth.qll 4c741d502d21d449c4e01010776f767c69b408c80ce7d10784b599463bcfd0e3 c76b8628663c126914ead897c779ce782294e9109125d61de958e0eee543abce
|
||||
lib/codeql/rust/elements/internal/generated/Synth.qll a8ea364358a2bc3a9226d451c0867e89c29509a0f54dd88ed23c77045db2c85a a44de5e84a63cb5a1bfa66b0df33bf28c9f8b6628393d0f3b2f6215dabee47bd
|
||||
lib/codeql/rust/elements/internal/generated/SynthConstructors.qll f41abfc73415b7accb38da7c107faebfe6843c270ad54e0e54a96e930dfe479a f41abfc73415b7accb38da7c107faebfe6843c270ad54e0e54a96e930dfe479a
|
||||
lib/codeql/rust/elements/internal/generated/Token.qll 77a91a25ca5669703cf3a4353b591cef4d72caa6b0b9db07bb9e005d69c848d1 2fdffc4882ed3a6ca9ac6d1fb5f1ac5a471ca703e2ffdc642885fa558d6e373b
|
||||
lib/codeql/rust/elements/internal/generated/TokenTree.qll 1a3c4f5f30659738641abdd28cb793dab3cfde484196b59656fc0a2767e53511 de2ebb210c7759ef7a6f7ee9f805e1cac879221287281775fc80ba34a5492edf
|
||||
|
||||
3
rust/ql/.gitattributes
generated
vendored
3
rust/ql/.gitattributes
generated
vendored
@@ -237,7 +237,6 @@
|
||||
/lib/codeql/rust/elements/internal/BecomeExprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/BinaryExprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/BlockExprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/BlockExprImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/BoxPatConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/BreakExprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/CallExprConstructor.qll linguist-generated
|
||||
@@ -249,7 +248,6 @@
|
||||
/lib/codeql/rust/elements/internal/ConstBlockPatConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ConstBlockPatImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ConstConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ConstImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ConstParamConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ConstParamImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ContinueExprConstructor.qll linguist-generated
|
||||
@@ -290,7 +288,6 @@
|
||||
/lib/codeql/rust/elements/internal/ImplTraitTypeReprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/IndexExprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/InferTypeReprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ItemImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ItemListConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ItemListImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/LabelConstructor.qll linguist-generated
|
||||
|
||||
4
rust/ql/examples/qlpack.lock.yml
Normal file
4
rust/ql/examples/qlpack.lock.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
dependencies: {}
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
7
rust/ql/examples/qlpack.yml
Normal file
7
rust/ql/examples/qlpack.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
name: codeql/rust-examples
|
||||
groups:
|
||||
- rust
|
||||
- examples
|
||||
dependencies:
|
||||
codeql/rust-all: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
18
rust/ql/examples/snippets/empty_if.ql
Normal file
18
rust/ql/examples/snippets/empty_if.ql
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @name Empty 'if' expression
|
||||
* @description Finds 'if' expressions where the "then" branch is empty and no
|
||||
* "else" branch exists.
|
||||
* @id rust/examples/empty-if
|
||||
* @tags example
|
||||
*/
|
||||
|
||||
import rust
|
||||
|
||||
// find 'if' expressions...
|
||||
from IfExpr ifExpr
|
||||
where
|
||||
// where the 'then' branch is empty
|
||||
ifExpr.getThen().getStmtList().getNumberOfStmtOrExpr() = 0 and
|
||||
// and no 'else' branch exists
|
||||
not ifExpr.hasElse()
|
||||
select ifExpr, "This 'if' expression is redundant."
|
||||
48
rust/ql/examples/snippets/simple_constant_password.ql
Normal file
48
rust/ql/examples/snippets/simple_constant_password.ql
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @name Constant password
|
||||
* @description Finds places where a string literal is used in a function call
|
||||
* argument that looks like a password.
|
||||
* @id rust/examples/simple-constant-password
|
||||
* @tags example
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.rust.dataflow.DataFlow
|
||||
import codeql.rust.dataflow.TaintTracking
|
||||
|
||||
/**
|
||||
* A data flow configuration for tracking flow from a string literal to a function
|
||||
* call argument that looks like a password. For example:
|
||||
* ```
|
||||
* fn set_password(password: &str) { ... }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* let pwd = "123456"; // source
|
||||
* set_password(pwd); // sink (argument 0)
|
||||
* ```
|
||||
*/
|
||||
module ConstantPasswordConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
// `node` is a string literal
|
||||
node.asExpr() instanceof StringLiteralExpr
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
// `node` is an argument whose corresponding parameter name matches the pattern "pass%"
|
||||
exists(CallExpr call, Function target, int argIndex, Variable v |
|
||||
call.getStaticTarget() = target and
|
||||
v.getParameter() = target.getParam(argIndex) and
|
||||
v.getText().matches("pass%") and
|
||||
call.getArg(argIndex) = node.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// instantiate the data flow configuration as a global taint tracking module
|
||||
module ConstantPasswordFlow = TaintTracking::Global<ConstantPasswordConfig>;
|
||||
|
||||
// report flows from sources to sinks
|
||||
from DataFlow::Node sourceNode, DataFlow::Node sinkNode
|
||||
where ConstantPasswordFlow::flow(sourceNode, sinkNode)
|
||||
select sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
|
||||
39
rust/ql/examples/snippets/simple_sql_injection.ql
Normal file
39
rust/ql/examples/snippets/simple_sql_injection.ql
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @name Database query built from user-controlled sources
|
||||
* @description Finds places where a value from a remote or local user input
|
||||
* is used as the first argument of a call to `sqlx_core::query::query`.
|
||||
* @id rust/examples/simple-sql-injection
|
||||
* @tags example
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.rust.dataflow.DataFlow
|
||||
import codeql.rust.dataflow.TaintTracking
|
||||
import codeql.rust.Concepts
|
||||
|
||||
/**
|
||||
* A data flow configuration for tracking flow from a user input (threat model
|
||||
* source) to the first argument of a call to `sqlx_core::query::query`.
|
||||
*/
|
||||
module SqlInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
// `node` is a user input (threat model source)
|
||||
node instanceof ActiveThreatModelSource
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
// `node` is the first argument of a call to `sqlx_core::query::query`
|
||||
exists(CallExpr call |
|
||||
call.getStaticTarget().getCanonicalPath() = "sqlx_core::query::query" and
|
||||
call.getArg(0) = node.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// instantiate the data flow configuration as a global taint tracking module
|
||||
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
|
||||
|
||||
// report flows from sources to sinks
|
||||
from DataFlow::Node sourceNode, DataFlow::Node sinkNode
|
||||
where SqlInjectionFlow::flow(sourceNode, sinkNode)
|
||||
select sinkNode, "This query depends on a $@.", sourceNode, "user-provided value"
|
||||
@@ -7,4 +7,5 @@ mod a_module;
|
||||
fn main() {
|
||||
my_macro2!(); // $ item=my_macro2
|
||||
hello(); // $ item=HELLO
|
||||
lib::extern_crate_alias::a_module::hello(); // $ item=HELLO
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| exe/src/main.rs:7:1:10:1 | fn main |
|
||||
| exe/src/main.rs:7:1:11:1 | fn main |
|
||||
| lib/src/a_module/mod.rs:1:1:4:1 | fn hello |
|
||||
|
||||
@@ -15,3 +15,5 @@ mod macros {
|
||||
}
|
||||
|
||||
pub mod a_module;
|
||||
|
||||
pub extern crate self as extern_crate_alias;
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
| Inconsistencies - Path resolution | 0 |
|
||||
| Inconsistencies - SSA | 0 |
|
||||
| Inconsistencies - data flow | 0 |
|
||||
| Lines of code extracted | 21 |
|
||||
| Lines of user code extracted | 21 |
|
||||
| Lines of code extracted | 23 |
|
||||
| Lines of user code extracted | 23 |
|
||||
| Macro calls - resolved | 10 |
|
||||
| Macro calls - total | 10 |
|
||||
| Macro calls - unresolved | 0 |
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
| Inconsistencies - Path resolution | 0 |
|
||||
| Inconsistencies - SSA | 0 |
|
||||
| Inconsistencies - data flow | 0 |
|
||||
| Lines of code extracted | 21 |
|
||||
| Lines of user code extracted | 21 |
|
||||
| Lines of code extracted | 23 |
|
||||
| Lines of user code extracted | 23 |
|
||||
| Macro calls - resolved | 10 |
|
||||
| Macro calls - total | 10 |
|
||||
| Macro calls - unresolved | 0 |
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
## 0.1.20
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added models for cookie methods in the `poem` crate.
|
||||
|
||||
## 0.1.19
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
4
rust/ql/lib/change-notes/2025-11-19-dataflow-ast.md
Normal file
4
rust/ql/lib/change-notes/2025-11-19-dataflow-ast.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The type `DataFlow::Node` is now based directly on the AST instead of the CFG, which means that predicates like `asExpr()` return AST nodes instead of CFG nodes.
|
||||
5
rust/ql/lib/change-notes/released/0.1.20.md
Normal file
5
rust/ql/lib/change-notes/released/0.1.20.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 0.1.20
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added models for cookie methods in the `poem` crate.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.1.19
|
||||
lastReleaseVersion: 0.1.20
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
* provide concrete subclasses.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.dataflow.internal.DataFlowImpl
|
||||
private import codeql.Locations
|
||||
private import codeql.threatmodels.ThreatModels
|
||||
private import codeql.rust.Frameworks
|
||||
private import codeql.rust.dataflow.FlowSource
|
||||
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
|
||||
private import codeql.rust.controlflow.CfgNodes as CfgNodes
|
||||
private import codeql.concepts.ConceptsShared
|
||||
|
||||
private module ConceptsShared = ConceptsMake<Location, RustDataFlow>;
|
||||
@@ -345,16 +344,16 @@ module Path {
|
||||
SafeAccessCheck() { this = DataFlow::BarrierGuard<safeAccessCheck/3>::getABarrierNode() }
|
||||
}
|
||||
|
||||
private predicate safeAccessCheck(CfgNodes::AstCfgNode g, Cfg::CfgNode node, boolean branch) {
|
||||
g.(SafeAccessCheck::Range).checks(node, branch)
|
||||
private predicate safeAccessCheck(AstNode g, Expr e, boolean branch) {
|
||||
g.(SafeAccessCheck::Range).checks(e, branch)
|
||||
}
|
||||
|
||||
/** Provides a class for modeling new path safety checks. */
|
||||
module SafeAccessCheck {
|
||||
/** A data-flow node that checks that a path is safe to access in some way, for example by having a controlled prefix. */
|
||||
abstract class Range extends CfgNodes::AstCfgNode {
|
||||
/** Holds if this guard validates `node` upon evaluating to `branch`. */
|
||||
abstract predicate checks(Cfg::CfgNode node, boolean branch);
|
||||
abstract class Range extends AstNode {
|
||||
/** Holds if this guard validates `e` upon evaluating to `branch`. */
|
||||
abstract predicate checks(Expr e, boolean branch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ private import codeql.dataflow.DataFlow
|
||||
private import internal.DataFlowImpl as DataFlowImpl
|
||||
private import internal.Node as Node
|
||||
private import internal.Content as Content
|
||||
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
|
||||
private import codeql.rust.controlflow.CfgNodes as CfgNodes
|
||||
|
||||
/**
|
||||
* Provides classes for performing local (intra-procedural) and global
|
||||
@@ -68,7 +66,7 @@ module DataFlow {
|
||||
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
|
||||
* the argument `x`.
|
||||
*/
|
||||
signature predicate guardChecksSig(CfgNodes::AstCfgNode g, Cfg::CfgNode e, boolean branch);
|
||||
signature predicate guardChecksSig(AstNode g, Expr e, boolean branch);
|
||||
|
||||
/**
|
||||
* Provides a set of barrier nodes for a guard that validates an expression.
|
||||
|
||||
@@ -9,7 +9,6 @@ module Ssa {
|
||||
private import rust
|
||||
private import codeql.rust.controlflow.BasicBlocks
|
||||
private import codeql.rust.controlflow.ControlFlowGraph
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as CfgImpl
|
||||
private import internal.SsaImpl as SsaImpl
|
||||
|
||||
@@ -51,7 +50,7 @@ module Ssa {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
final CfgNode getARead() { result = SsaImpl::getARead(this) }
|
||||
final Expr getARead() { result = SsaImpl::getARead(this) }
|
||||
|
||||
/**
|
||||
* Gets a first control flow node that reads the value of this SSA definition.
|
||||
@@ -80,7 +79,7 @@ module Ssa {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
final CfgNode getAFirstRead() { SsaImpl::firstRead(this, result) }
|
||||
final Expr getAFirstRead() { SsaImpl::firstRead(this, result) }
|
||||
|
||||
/**
|
||||
* Holds if `read1` and `read2` are adjacent reads of this SSA definition.
|
||||
@@ -108,7 +107,7 @@ module Ssa {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
final predicate hasAdjacentReads(CfgNode read1, CfgNode read2) {
|
||||
final predicate hasAdjacentReads(Expr read1, Expr read2) {
|
||||
SsaImpl::adjacentReadPair(this, read1, read2)
|
||||
}
|
||||
|
||||
@@ -168,28 +167,28 @@ module Ssa {
|
||||
* ```
|
||||
*/
|
||||
class WriteDefinition extends Definition, SsaImpl::WriteDefinition {
|
||||
private CfgNode write;
|
||||
private AstNode write;
|
||||
|
||||
WriteDefinition() {
|
||||
exists(BasicBlock bb, int i, Variable v, CfgNode n |
|
||||
exists(BasicBlock bb, int i, Variable v, AstNode n |
|
||||
this.definesAt(v, bb, i) and
|
||||
SsaImpl::variableWriteActual(bb, i, v, n)
|
||||
SsaImpl::variableWriteActual(bb, i, v, n.getACfgNode())
|
||||
|
|
||||
write.(VariableAccessCfgNode).getAccess().getVariable() = v and
|
||||
write.(VariableAccess).getVariable() = v and
|
||||
(
|
||||
write = n.(AssignmentExprCfgNode).getAWriteAccess()
|
||||
write = n.(AssignmentExpr).getAWriteAccess()
|
||||
or
|
||||
write = n.(CompoundAssignmentExprCfgNode).getLhs()
|
||||
write = n.(CompoundAssignmentExpr).getLhs()
|
||||
)
|
||||
or
|
||||
not n instanceof AssignmentExprCfgNode and
|
||||
not n instanceof CompoundAssignmentExprCfgNode and
|
||||
not n instanceof AssignmentExpr and
|
||||
not n instanceof CompoundAssignmentExpr and
|
||||
write = n
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the underlying write access. */
|
||||
final CfgNode getWriteAccess() { result = write }
|
||||
final AstNode getWriteAccess() { result = write }
|
||||
|
||||
/**
|
||||
* Holds if this SSA definition assigns `value` to the underlying
|
||||
@@ -199,19 +198,19 @@ module Ssa {
|
||||
* `let` statement, `let x = value`. Note that patterns on the lhs. are
|
||||
* currently not supported.
|
||||
*/
|
||||
predicate assigns(ExprCfgNode value) {
|
||||
exists(AssignmentExprCfgNode ae |
|
||||
predicate assigns(Expr value) {
|
||||
exists(AssignmentExpr ae |
|
||||
ae.getLhs() = write and
|
||||
ae.getRhs() = value
|
||||
)
|
||||
or
|
||||
exists(IdentPatCfgNode pat | pat.getName() = write |
|
||||
exists(LetStmtCfgNode ls |
|
||||
exists(IdentPat pat | pat.getName() = write |
|
||||
exists(LetStmt ls |
|
||||
pat = ls.getPat() and
|
||||
ls.getInitializer() = value
|
||||
)
|
||||
or
|
||||
exists(LetExprCfgNode le |
|
||||
exists(LetExpr le |
|
||||
pat = le.getPat() and
|
||||
le.getScrutinee() = value
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.frameworks.stdlib.Builtins
|
||||
private import DataFlowImpl
|
||||
|
||||
/**
|
||||
@@ -21,14 +21,18 @@ abstract class Content extends TContent {
|
||||
abstract class FieldContent extends Content {
|
||||
/** Gets an access to this field. */
|
||||
pragma[nomagic]
|
||||
abstract FieldExprCfgNode getAnAccess();
|
||||
abstract FieldExpr getAnAccess();
|
||||
}
|
||||
|
||||
/** A tuple field belonging to either a variant or a struct. */
|
||||
class TupleFieldContent extends FieldContent, TTupleFieldContent {
|
||||
private TupleField field;
|
||||
|
||||
TupleFieldContent() { this = TTupleFieldContent(field) }
|
||||
TupleFieldContent() {
|
||||
this = TTupleFieldContent(field) and
|
||||
// tuples are handled using the special `TupleContent` type
|
||||
not field = any(TupleType tt).getATupleField()
|
||||
}
|
||||
|
||||
/** Holds if this field belongs to an enum variant. */
|
||||
predicate isVariantField(Variant v, int pos) { field.isVariantField(v, pos) }
|
||||
@@ -36,7 +40,7 @@ class TupleFieldContent extends FieldContent, TTupleFieldContent {
|
||||
/** Holds if this field belongs to a struct. */
|
||||
predicate isStructField(Struct s, int pos) { field.isStructField(s, pos) }
|
||||
|
||||
override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getTupleField() }
|
||||
override FieldExpr getAnAccess() { field = result.getTupleField() }
|
||||
|
||||
final override string toString() {
|
||||
exists(Variant v, int pos, string vname |
|
||||
@@ -69,7 +73,7 @@ class StructFieldContent extends FieldContent, TStructFieldContent {
|
||||
/** Holds if this field belongs to a struct. */
|
||||
predicate isStructField(Struct s, string name) { field.isStructField(s, name) }
|
||||
|
||||
override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getStructField() }
|
||||
override FieldExpr getAnAccess() { field = result.getStructField() }
|
||||
|
||||
final override string toString() {
|
||||
exists(Variant v, string name, string vname |
|
||||
@@ -148,7 +152,7 @@ final class TuplePositionContent extends FieldContent, TTuplePositionContent {
|
||||
/** Gets the index of this tuple position. */
|
||||
int getPosition() { result = pos }
|
||||
|
||||
override FieldExprCfgNode getAnAccess() {
|
||||
override FieldExpr getAnAccess() {
|
||||
// TODO: limit to tuple types
|
||||
result.getIdentifier().getText().toInt() = pos
|
||||
}
|
||||
|
||||
@@ -29,17 +29,6 @@ private module Input implements InputSig<Location, RustDataFlow> {
|
||||
}
|
||||
|
||||
predicate missingLocationExclude(RustDataFlow::Node n) { not exists(n.asExpr().getLocation()) }
|
||||
|
||||
predicate multipleArgumentCallExclude(Node::ArgumentNode arg, DataFlowCall call) {
|
||||
// An argument such as `x` in `if !x { ... }` has two successors (and hence
|
||||
// two calls); one for each Boolean outcome of `x`.
|
||||
exists(CfgNodes::ExprCfgNode n |
|
||||
arg.isArgumentOf(call, _) and
|
||||
n = call.asCallCfgNode() and
|
||||
arg.asExpr().getASuccessor(any(ConditionalSuccessor c)).getASuccessor*() = n and
|
||||
n.getASplit() instanceof ConditionalCompletionSplitting::ConditionalCompletionSplit
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeConsistency<Location, RustDataFlow, RustTaintTracking, Input>
|
||||
|
||||
@@ -14,7 +14,6 @@ private import codeql.rust.controlflow.internal.Scope as Scope
|
||||
private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
private import codeql.rust.controlflow.ControlFlowGraph
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.dataflow.Ssa
|
||||
private import codeql.rust.dataflow.FlowSummary
|
||||
private import Node
|
||||
@@ -60,7 +59,7 @@ final class DataFlowCallable extends TDataFlowCallable {
|
||||
|
||||
final class DataFlowCall extends TDataFlowCall {
|
||||
/** Gets the underlying call in the CFG, if any. */
|
||||
CallCfgNode asCallCfgNode() { this = TCall(result) }
|
||||
Call asCall() { this = TCall(result) }
|
||||
|
||||
predicate isSummaryCall(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
@@ -69,13 +68,13 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
}
|
||||
|
||||
DataFlowCallable getEnclosingCallable() {
|
||||
result.asCfgScope() = this.asCallCfgNode().getExpr().getEnclosingCfgScope()
|
||||
result.asCfgScope() = this.asCall().getEnclosingCfgScope()
|
||||
or
|
||||
this.isSummaryCall(result.asSummarizedCallable(), _)
|
||||
}
|
||||
|
||||
string toString() {
|
||||
result = this.asCallCfgNode().toString()
|
||||
result = this.asCall().toString()
|
||||
or
|
||||
exists(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
@@ -85,7 +84,7 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
)
|
||||
}
|
||||
|
||||
Location getLocation() { result = this.asCallCfgNode().getLocation() }
|
||||
Location getLocation() { result = this.asCall().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,13 +145,13 @@ final class ArgumentPosition extends ParameterPosition {
|
||||
* Note that this does not hold for the receiever expression of a method call
|
||||
* as the synthetic `ReceiverNode` is the argument for the `self` parameter.
|
||||
*/
|
||||
predicate isArgumentForCall(ExprCfgNode arg, CallCfgNode call, ParameterPosition pos) {
|
||||
predicate isArgumentForCall(Expr arg, Call call, ParameterPosition pos) {
|
||||
// TODO: Handle index expressions as calls in data flow.
|
||||
not call.getCall() instanceof IndexExpr and
|
||||
not call instanceof IndexExpr and
|
||||
(
|
||||
call.getPositionalArgument(pos.getPosition()) = arg
|
||||
or
|
||||
call.getReceiver() = arg and pos.isSelf() and not call.getCall().receiverImplicitlyBorrowed()
|
||||
call.getReceiver() = arg and pos.isSelf() and not call.receiverImplicitlyBorrowed()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -181,19 +180,24 @@ module SsaFlow {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that may execute last in `n`, and which, when it executes last,
|
||||
* will be the value of `n`.
|
||||
* Gets a node that may execute last in `e`, and which, when it executes last,
|
||||
* will be the value of `e`.
|
||||
*/
|
||||
private ExprCfgNode getALastEvalNode(ExprCfgNode e) {
|
||||
e = any(IfExprCfgNode n | result = [n.getThen(), n.getElse()]) or
|
||||
result = e.(LoopExprCfgNode).getLoopBody() or
|
||||
result = e.(ReturnExprCfgNode).getExpr() or
|
||||
result = e.(BreakExprCfgNode).getExpr() or
|
||||
result = e.(BlockExprCfgNode).getTailExpr() or
|
||||
result = e.(MacroBlockExprCfgNode).getTailExpr() or
|
||||
result = e.(MatchExprCfgNode).getArmExpr(_) or
|
||||
result = e.(MacroExprCfgNode).getMacroCall().(MacroCallCfgNode).getExpandedNode() or
|
||||
result.(BreakExprCfgNode).getTarget() = e
|
||||
private Expr getALastEvalNode(Expr e) {
|
||||
e = any(IfExpr n | result = [n.getThen(), n.getElse()]) or
|
||||
result = e.(LoopExpr).getLoopBody() or
|
||||
result = e.(ReturnExpr).getExpr() or
|
||||
result = e.(BreakExpr).getExpr() or
|
||||
e =
|
||||
any(BlockExpr be |
|
||||
not be.isAsync() and
|
||||
result = be.getTailExpr()
|
||||
) or
|
||||
result = e.(MacroBlockExpr).getTailExpr() or
|
||||
result = e.(MatchExpr).getAnArm().getExpr() or
|
||||
result = e.(MacroExpr).getMacroCall().getMacroCallExpansion() or
|
||||
result.(BreakExpr).getTarget() = e or
|
||||
result = e.(ParenExpr).getExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,11 +215,11 @@ private ExprCfgNode getALastEvalNode(ExprCfgNode e) {
|
||||
* we add a reverse flow step from `[post] { foo(); &mut a}` to `[post] &mut a`,
|
||||
* in order for the side-effect of `set_data` to reach `&mut a`.
|
||||
*/
|
||||
ExprCfgNode getPostUpdateReverseStep(ExprCfgNode e, boolean preservesValue) {
|
||||
Expr getPostUpdateReverseStep(Expr e, boolean preservesValue) {
|
||||
result = getALastEvalNode(e) and
|
||||
preservesValue = true
|
||||
or
|
||||
result = e.(CastExprCfgNode).getExpr() and
|
||||
result = e.(CastExpr).getExpr() and
|
||||
preservesValue = false
|
||||
}
|
||||
|
||||
@@ -236,48 +240,48 @@ module LocalFlow {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
|
||||
nodeFrom.getCfgNode() = getALastEvalNode(nodeTo.getCfgNode())
|
||||
nodeFrom.asExpr() = getALastEvalNode(nodeTo.asExpr())
|
||||
or
|
||||
// An edge from the right-hand side of a let statement to the left-hand side.
|
||||
exists(LetStmtCfgNode s |
|
||||
nodeFrom.getCfgNode() = s.getInitializer() and
|
||||
nodeTo.getCfgNode() = s.getPat()
|
||||
exists(LetStmt s |
|
||||
nodeFrom.asExpr() = s.getInitializer() and
|
||||
nodeTo.asPat() = s.getPat()
|
||||
)
|
||||
or
|
||||
// An edge from the right-hand side of a let expression to the left-hand side.
|
||||
exists(LetExprCfgNode e |
|
||||
nodeFrom.getCfgNode() = e.getScrutinee() and
|
||||
nodeTo.getCfgNode() = e.getPat()
|
||||
exists(LetExpr e |
|
||||
nodeFrom.asExpr() = e.getScrutinee() and
|
||||
nodeTo.asPat() = e.getPat()
|
||||
)
|
||||
or
|
||||
exists(IdentPatCfgNode p |
|
||||
exists(IdentPat p |
|
||||
not p.isRef() and
|
||||
nodeFrom.getCfgNode() = p and
|
||||
nodeTo.getCfgNode() = p.getName()
|
||||
nodeFrom.asPat() = p and
|
||||
nodeTo.(NameNode).getName() = p.getName()
|
||||
)
|
||||
or
|
||||
exists(SelfParamCfgNode self |
|
||||
nodeFrom.getCfgNode() = self and
|
||||
nodeTo.getCfgNode() = self.getName()
|
||||
exists(SelfParam self |
|
||||
nodeFrom.asParameter() = self and
|
||||
nodeTo.(NameNode).getName() = self.getName()
|
||||
)
|
||||
or
|
||||
// An edge from a pattern/expression to its corresponding SSA definition.
|
||||
nodeFrom.(AstCfgFlowNode).getCfgNode() =
|
||||
nodeFrom.(AstNodeNode).getAstNode() =
|
||||
nodeTo.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess()
|
||||
or
|
||||
nodeFrom.(SourceParameterNode).getParameter().(ParamCfgNode).getPat() = nodeTo.asPat()
|
||||
nodeFrom.(SourceParameterNode).getParameter().(Param).getPat() = nodeTo.asPat()
|
||||
or
|
||||
exists(AssignmentExprCfgNode a |
|
||||
a.getRhs() = nodeFrom.getCfgNode() and
|
||||
a.getLhs() = nodeTo.getCfgNode()
|
||||
exists(AssignmentExpr a |
|
||||
a.getRhs() = nodeFrom.asExpr() and
|
||||
a.getLhs() = nodeTo.asExpr()
|
||||
)
|
||||
or
|
||||
exists(MatchExprCfgNode match |
|
||||
exists(MatchExpr match |
|
||||
nodeFrom.asExpr() = match.getScrutinee() and
|
||||
nodeTo.asPat() = match.getArmPat(_)
|
||||
nodeTo.asPat() = match.getAnArm().getPat()
|
||||
)
|
||||
or
|
||||
nodeFrom.asPat().(OrPatCfgNode).getAPat() = nodeTo.asPat()
|
||||
nodeFrom.asPat().(OrPat).getAPat() = nodeTo.asPat()
|
||||
or
|
||||
// Simple value step from receiver expression to receiver node, in case
|
||||
// there is no implicit deref or borrow operation.
|
||||
@@ -305,12 +309,10 @@ predicate lambdaCreationExpr(Expr creation) {
|
||||
* Holds if `call` is a lambda call of kind `kind` where `receiver` is the
|
||||
* invoked expression.
|
||||
*/
|
||||
predicate lambdaCallExpr(CallExprCfgNode call, LambdaCallKind kind, ExprCfgNode receiver) {
|
||||
predicate lambdaCallExpr(CallExpr call, LambdaCallKind kind, Expr receiver) {
|
||||
receiver = call.getFunction() and
|
||||
// All calls to complex expressions and local variable accesses are lambda call.
|
||||
exists(Expr f | f = receiver.getExpr() |
|
||||
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
|
||||
) and
|
||||
(receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess()) and
|
||||
exists(kind)
|
||||
}
|
||||
|
||||
@@ -379,19 +381,27 @@ module RustDataFlow implements InputSig<Location> {
|
||||
node instanceof CaptureNode or
|
||||
node instanceof ClosureParameterNode or
|
||||
node instanceof ReceiverNode or
|
||||
node instanceof ReceiverPostUpdateNode
|
||||
node.asExpr() instanceof ParenExpr or
|
||||
nodeIsHidden(node.(PostUpdateNode).getPreUpdateNode())
|
||||
}
|
||||
|
||||
private Expr stripParens(Expr e) {
|
||||
not e instanceof ParenExpr and
|
||||
result = e
|
||||
or
|
||||
result = stripParens(e.(ParenExpr).getExpr())
|
||||
}
|
||||
|
||||
predicate neverSkipInPathGraph(Node node) {
|
||||
node.(Node::Node).getCfgNode() = any(LetStmtCfgNode s).getPat()
|
||||
node.(Node::Node).asPat() = any(LetStmt s).getPat()
|
||||
or
|
||||
node.(Node::Node).getCfgNode() = any(LetExprCfgNode e).getPat()
|
||||
node.(Node::Node).asPat() = any(LetExpr e).getPat()
|
||||
or
|
||||
node.(Node::Node).getCfgNode() = any(AssignmentExprCfgNode a).getLhs()
|
||||
node.(Node::Node).asExpr() = stripParens(any(AssignmentExpr a).getLhs())
|
||||
or
|
||||
exists(MatchExprCfgNode match |
|
||||
node.asExpr() = match.getScrutinee() or
|
||||
node.asExpr() = match.getArmPat(_)
|
||||
exists(MatchExpr match |
|
||||
node.asExpr() = stripParens(match.getScrutinee()) or
|
||||
node.asPat() = match.getAnArm().getPat()
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::sourceLocalStep(_, node, _)
|
||||
@@ -399,7 +409,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
FlowSummaryImpl::Private::Steps::sinkLocalStep(node, _, _)
|
||||
}
|
||||
|
||||
class DataFlowExpr = ExprCfgNode;
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
/** Gets the node corresponding to `e`. */
|
||||
Node exprNode(DataFlowExpr e) { result.asExpr() = e }
|
||||
@@ -412,7 +422,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
/** Gets a viable implementation of the target of the given `Call`. */
|
||||
DataFlowCallable viableCallable(DataFlowCall call) {
|
||||
exists(Call c | c = call.asCallCfgNode().getCall() |
|
||||
exists(Call c | c = call.asCall() |
|
||||
result.asCfgScope() = c.getARuntimeTarget()
|
||||
or
|
||||
exists(SummarizedCallable sc, Function staticTarget |
|
||||
@@ -511,79 +521,79 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate implicitDerefToReceiver(Node node1, ReceiverNode node2, ReferenceContent c) {
|
||||
TypeInference::receiverHasImplicitDeref(node1.asExpr().getExpr()) and
|
||||
TypeInference::receiverHasImplicitDeref(node1.asExpr()) and
|
||||
node1.asExpr() = node2.getReceiver() and
|
||||
exists(c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate implicitBorrowToReceiver(Node node1, ReceiverNode node2, ReferenceContent c) {
|
||||
TypeInference::receiverHasImplicitBorrow(node1.asExpr().getExpr()) and
|
||||
TypeInference::receiverHasImplicitBorrow(node1.asExpr()) and
|
||||
node1.asExpr() = node2.getReceiver() and
|
||||
exists(c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate referenceExprToExpr(Node node1, Node node2, ReferenceContent c) {
|
||||
node1.asExpr() = node2.asExpr().(RefExprCfgNode).getExpr() and
|
||||
node1.asExpr() = node2.asExpr().(RefExpr).getExpr() and
|
||||
exists(c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate readContentStep(Node node1, Content c, Node node2) {
|
||||
exists(TupleStructPatCfgNode pat, int pos |
|
||||
exists(TupleStructPat pat, int pos |
|
||||
pat = node1.asPat() and
|
||||
node2.asPat() = pat.getField(pos) and
|
||||
c = TTupleFieldContent(pat.getTupleStructPat().getTupleField(pos))
|
||||
c = TTupleFieldContent(pat.getTupleField(pos))
|
||||
)
|
||||
or
|
||||
exists(TuplePatCfgNode pat, int pos |
|
||||
exists(TuplePat pat, int pos |
|
||||
pos = c.(TuplePositionContent).getPosition() and
|
||||
node1.asPat() = pat and
|
||||
node2.asPat() = pat.getField(pos)
|
||||
)
|
||||
or
|
||||
exists(StructPatCfgNode pat, string field |
|
||||
exists(StructPat pat, string field |
|
||||
pat = node1.asPat() and
|
||||
c = TStructFieldContent(pat.getStructPat().getStructField(field)) and
|
||||
node2.asPat() = pat.getFieldPat(field)
|
||||
c = TStructFieldContent(pat.getStructField(field)) and
|
||||
node2.asPat() = pat.getPatField(field).getPat()
|
||||
)
|
||||
or
|
||||
c instanceof ReferenceContent and
|
||||
node1.asPat().(RefPatCfgNode).getPat() = node2.asPat()
|
||||
node1.asPat().(RefPat).getPat() = node2.asPat()
|
||||
or
|
||||
exists(FieldExprCfgNode access |
|
||||
exists(FieldExpr access |
|
||||
node1.asExpr() = access.getContainer() and
|
||||
node2.asExpr() = access and
|
||||
access = c.(FieldContent).getAnAccess()
|
||||
)
|
||||
or
|
||||
exists(IndexExprCfgNode arr |
|
||||
exists(IndexExpr arr |
|
||||
c instanceof ElementContent and
|
||||
node1.asExpr() = arr.getBase() and
|
||||
node2.asExpr() = arr
|
||||
)
|
||||
or
|
||||
exists(ForExprCfgNode for |
|
||||
exists(ForExpr for |
|
||||
c instanceof ElementContent and
|
||||
node1.asExpr() = for.getIterable() and
|
||||
node2.asPat() = for.getPat()
|
||||
)
|
||||
or
|
||||
exists(SlicePatCfgNode pat |
|
||||
exists(SlicePat pat |
|
||||
c instanceof ElementContent and
|
||||
node1.asPat() = pat and
|
||||
node2.asPat() = pat.getAPat()
|
||||
)
|
||||
or
|
||||
exists(TryExprCfgNode try |
|
||||
exists(TryExpr try |
|
||||
node1.asExpr() = try.getExpr() and
|
||||
node2.asExpr() = try and
|
||||
c.(TupleFieldContent)
|
||||
.isVariantField([any(OptionEnum o).getSome(), any(ResultEnum r).getOk()], 0)
|
||||
)
|
||||
or
|
||||
exists(PrefixExprCfgNode deref |
|
||||
exists(PrefixExpr deref |
|
||||
c instanceof ReferenceContent and
|
||||
deref.getOperatorName() = "*" and
|
||||
node1.asExpr() = deref.getExpr() and
|
||||
@@ -597,7 +607,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
c instanceof FunctionCallReturnContent
|
||||
)
|
||||
or
|
||||
exists(AwaitExprCfgNode await |
|
||||
exists(AwaitExpr await |
|
||||
c instanceof FutureContent and
|
||||
node1.asExpr() = await.getExpr() and
|
||||
node2.asExpr() = await
|
||||
@@ -644,7 +654,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fieldAssignment(Node node1, Node node2, FieldContent c) {
|
||||
exists(AssignmentExprCfgNode assignment, FieldExprCfgNode access |
|
||||
exists(AssignmentExpr assignment, FieldExpr access |
|
||||
assignment.getLhs() = access and
|
||||
node1.asExpr() = assignment.getRhs() and
|
||||
node2.asExpr() = access.getContainer() and
|
||||
@@ -654,7 +664,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate referenceAssignment(Node node1, Node node2, ReferenceContent c) {
|
||||
exists(AssignmentExprCfgNode assignment, PrefixExprCfgNode deref |
|
||||
exists(AssignmentExpr assignment, PrefixExpr deref |
|
||||
assignment.getLhs() = deref and
|
||||
deref.getOperatorName() = "*" and
|
||||
node1.asExpr() = assignment.getRhs() and
|
||||
@@ -665,19 +675,19 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate storeContentStep(Node node1, Content c, Node node2) {
|
||||
exists(CallExprCfgNode call, int pos |
|
||||
node1.asExpr() = call.getArgument(pragma[only_bind_into](pos)) and
|
||||
exists(CallExpr call, int pos |
|
||||
node1.asExpr() = call.getArg(pragma[only_bind_into](pos)) and
|
||||
node2.asExpr() = call and
|
||||
c = TTupleFieldContent(call.getCallExpr().getTupleField(pragma[only_bind_into](pos)))
|
||||
c = TTupleFieldContent(call.getTupleField(pragma[only_bind_into](pos)))
|
||||
)
|
||||
or
|
||||
exists(StructExprCfgNode re, string field |
|
||||
c = TStructFieldContent(re.getStructExpr().getStructField(field)) and
|
||||
node1.asExpr() = re.getFieldExpr(field) and
|
||||
exists(StructExpr re, string field |
|
||||
c = TStructFieldContent(re.getStructField(field)) and
|
||||
node1.asExpr() = re.getFieldExpr(field).getExpr() and
|
||||
node2.asExpr() = re
|
||||
)
|
||||
or
|
||||
exists(TupleExprCfgNode tuple |
|
||||
exists(TupleExpr tuple |
|
||||
node1.asExpr() = tuple.getField(c.(TuplePositionContent).getPosition()) and
|
||||
node2.asExpr() = tuple
|
||||
)
|
||||
@@ -685,23 +695,23 @@ module RustDataFlow implements InputSig<Location> {
|
||||
c instanceof ElementContent and
|
||||
node1.asExpr() =
|
||||
[
|
||||
node2.asExpr().(ArrayRepeatExprCfgNode).getRepeatOperand(),
|
||||
node2.asExpr().(ArrayListExprCfgNode).getAnExpr()
|
||||
node2.asExpr().(ArrayRepeatExpr).getRepeatOperand(),
|
||||
node2.asExpr().(ArrayListExpr).getAnExpr()
|
||||
]
|
||||
or
|
||||
// Store from a `ref` identifier pattern into the contained name.
|
||||
exists(IdentPatCfgNode p |
|
||||
exists(IdentPat p |
|
||||
c instanceof ReferenceContent and
|
||||
p.isRef() and
|
||||
node1.asPat() = p and
|
||||
node2.(NameNode).asName() = p.getName()
|
||||
node2.(NameNode).getName() = p.getName()
|
||||
)
|
||||
or
|
||||
fieldAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
|
||||
or
|
||||
referenceAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
|
||||
or
|
||||
exists(AssignmentExprCfgNode assignment, IndexExprCfgNode index |
|
||||
exists(AssignmentExpr assignment, IndexExpr index |
|
||||
c instanceof ElementContent and
|
||||
assignment.getLhs() = index and
|
||||
node1.asExpr() = assignment.getRhs() and
|
||||
@@ -808,7 +818,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
|
||||
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
|
||||
exists(kind) and
|
||||
exists(Expr e | e = creation.asExpr().getExpr() |
|
||||
exists(Expr e | e = creation.asExpr() |
|
||||
lambdaCreationExpr(e) and e = c.asCfgScope()
|
||||
or
|
||||
// A path expression, that resolves to a function, evaluates to a function
|
||||
@@ -825,9 +835,9 @@ module RustDataFlow implements InputSig<Location> {
|
||||
*/
|
||||
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
(
|
||||
receiver.asExpr() = call.asCallCfgNode().(CallExprCfgNode).getFunction() and
|
||||
receiver.asExpr() = call.asCall().(CallExpr).getFunction() and
|
||||
// All calls to complex expressions and local variable accesses are lambda call.
|
||||
exists(Expr f | f = receiver.asExpr().getExpr() |
|
||||
exists(Expr f | f = receiver.asExpr() |
|
||||
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
|
||||
)
|
||||
or
|
||||
@@ -854,7 +864,7 @@ module VariableCapture {
|
||||
private import codeql.dataflow.VariableCapture as SharedVariableCapture
|
||||
private import codeql.rust.controlflow.BasicBlocks as BasicBlocks
|
||||
|
||||
private predicate closureFlowStep(ExprCfgNode e1, ExprCfgNode e2) {
|
||||
private predicate closureFlowStep(Expr e1, Expr e2) {
|
||||
Stages::DataFlowStage::ref() and
|
||||
e1 = getALastEvalNode(e2)
|
||||
or
|
||||
@@ -883,48 +893,48 @@ module VariableCapture {
|
||||
|
||||
CapturedParameter() { p = this.getParameter() }
|
||||
|
||||
SourceParameterNode getParameterNode() { result.getParameter().getParamBase() = p }
|
||||
SourceParameterNode getParameterNode() { result.getParameter() = p }
|
||||
}
|
||||
|
||||
class Expr extends CfgNode {
|
||||
predicate hasCfgNode(BasicBlocks::BasicBlock bb, int i) { this = bb.getNode(i) }
|
||||
class Expr extends AstNode {
|
||||
predicate hasCfgNode(BasicBlocks::BasicBlock bb, int i) { this = bb.getNode(i).getAstNode() }
|
||||
}
|
||||
|
||||
class VariableWrite extends Expr {
|
||||
ExprCfgNode source;
|
||||
Expr source;
|
||||
CapturedVariable v;
|
||||
|
||||
VariableWrite() {
|
||||
exists(AssignmentExprCfgNode assign, Variable::VariableWriteAccess write |
|
||||
exists(AssignmentExpr assign, Variable::VariableWriteAccess write |
|
||||
this = assign and
|
||||
v = write.getVariable() and
|
||||
assign.getLhs().getExpr() = write and
|
||||
assign.getLhs() = write and
|
||||
assign.getRhs() = source
|
||||
)
|
||||
or
|
||||
exists(LetStmtCfgNode ls |
|
||||
this = ls and
|
||||
v.getPat() = ls.getPat().getPat() and
|
||||
ls.getInitializer() = source
|
||||
)
|
||||
this =
|
||||
any(LetStmt ls |
|
||||
v.getPat() = ls.getPat() and
|
||||
ls.getInitializer() = source
|
||||
)
|
||||
or
|
||||
exists(LetExprCfgNode le |
|
||||
this = le and
|
||||
v.getPat() = le.getPat().getPat() and
|
||||
le.getScrutinee() = source
|
||||
)
|
||||
this =
|
||||
any(LetExpr le |
|
||||
v.getPat() = le.getPat() and
|
||||
le.getScrutinee() = source
|
||||
)
|
||||
}
|
||||
|
||||
CapturedVariable getVariable() { result = v }
|
||||
|
||||
ExprCfgNode getSource() { result = source }
|
||||
Expr getSource() { result = source }
|
||||
}
|
||||
|
||||
class VariableRead extends Expr instanceof ExprCfgNode {
|
||||
class VariableRead extends Expr {
|
||||
CapturedVariable v;
|
||||
|
||||
VariableRead() {
|
||||
exists(VariableAccess read | this.getExpr() = read and v = read.getVariable() |
|
||||
exists(VariableAccess read | this = read and v = read.getVariable() |
|
||||
read instanceof VariableReadAccess
|
||||
or
|
||||
read = any(RefExpr re).getExpr()
|
||||
@@ -934,10 +944,10 @@ module VariableCapture {
|
||||
CapturedVariable getVariable() { result = v }
|
||||
}
|
||||
|
||||
class ClosureExpr extends Expr instanceof ExprCfgNode {
|
||||
ClosureExpr() { lambdaCreationExpr(super.getExpr()) }
|
||||
class ClosureExpr extends Expr {
|
||||
ClosureExpr() { lambdaCreationExpr(this) }
|
||||
|
||||
predicate hasBody(Callable body) { body = super.getExpr() }
|
||||
predicate hasBody(Callable body) { body = this }
|
||||
|
||||
predicate hasAliasedAccess(Expr f) { closureFlowStep+(this, f) and not closureFlowStep(f, _) }
|
||||
}
|
||||
@@ -991,10 +1001,11 @@ private module Cached {
|
||||
|
||||
cached
|
||||
newtype TDataFlowCall =
|
||||
TCall(CallCfgNode c) {
|
||||
TCall(Call call) {
|
||||
Stages::DataFlowStage::ref() and
|
||||
call.hasEnclosingCfgScope() and
|
||||
// TODO: Handle index expressions as calls in data flow.
|
||||
not c.getCall() instanceof IndexExpr
|
||||
not call instanceof IndexExpr
|
||||
} or
|
||||
TSummaryCall(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
|
||||
@@ -9,7 +9,6 @@ private import codeql.rust.dataflow.internal.DataFlowImpl
|
||||
private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.dataflow.FlowSummary
|
||||
private import codeql.rust.dataflow.Ssa
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import Content
|
||||
|
||||
module Input implements InputSig<Location, RustDataFlow> {
|
||||
@@ -132,9 +131,7 @@ module Input implements InputSig<Location, RustDataFlow> {
|
||||
private import Make<Location, RustDataFlow, Input> as Impl
|
||||
|
||||
private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
DataFlowCall getACall(Public::SummarizedCallable sc) {
|
||||
result.asCallCfgNode().getCall().getStaticTarget() = sc
|
||||
}
|
||||
DataFlowCall getACall(Public::SummarizedCallable sc) { result.asCall().getStaticTarget() = sc }
|
||||
|
||||
/** Gets the argument of `source` described by `sc`, if any. */
|
||||
private Expr getSourceNodeArgument(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
|
||||
@@ -151,10 +148,9 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
result = expr.(ClosureExpr)
|
||||
or
|
||||
// The expression is an SSA read of an assignment of a closure
|
||||
exists(Ssa::Definition def, ExprCfgNode value |
|
||||
def.getARead().getAstNode() = expr and
|
||||
def.getAnUltimateDefinition().(Ssa::WriteDefinition).assigns(value) and
|
||||
result = value.getExpr().(ClosureExpr)
|
||||
exists(Ssa::Definition def |
|
||||
def.getARead() = expr and
|
||||
def.getAnUltimateDefinition().(Ssa::WriteDefinition).assigns(result.(ClosureExpr))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -164,7 +160,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
|
||||
RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) {
|
||||
s.head() = Impl::Private::SummaryComponent::return(_) and
|
||||
result.asExpr().getExpr() = source.getCall()
|
||||
result.asExpr() = source.getCall()
|
||||
or
|
||||
exists(ArgumentPosition pos, Expr arg |
|
||||
s.head() = Impl::Private::SummaryComponent::parameter(pos) and
|
||||
@@ -172,13 +168,13 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
result.asParameter() = getCallable(arg).getParam(pos.getPosition())
|
||||
)
|
||||
or
|
||||
result.(RustDataFlow::PostUpdateNode).getPreUpdateNode().asExpr().getExpr() =
|
||||
result.(RustDataFlow::PostUpdateNode).getPreUpdateNode().asExpr() =
|
||||
getSourceNodeArgument(source, s.headOfSingleton())
|
||||
}
|
||||
|
||||
RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {
|
||||
exists(CallExprBase call, Expr arg, ArgumentPosition pos |
|
||||
result.asExpr().getExpr() = arg and
|
||||
result.asExpr() = arg and
|
||||
sc = Impl::Private::SummaryComponent::argument(pos) and
|
||||
call = sink.getCall() and
|
||||
arg = pos.getArgument(call)
|
||||
|
||||
@@ -35,17 +35,17 @@ class NodePublic extends TNode {
|
||||
/**
|
||||
* Gets the expression that corresponds to this node, if any.
|
||||
*/
|
||||
final ExprCfgNode asExpr() { this = TExprNode(result) }
|
||||
final Expr asExpr() { this = TExprNode(result) }
|
||||
|
||||
/**
|
||||
* Gets the parameter that corresponds to this node, if any.
|
||||
*/
|
||||
ParamBase asParameter() { result = this.(SourceParameterNode).getParameter().getParamBase() }
|
||||
ParamBase asParameter() { result = this.(SourceParameterNode).getParameter() }
|
||||
|
||||
/**
|
||||
* Gets the pattern that corresponds to this node, if any.
|
||||
*/
|
||||
final PatCfgNode asPat() { this = TPatNode(result) }
|
||||
final Pat asPat() { this = TPatNode(result) }
|
||||
}
|
||||
|
||||
abstract class Node extends NodePublic {
|
||||
@@ -56,9 +56,9 @@ abstract class Node extends NodePublic {
|
||||
abstract CfgScope getCfgScope();
|
||||
|
||||
/**
|
||||
* Gets the control flow node that corresponds to this data flow node.
|
||||
* Gets the AST node that corresponds to this data flow node, if any.
|
||||
*/
|
||||
CfgNode getCfgNode() { none() }
|
||||
AstNode getAstNode() { none() }
|
||||
}
|
||||
|
||||
/** A data flow node used to model flow summaries. */
|
||||
@@ -118,17 +118,17 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
|
||||
}
|
||||
}
|
||||
|
||||
/** A data flow node that corresponds directly to a CFG node for an AST node. */
|
||||
abstract class AstCfgFlowNode extends Node {
|
||||
AstCfgNode n;
|
||||
/** A data flow node that corresponds directly to an AST node. */
|
||||
abstract class AstNodeNode extends Node {
|
||||
AstNode n;
|
||||
|
||||
final override CfgNode getCfgNode() { result = n }
|
||||
final override AstNode getAstNode() { result = n }
|
||||
|
||||
final override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() }
|
||||
final override CfgScope getCfgScope() { result = n.getEnclosingCfgScope() }
|
||||
|
||||
final override Location getLocation() { result = n.getAstNode().getLocation() }
|
||||
final override Location getLocation() { result = n.getLocation() }
|
||||
|
||||
final override string toString() { result = n.getAstNode().toString() }
|
||||
final override string toString() { result = n.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,25 +139,25 @@ abstract class AstCfgFlowNode extends Node {
|
||||
* to multiple `ExprNode`s, just like it may correspond to multiple
|
||||
* `ControlFlow::Node`s.
|
||||
*/
|
||||
class ExprNode extends AstCfgFlowNode, TExprNode {
|
||||
override ExprCfgNode n;
|
||||
class ExprNode extends AstNodeNode, TExprNode {
|
||||
override Expr n;
|
||||
|
||||
ExprNode() { this = TExprNode(n) }
|
||||
}
|
||||
|
||||
final class PatNode extends AstCfgFlowNode, TPatNode {
|
||||
override PatCfgNode n;
|
||||
final class PatNode extends AstNodeNode, TPatNode {
|
||||
override Pat n;
|
||||
|
||||
PatNode() { this = TPatNode(n) }
|
||||
}
|
||||
|
||||
/** A data flow node that corresponds to a name node in the CFG. */
|
||||
final class NameNode extends AstCfgFlowNode, TNameNode {
|
||||
override NameCfgNode n;
|
||||
final class NameNode extends AstNodeNode, TNameNode {
|
||||
override Name n;
|
||||
|
||||
NameNode() { this = TNameNode(n) }
|
||||
|
||||
NameCfgNode asName() { result = n }
|
||||
Name getName() { result = n }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,20 +169,20 @@ abstract class ParameterNode extends Node {
|
||||
abstract predicate isParameterOf(DataFlowCallable c, ParameterPosition pos);
|
||||
}
|
||||
|
||||
final class SourceParameterNode extends AstCfgFlowNode, ParameterNode, TSourceParameterNode {
|
||||
override ParamBaseCfgNode n;
|
||||
final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParameterNode {
|
||||
override ParamBase n;
|
||||
|
||||
SourceParameterNode() { this = TSourceParameterNode(n) }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
n.getAstNode() = pos.getParameterIn(c.asCfgScope().(Callable).getParamList())
|
||||
n = pos.getParameterIn(c.asCfgScope().(Callable).getParamList())
|
||||
}
|
||||
|
||||
/** Get the parameter position of this parameter. */
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
/** Gets the parameter in the CFG that this node corresponds to. */
|
||||
ParamBaseCfgNode getParameter() { result = n }
|
||||
ParamBase getParameter() { result = n }
|
||||
}
|
||||
|
||||
/** A parameter for a library callable with a flow summary. */
|
||||
@@ -223,13 +223,13 @@ abstract class ArgumentNode extends Node {
|
||||
}
|
||||
|
||||
final class ExprArgumentNode extends ArgumentNode, ExprNode {
|
||||
private CallCfgNode call_;
|
||||
private Call call_;
|
||||
private RustDataFlow::ArgumentPosition pos_;
|
||||
|
||||
ExprArgumentNode() { isArgumentForCall(n, call_, pos_) }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call.asCallCfgNode() = call_ and pos = pos_
|
||||
call.asCall() = call_ and pos = pos_
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,19 +238,19 @@ final class ExprArgumentNode extends ArgumentNode, ExprNode {
|
||||
* has taken place.
|
||||
*/
|
||||
final class ReceiverNode extends ArgumentNode, TReceiverNode {
|
||||
private CallCfgNode n;
|
||||
private Call n;
|
||||
|
||||
ReceiverNode() { this = TReceiverNode(n, false) }
|
||||
|
||||
ExprCfgNode getReceiver() { result = n.getReceiver() }
|
||||
Expr getReceiver() { result = n.getReceiver() }
|
||||
|
||||
MethodCallExprCfgNode getMethodCall() { result = n }
|
||||
MethodCallExpr getMethodCall() { result = n }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call.asCallCfgNode() = n and pos = TSelfParameterPosition()
|
||||
call.asCall() = n and pos = TSelfParameterPosition()
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() }
|
||||
override CfgScope getCfgScope() { result = n.getEnclosingCfgScope() }
|
||||
|
||||
override Location getLocation() { result = this.getReceiver().getLocation() }
|
||||
|
||||
@@ -275,12 +275,12 @@ final class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
|
||||
* passed into the closure body at an invocation.
|
||||
*/
|
||||
final class ClosureArgumentNode extends ArgumentNode, ExprNode {
|
||||
private CallExprCfgNode call_;
|
||||
private CallExpr call_;
|
||||
|
||||
ClosureArgumentNode() { lambdaCallExpr(call_, _, this.asExpr()) }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call.asCallCfgNode() = call_ and
|
||||
call.asCall() = call_ and
|
||||
pos.isClosureSelf()
|
||||
}
|
||||
}
|
||||
@@ -309,7 +309,7 @@ abstract class ReturnNode extends Node {
|
||||
}
|
||||
|
||||
final class ExprReturnNode extends ExprNode, ReturnNode {
|
||||
ExprReturnNode() { this.getCfgNode().getASuccessor() instanceof AnnotatedExitCfgNode }
|
||||
ExprReturnNode() { n.getACfgNode().getASuccessor() instanceof AnnotatedExitCfgNode }
|
||||
|
||||
override ReturnKind getKind() { result = TNormalReturnKind() }
|
||||
}
|
||||
@@ -329,11 +329,11 @@ abstract class OutNode extends Node {
|
||||
}
|
||||
|
||||
final private class ExprOutNode extends ExprNode, OutNode {
|
||||
ExprOutNode() { this.asExpr() instanceof CallCfgNode }
|
||||
ExprOutNode() { this.asExpr() instanceof Call }
|
||||
|
||||
/** Gets the underlying call CFG node that includes this out node. */
|
||||
override DataFlowCall getCall(ReturnKind kind) {
|
||||
result.asCallCfgNode() = this.getCfgNode() and
|
||||
result.asCall() = n and
|
||||
kind = TNormalReturnKind()
|
||||
}
|
||||
}
|
||||
@@ -391,27 +391,27 @@ abstract class PostUpdateNode extends PostUpdateNodePublic, Node {
|
||||
}
|
||||
|
||||
final class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
|
||||
private ExprCfgNode n;
|
||||
private Expr e;
|
||||
|
||||
ExprPostUpdateNode() { this = TExprPostUpdateNode(n) }
|
||||
ExprPostUpdateNode() { this = TExprPostUpdateNode(e) }
|
||||
|
||||
override Node getPreUpdateNode() { result = TExprNode(n) }
|
||||
override Node getPreUpdateNode() { result = TExprNode(e) }
|
||||
|
||||
override CfgScope getCfgScope() { result = n.getScope() }
|
||||
override CfgScope getCfgScope() { result = e.getEnclosingCfgScope() }
|
||||
|
||||
override Location getLocation() { result = n.getLocation() }
|
||||
override Location getLocation() { result = e.getLocation() }
|
||||
}
|
||||
|
||||
final class ReceiverPostUpdateNode extends PostUpdateNode, TReceiverNode {
|
||||
private CallCfgNode n;
|
||||
private Call call;
|
||||
|
||||
ReceiverPostUpdateNode() { this = TReceiverNode(n, true) }
|
||||
ReceiverPostUpdateNode() { this = TReceiverNode(call, true) }
|
||||
|
||||
override Node getPreUpdateNode() { result = TReceiverNode(n, false) }
|
||||
override Node getPreUpdateNode() { result = TReceiverNode(call, false) }
|
||||
|
||||
override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() }
|
||||
override CfgScope getCfgScope() { result = call.getEnclosingCfgScope() }
|
||||
|
||||
override Location getLocation() { result = n.getReceiver().getLocation() }
|
||||
override Location getLocation() { result = call.getReceiver().getLocation() }
|
||||
}
|
||||
|
||||
final class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode {
|
||||
@@ -445,38 +445,46 @@ final class CastNode extends ExprNode {
|
||||
|
||||
cached
|
||||
newtype TNode =
|
||||
TExprNode(ExprCfgNode n) { Stages::DataFlowStage::ref() } or
|
||||
TSourceParameterNode(ParamBaseCfgNode p) or
|
||||
TPatNode(PatCfgNode p) or
|
||||
TNameNode(NameCfgNode n) { n.getName() = any(Variable v).getName() } or
|
||||
TExprPostUpdateNode(ExprCfgNode e) {
|
||||
isArgumentForCall(e, _, _)
|
||||
or
|
||||
lambdaCallExpr(_, _, e)
|
||||
or
|
||||
lambdaCreationExpr(e.getExpr())
|
||||
or
|
||||
// Whenever `&mut e` has a post-update node we also create one for `e`.
|
||||
// E.g., for `e` in `f(..., &mut e, ...)` or `*(&mut e) = ...`.
|
||||
e = any(RefExprCfgNode ref | ref.isMut() and exists(TExprPostUpdateNode(ref))).getExpr()
|
||||
or
|
||||
e =
|
||||
[
|
||||
any(IndexExprCfgNode i).getBase(), //
|
||||
any(FieldExprCfgNode access).getContainer(), //
|
||||
any(TryExprCfgNode try).getExpr(), //
|
||||
any(PrefixExprCfgNode pe | pe.getOperatorName() = "*").getExpr(), //
|
||||
any(AwaitExprCfgNode a).getExpr(), //
|
||||
any(MethodCallExprCfgNode mc).getReceiver(), //
|
||||
getPostUpdateReverseStep(any(PostUpdateNode n).getPreUpdateNode().asExpr(), _)
|
||||
]
|
||||
TExprNode(Expr e) { e.hasEnclosingCfgScope() and Stages::DataFlowStage::ref() } or
|
||||
TSourceParameterNode(ParamBase p) { p.hasEnclosingCfgScope() } or
|
||||
TPatNode(Pat p) { p.hasEnclosingCfgScope() } or
|
||||
TNameNode(Name n) { n = any(Variable v).getName() and n.hasEnclosingCfgScope() } or
|
||||
TExprPostUpdateNode(Expr e) {
|
||||
e.hasEnclosingCfgScope() and
|
||||
(
|
||||
isArgumentForCall(e, _, _)
|
||||
or
|
||||
lambdaCallExpr(_, _, e)
|
||||
or
|
||||
lambdaCreationExpr(e)
|
||||
or
|
||||
// Whenever `&mut e` has a post-update node we also create one for `e`.
|
||||
// E.g., for `e` in `f(..., &mut e, ...)` or `*(&mut e) = ...`.
|
||||
e = any(RefExpr ref | ref.isMut() and exists(TExprPostUpdateNode(ref))).getExpr()
|
||||
or
|
||||
e =
|
||||
[
|
||||
any(IndexExpr i).getBase(), //
|
||||
any(FieldExpr access).getContainer(), //
|
||||
any(TryExpr try).getExpr(), //
|
||||
any(PrefixExpr pe | pe.getOperatorName() = "*").getExpr(), //
|
||||
any(AwaitExpr a).getExpr(), //
|
||||
any(MethodCallExpr mc).getReceiver(), //
|
||||
getPostUpdateReverseStep(any(PostUpdateNode n).getPreUpdateNode().asExpr(), _)
|
||||
]
|
||||
)
|
||||
} or
|
||||
TReceiverNode(CallCfgNode mc, Boolean isPost) {
|
||||
mc.getCall().receiverImplicitlyBorrowed() and
|
||||
TReceiverNode(Call call, Boolean isPost) {
|
||||
call.hasEnclosingCfgScope() and
|
||||
call.receiverImplicitlyBorrowed() and
|
||||
// TODO: Handle index expressions as calls in data flow.
|
||||
not mc.getCall() instanceof IndexExpr
|
||||
not call instanceof IndexExpr
|
||||
} or
|
||||
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
|
||||
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
|
||||
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) {
|
||||
forall(AstNode n | n = sn.getSinkElement() or n = sn.getSourceElement() |
|
||||
n.hasEnclosingCfgScope()
|
||||
)
|
||||
} or
|
||||
TClosureSelfReferenceNode(CfgScope c) { lambdaCreationExpr(c) } or
|
||||
TCaptureNode(VariableCapture::Flow::SynthesizedCaptureNode cn)
|
||||
|
||||
@@ -2,7 +2,6 @@ private import rust
|
||||
private import codeql.rust.controlflow.BasicBlocks as BasicBlocks
|
||||
private import BasicBlocks
|
||||
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
|
||||
private import codeql.rust.controlflow.CfgNodes as CfgNodes
|
||||
private import Cfg
|
||||
private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as ControlFlowGraphImpl
|
||||
private import codeql.ssa.Ssa as SsaImplCommon
|
||||
@@ -229,11 +228,11 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
CfgNode getARead(Definition def) {
|
||||
Expr getARead(Definition def) {
|
||||
exists(Variable v, BasicBlock bb, int i |
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
variableReadCertain(bb, i, v.getAnAccess(), v) and
|
||||
result = bb.getNode(i)
|
||||
result = bb.getNode(i).getAstNode()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -247,8 +246,10 @@ private module Cached {
|
||||
* without passing through any other non-pseudo read.
|
||||
*/
|
||||
cached
|
||||
predicate firstRead(Definition def, CfgNode read) {
|
||||
exists(BasicBlock bb, int i | Impl::firstUse(def, bb, i, true) and read = bb.getNode(i))
|
||||
predicate firstRead(Definition def, Expr read) {
|
||||
exists(BasicBlock bb, int i |
|
||||
Impl::firstUse(def, bb, i, true) and read = bb.getNode(i).getAstNode()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,12 +258,12 @@ private module Cached {
|
||||
* passing through another non-pseudo read.
|
||||
*/
|
||||
cached
|
||||
predicate adjacentReadPair(Definition def, CfgNode read1, CfgNode read2) {
|
||||
predicate adjacentReadPair(Definition def, Expr read1, Expr read2) {
|
||||
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2, Variable v |
|
||||
Impl::ssaDefReachesRead(v, def, bb1, i1) and
|
||||
Impl::adjacentUseUse(bb1, i1, bb2, i2, v, true) and
|
||||
read1 = bb1.getNode(i1) and
|
||||
read2 = bb2.getNode(i2)
|
||||
read1 = bb1.getNode(i1).getAstNode() and
|
||||
read2 = bb2.getNode(i2).getAstNode()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -287,7 +288,7 @@ private module Cached {
|
||||
DataFlowIntegrationImpl::localMustFlowStep(v, nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
signature predicate guardChecksSig(CfgNodes::AstCfgNode g, Cfg::CfgNode e, boolean branch);
|
||||
signature predicate guardChecksSig(AstNode g, Expr e, boolean branch);
|
||||
|
||||
cached // nothing is actually cached
|
||||
module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
@@ -310,47 +311,49 @@ private module Cached {
|
||||
import Cached
|
||||
private import codeql.rust.dataflow.Ssa
|
||||
|
||||
private class ExprAlias = Expr;
|
||||
|
||||
private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInputSig {
|
||||
private import codeql.rust.dataflow.internal.DataFlowImpl as DataFlowImpl
|
||||
private import codeql.util.Boolean
|
||||
|
||||
class Expr extends CfgNodes::AstCfgNode {
|
||||
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) }
|
||||
class Expr extends ExprAlias {
|
||||
predicate hasCfgNode(BasicBlock bb, int i) { this.getACfgNode() = bb.getNode(i) }
|
||||
}
|
||||
|
||||
Expr getARead(Definition def) { result = Cached::getARead(def) }
|
||||
|
||||
predicate ssaDefHasSource(WriteDefinition def) { none() } // handled in `DataFlowImpl.qll` instead
|
||||
|
||||
private predicate isArg(CfgNodes::CallExprBaseCfgNode call, CfgNodes::ExprCfgNode e) {
|
||||
call.getArgument(_) = e
|
||||
private predicate isArg(CallExprBase call, Expr e) {
|
||||
call.getAnArg() = e
|
||||
or
|
||||
call.(CfgNodes::MethodCallExprCfgNode).getReceiver() = e
|
||||
call.(MethodCallExpr).getReceiver() = e
|
||||
or
|
||||
exists(CfgNodes::ExprCfgNode mid |
|
||||
exists(Expr mid |
|
||||
isArg(call, mid) and
|
||||
e = DataFlowImpl::getPostUpdateReverseStep(mid, _)
|
||||
)
|
||||
}
|
||||
|
||||
predicate allowFlowIntoUncertainDef(UncertainWriteDefinition def) {
|
||||
exists(CfgNodes::CallExprBaseCfgNode call, Variable v, BasicBlock bb, int i |
|
||||
exists(Variable v, BasicBlock bb, int i |
|
||||
def.definesAt(v, bb, i) and
|
||||
mutablyBorrows(bb.getNode(i).getAstNode(), v) and
|
||||
isArg(call, bb.getNode(i))
|
||||
isArg(_, bb.getNode(i).getAstNode())
|
||||
)
|
||||
}
|
||||
|
||||
class GuardValue = Boolean;
|
||||
|
||||
class Guard extends CfgNodes::AstCfgNode {
|
||||
class Guard extends AstNode {
|
||||
/**
|
||||
* Holds if the evaluation of this guard to `branch` corresponds to the edge
|
||||
* from `bb1` to `bb2`.
|
||||
*/
|
||||
predicate hasValueBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue branch) {
|
||||
exists(Cfg::ConditionalSuccessor s |
|
||||
this = bb1.getANode() and
|
||||
this = bb1.getANode().getAstNode() and
|
||||
bb2 = bb1.getASuccessor(s) and
|
||||
s.getValue() = branch
|
||||
)
|
||||
@@ -369,7 +372,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
|
||||
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
|
||||
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, GuardValue branch) {
|
||||
exists(ConditionBasicBlock conditionBlock, ConditionalSuccessor s |
|
||||
guard = conditionBlock.getLastNode() and
|
||||
guard = conditionBlock.getLastNode().getAstNode() and
|
||||
s.getValue() = branch and
|
||||
conditionBlock.edgeDominates(bb, s)
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
private import rust
|
||||
private import codeql.dataflow.TaintTracking
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.dataflow.FlowSummary
|
||||
private import DataFlowImpl
|
||||
@@ -21,22 +20,22 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
|
||||
Stages::DataFlowStage::ref() and
|
||||
model = "" and
|
||||
(
|
||||
exists(BinaryExprCfgNode binary |
|
||||
exists(BinaryExpr binary |
|
||||
binary.getOperatorName() = ["+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>"] and
|
||||
pred.asExpr() = [binary.getLhs(), binary.getRhs()] and
|
||||
succ.asExpr() = binary
|
||||
)
|
||||
or
|
||||
exists(PrefixExprCfgNode prefix |
|
||||
exists(PrefixExpr prefix |
|
||||
prefix.getOperatorName() = ["-", "!"] and
|
||||
pred.asExpr() = prefix.getExpr() and
|
||||
succ.asExpr() = prefix
|
||||
)
|
||||
or
|
||||
pred.asExpr() = succ.asExpr().(CastExprCfgNode).getExpr()
|
||||
pred.asExpr() = succ.asExpr().(CastExpr).getExpr()
|
||||
or
|
||||
exists(IndexExprCfgNode index |
|
||||
index.getIndex() instanceof RangeExprCfgNode and
|
||||
exists(IndexExpr index |
|
||||
index.getIndex() instanceof RangeExpr and
|
||||
pred.asExpr() = index.getBase() and
|
||||
succ.asExpr() = index
|
||||
)
|
||||
@@ -52,8 +51,16 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
|
||||
cs.getContent() instanceof ReferenceContent
|
||||
)
|
||||
or
|
||||
exists(FormatArgsExprCfgNode format | succ.asExpr() = format |
|
||||
pred.asExpr() = [format.getArgumentExpr(_), format.getFormatTemplateVariableAccess(_)]
|
||||
exists(FormatArgsExpr format | succ.asExpr() = format |
|
||||
pred.asExpr() = format.getAnArg().getExpr()
|
||||
or
|
||||
pred.asExpr() =
|
||||
any(FormatTemplateVariableAccess v |
|
||||
exists(Format f |
|
||||
f = format.getAFormat() and
|
||||
v.getArgument() = [f.getArgumentRef(), f.getWidthArgument(), f.getPrecisionArgument()]
|
||||
)
|
||||
)
|
||||
)
|
||||
or
|
||||
succ.(Node::PostUpdateNode).getPreUpdateNode().asExpr() =
|
||||
|
||||
@@ -25,6 +25,11 @@ final class AssignmentOperation = AssignmentOperationImpl;
|
||||
final class AssignmentExpr extends AssignmentOperationImpl {
|
||||
AssignmentExpr() { this.getOperatorName() = "=" }
|
||||
|
||||
/**
|
||||
* Gets a write access that occurs in the left-hand side of this assignment expression.
|
||||
*/
|
||||
VariableWriteAccess getAWriteAccess() { this = result.getAssignmentExpr() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignmentExpr" }
|
||||
}
|
||||
|
||||
|
||||
7
rust/ql/lib/codeql/rust/elements/ConstAccess.qll
Normal file
7
rust/ql/lib/codeql/rust/elements/ConstAccess.qll
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This module provides the public class `ConstAccess`.
|
||||
*/
|
||||
|
||||
private import internal.ConstImpl
|
||||
|
||||
final class ConstAccess = Impl::ConstAccess;
|
||||
@@ -13,9 +13,9 @@ private import codeql.rust.controlflow.ControlFlowGraph
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.ElementImpl::Impl as ElementImpl
|
||||
private import codeql.rust.elements.internal.generated.ParentChild
|
||||
private import codeql.rust.controlflow.ControlFlowGraph
|
||||
private import codeql.rust.elements.internal.MacroCallImpl::Impl as MacroCallImpl
|
||||
|
||||
/**
|
||||
* Gets the immediate parent of a non-`AstNode` element `e`.
|
||||
@@ -59,6 +59,9 @@ module Impl {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this node is inside a CFG scope. */
|
||||
predicate hasEnclosingCfgScope() { exists(this.getEnclosingCfgScope()) }
|
||||
|
||||
/** Gets the block that encloses this node, if any. */
|
||||
cached
|
||||
BlockExpr getEnclosingBlock() {
|
||||
@@ -71,21 +74,15 @@ module Impl {
|
||||
}
|
||||
|
||||
/** Holds if this node is inside a macro expansion. */
|
||||
predicate isInMacroExpansion() { MacroCallImpl::isInMacroExpansion(_, this) }
|
||||
predicate isInMacroExpansion() { ElementImpl::MacroExpansion::isInMacroExpansion(this) }
|
||||
|
||||
/**
|
||||
* Holds if this node exists only as the result of a macro expansion.
|
||||
*
|
||||
* This is the same as `isInMacroExpansion()`, but excludes AST nodes corresponding
|
||||
* to macro arguments.
|
||||
* to macro arguments, including attribute macro targets.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate isFromMacroExpansion() {
|
||||
exists(AstNode root |
|
||||
MacroCallImpl::isInMacroExpansion(root, this) and
|
||||
not this = root.(MacroCall).getATokenTreeNode()
|
||||
)
|
||||
}
|
||||
predicate isFromMacroExpansion() { ElementImpl::MacroExpansion::isFromMacroExpansion(this) }
|
||||
|
||||
/**
|
||||
* Gets a control flow node for this AST node, if any.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `BlockExpr`.
|
||||
*
|
||||
@@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.BlockExpr
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A block expression. For example:
|
||||
* ```rust
|
||||
@@ -26,5 +26,10 @@ module Impl {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class BlockExpr extends Generated::BlockExpr { }
|
||||
class BlockExpr extends Generated::BlockExpr {
|
||||
/**
|
||||
* Gets the tail expression of this block, if it exists.
|
||||
*/
|
||||
Expr getTailExpr() { result = this.getStmtList().getTailExpr() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `Const`.
|
||||
*
|
||||
@@ -6,12 +5,15 @@
|
||||
*/
|
||||
|
||||
private import codeql.rust.elements.internal.generated.Const
|
||||
private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl
|
||||
private import codeql.rust.internal.PathResolution
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the customizable definition of `Const` and should not
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A constant item declaration.
|
||||
*
|
||||
@@ -21,4 +23,27 @@ module Impl {
|
||||
* ```
|
||||
*/
|
||||
class Const extends Generated::Const { }
|
||||
|
||||
/**
|
||||
* A constant access.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
* const X: i32 = 42;
|
||||
*
|
||||
* fn main() {
|
||||
* println!("{}", X);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class ConstAccess extends PathExprImpl::PathExpr {
|
||||
private Const c;
|
||||
|
||||
ConstAccess() { c = resolvePath(this.getPath()) }
|
||||
|
||||
/** Gets the constant being accessed. */
|
||||
Const getConst() { result = c }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ConstAccess" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,118 @@ private import codeql.rust.elements.internal.generated.Element
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.generated.ParentChild
|
||||
private import codeql.rust.elements.internal.generated.Synth
|
||||
private import codeql.rust.elements.internal.generated.Raw
|
||||
private import codeql.rust.elements.internal.LocationImpl
|
||||
|
||||
/**
|
||||
* Provides logic for classifying elements with respect to macro expansions.
|
||||
*/
|
||||
cached
|
||||
module MacroExpansion {
|
||||
/**
|
||||
* Holds if `e` is superseded by an attribute macro expansion. That is, `e` is
|
||||
* a transitive child of an item with an attribute macro expansion.
|
||||
*
|
||||
* Since this predicate is referenced in the charpred of `Element`, we need to
|
||||
* use the parent-child relation on raw elements to avoid non-monotonicity.
|
||||
*/
|
||||
private predicate supersededByAttributeMacroExpansionRaw(Raw::Item item, Raw::Element e) {
|
||||
exists(item.getAttributeMacroExpansion()) and
|
||||
e = Raw::getImmediateChild(item, _) and
|
||||
not e = item.getAttributeMacroExpansion() and
|
||||
// Don't consider attributes themselves to be superseded. E.g., in `#[a] fn
|
||||
// f() {}` the macro expansion supersedes `fn f() {}` but not `#[a]`.
|
||||
not e instanceof Raw::Attr
|
||||
or
|
||||
exists(Raw::Element parent |
|
||||
e = Raw::getImmediateChild(parent, _) and
|
||||
supersededByAttributeMacroExpansionRaw(item, parent)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isMacroExpansion(AstNode macro, AstNode expansion) {
|
||||
expansion = macro.(MacroCall).getMacroCallExpansion()
|
||||
or
|
||||
expansion = macro.(Adt).getDeriveMacroExpansion(_)
|
||||
or
|
||||
expansion = macro.(Item).getAttributeMacroExpansion()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the immediately enclosing macro invocation for element `e`, if any.
|
||||
*
|
||||
* The result is either a `MacroCall`, an `Adt` with a derive macro expansion, or
|
||||
* an `Item` with an attribute macro expansion.
|
||||
*/
|
||||
cached
|
||||
AstNode getImmediatelyEnclosingMacroInvocation(Element e) {
|
||||
isMacroExpansion(result, e)
|
||||
or
|
||||
exists(Element mid |
|
||||
result = getImmediatelyEnclosingMacroInvocation(mid) and
|
||||
mid = getImmediateParent(e) and
|
||||
not isMacroExpansion(mid, e)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isAttributeMacroExpansionSourceLocation(Item i, Location l) {
|
||||
exists(Raw::Locatable e, @location_default loc |
|
||||
supersededByAttributeMacroExpansionRaw(Synth::convertElementToRaw(i), e) and
|
||||
locatable_locations(e, loc) and
|
||||
l = LocationImpl::TLocationDefault(loc)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets an AST node whose location is inside the token tree belonging to `mc`. */
|
||||
pragma[nomagic]
|
||||
private AstNode getATokenTreeNode(MacroCall mc) {
|
||||
mc = getImmediatelyEnclosingMacroInvocation(result) and
|
||||
mc.getTokenTree().getLocation().contains(result.getLocation())
|
||||
}
|
||||
|
||||
/** Holds if `n` is inside a macro expansion. */
|
||||
cached
|
||||
predicate isInMacroExpansion(AstNode n) { exists(getImmediatelyEnclosingMacroInvocation(n)) }
|
||||
|
||||
/**
|
||||
* Holds if `n` exists only as the result of a macro expansion.
|
||||
*
|
||||
* This is the same as `isInMacroExpansion(n)`, but excludes AST nodes corresponding
|
||||
* to macro arguments, including attribute macro targets.
|
||||
*
|
||||
* Note: This predicate is a heuristic based on location information and may not be
|
||||
* accurate in all cases.
|
||||
*/
|
||||
cached
|
||||
predicate isFromMacroExpansion(AstNode n) {
|
||||
exists(AstNode macro |
|
||||
macro = getImmediatelyEnclosingMacroInvocation(n) and
|
||||
not n = getATokenTreeNode(macro) and
|
||||
not isAttributeMacroExpansionSourceLocation(macro, n.getLocation())
|
||||
)
|
||||
or
|
||||
isFromMacroExpansion(pragma[only_bind_into](getImmediatelyEnclosingMacroInvocation(n)))
|
||||
}
|
||||
|
||||
cached
|
||||
predicate isRelevantElement(Generated::Element e) {
|
||||
exists(Raw::Element raw |
|
||||
raw = Synth::convertElementToRaw(e) and
|
||||
not supersededByAttributeMacroExpansionRaw(_, raw)
|
||||
)
|
||||
or
|
||||
// Synthetic elements are relevant when their parents are
|
||||
Synth::convertFormatArgsExprToRaw(_) = Synth::getSynthParent(e)
|
||||
}
|
||||
}
|
||||
|
||||
class Element extends Generated::Element {
|
||||
Element() { MacroExpansion::isRelevantElement(this) }
|
||||
|
||||
override string toStringImpl() { result = this.getAPrimaryQlClass() }
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `Item`.
|
||||
*
|
||||
@@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.Item
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* An item such as a function, struct, enum, etc.
|
||||
*
|
||||
@@ -23,4 +23,10 @@ module Impl {
|
||||
* ```
|
||||
*/
|
||||
class Item extends Generated::Item { }
|
||||
|
||||
private class ItemWithAttributeMacroExpansion extends Item {
|
||||
ItemWithAttributeMacroExpansion() { this.hasAttributeMacroExpansion() }
|
||||
|
||||
override string toStringImpl() { result = "(item with attribute macro expansion)" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ module Impl {
|
||||
* [1]: https://doc.rust-lang.org/reference/tokens.html#string-literals
|
||||
*/
|
||||
class StringLiteralExpr extends LiteralExpr {
|
||||
StringLiteralExpr() { this.getTextValue().regexpMatch("r?#*\".*\"#*") }
|
||||
StringLiteralExpr() { this.getTextValue().charAt(0) = ["\"", "r"] }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "StringLiteralExpr" }
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import codeql.Locations
|
||||
private import codeql.rust.elements.internal.ElementImpl::Impl as ElementImpl
|
||||
private import codeql.rust.elements.internal.LocationImpl
|
||||
private import codeql.rust.elements.internal.generated.Locatable
|
||||
private import codeql.rust.elements.internal.generated.Synth
|
||||
@@ -50,21 +51,12 @@ module Impl {
|
||||
locatable_locations(Synth::convertLocatableToRaw(l), result)
|
||||
}
|
||||
|
||||
private MacroCall getImmediatelyEnclosingMacroCall(AstNode n) {
|
||||
result = n.getParentNode()
|
||||
or
|
||||
exists(AstNode mid |
|
||||
result = getImmediatelyEnclosingMacroCall(mid) and
|
||||
n.getParentNode() = mid and
|
||||
not mid instanceof MacroCall
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the non-synthesized location of `l`, if any. */
|
||||
LocationImpl::LocationDefault getLocationDefault(Locatable l) {
|
||||
result = LocationImpl::TLocationDefault(getDbLocation(l))
|
||||
or
|
||||
not exists(getDbLocation(l)) and
|
||||
result = getLocationDefault(getImmediatelyEnclosingMacroCall(l))
|
||||
result =
|
||||
getLocationDefault(ElementImpl::MacroExpansion::getImmediatelyEnclosingMacroInvocation(l))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,17 +14,6 @@ module Impl {
|
||||
private import rust
|
||||
private import codeql.rust.internal.PathResolution
|
||||
|
||||
pragma[nomagic]
|
||||
predicate isInMacroExpansion(AstNode root, AstNode n) {
|
||||
n = root.(MacroCall).getMacroCallExpansion()
|
||||
or
|
||||
n = root.(Adt).getDeriveMacroExpansion(_)
|
||||
or
|
||||
n = root.(Item).getAttributeMacroExpansion()
|
||||
or
|
||||
isInMacroExpansion(root, n.getParentNode())
|
||||
}
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A macro invocation.
|
||||
@@ -35,16 +24,7 @@ module Impl {
|
||||
* ```
|
||||
*/
|
||||
class MacroCall extends Generated::MacroCall {
|
||||
override string toStringImpl() {
|
||||
if this.hasPath() then result = this.getPath().toAbbreviatedString() + "!..." else result = ""
|
||||
}
|
||||
|
||||
/** Gets an AST node whose location is inside the token tree belonging to this macro call. */
|
||||
pragma[nomagic]
|
||||
AstNode getATokenTreeNode() {
|
||||
isInMacroExpansion(this, result) and
|
||||
this.getTokenTree().getLocation().contains(result.getLocation())
|
||||
}
|
||||
override string toStringImpl() { result = this.getPath().toAbbreviatedString() + "!..." }
|
||||
|
||||
/**
|
||||
* Gets the macro definition that this macro call resolves to.
|
||||
|
||||
@@ -21,6 +21,24 @@ module Impl {
|
||||
* ```
|
||||
*/
|
||||
class ParenExpr extends Generated::ParenExpr {
|
||||
override string toStringImpl() { result = "(" + this.getExpr().toAbbreviatedString() + ")" }
|
||||
override string toStringImpl() {
|
||||
result = "(" + this.getExpr().toAbbreviatedString() + ")"
|
||||
or
|
||||
// In macro expansions such as
|
||||
//
|
||||
// ```rust
|
||||
// [
|
||||
// "a",
|
||||
// "b",
|
||||
// #[cfg(target_os = "macos")]
|
||||
// "c",
|
||||
// ]
|
||||
// ```
|
||||
//
|
||||
// the last array element will give rise to an empty `ParenExpr` when not
|
||||
// compiling for macos.
|
||||
not exists(this.getExpr().toAbbreviatedString()) and
|
||||
result = "(...)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,16 @@ module Impl {
|
||||
result.getName().getText() = name
|
||||
}
|
||||
|
||||
/** Gets a record field, if any. */
|
||||
StructField getAStructField() { result = this.getStructField(_) }
|
||||
|
||||
/** Gets the `i`th tuple field, if any. */
|
||||
pragma[nomagic]
|
||||
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }
|
||||
|
||||
/** Gets a tuple field, if any. */
|
||||
TupleField getATupleField() { result = this.getTupleField(_) }
|
||||
|
||||
/** Holds if this struct uses tuple fields. */
|
||||
pragma[nomagic]
|
||||
predicate isTuple() { this.getFieldList() instanceof TupleFieldList }
|
||||
|
||||
@@ -15,21 +15,12 @@ module Impl {
|
||||
|
||||
class BlockExprScope extends VariableScope, BlockExpr { }
|
||||
|
||||
abstract class MatchArmScope extends VariableScope {
|
||||
MatchArm arm;
|
||||
|
||||
bindingset[arm]
|
||||
MatchArmScope() { exists(arm) }
|
||||
|
||||
Pat getPat() { result = arm.getPat() }
|
||||
class MatchArmExprScope extends VariableScope {
|
||||
MatchArmExprScope() { this = any(MatchArm arm).getExpr() }
|
||||
}
|
||||
|
||||
class MatchArmExprScope extends MatchArmScope {
|
||||
MatchArmExprScope() { this = arm.getExpr() }
|
||||
}
|
||||
|
||||
class MatchArmGuardScope extends MatchArmScope {
|
||||
MatchArmGuardScope() { this = arm.getGuard() }
|
||||
class MatchArmGuardScope extends VariableScope {
|
||||
MatchArmGuardScope() { this = any(MatchArm arm).getGuard() }
|
||||
}
|
||||
|
||||
class ClosureBodyScope extends VariableScope {
|
||||
@@ -41,7 +32,7 @@ module Impl {
|
||||
*
|
||||
* Such variables are only available in the body guarded by the condition.
|
||||
*/
|
||||
class ConditionScope extends VariableScope, Expr {
|
||||
class ConditionScope extends VariableScope {
|
||||
private AstNode parent;
|
||||
private AstNode body;
|
||||
|
||||
@@ -57,6 +48,12 @@ module Impl {
|
||||
this = we.getCondition() and
|
||||
body = we.getLoopBody()
|
||||
)
|
||||
or
|
||||
parent =
|
||||
any(MatchArm ma |
|
||||
this = ma.getGuard() and
|
||||
body = ma.getExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the parent of this condition. */
|
||||
@@ -417,11 +414,14 @@ module Impl {
|
||||
ord = getPreOrderNumbering(scope, scope)
|
||||
or
|
||||
exists(Pat pat | pat = getAVariablePatAncestor(v) |
|
||||
scope =
|
||||
any(MatchArmScope arm |
|
||||
arm.getPat() = pat and
|
||||
ord = getPreOrderNumbering(scope, arm)
|
||||
)
|
||||
exists(MatchArm arm |
|
||||
pat = arm.getPat() and
|
||||
ord = getPreOrderNumbering(scope, scope)
|
||||
|
|
||||
scope = arm.getGuard()
|
||||
or
|
||||
not arm.hasGuard() and scope = arm.getExpr()
|
||||
)
|
||||
or
|
||||
exists(LetStmt let |
|
||||
let.getPat() = pat and
|
||||
|
||||
@@ -74,7 +74,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfArgList(ArgList e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nArg |
|
||||
n = 0 and
|
||||
nArg = n + 1 + max(int i | i = -1 or exists(e.getArg(i)) | i) and
|
||||
nArg = n + e.getNumberOfArgs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -126,8 +126,8 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAssocItem, int nAttr |
|
||||
n = 0 and
|
||||
nAssocItem = n + 1 + max(int i | i = -1 or exists(e.getAssocItem(i)) | i) and
|
||||
nAttr = nAssocItem + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAssocItem = n + e.getNumberOfAssocItems() and
|
||||
nAttr = nAssocItem + e.getNumberOfAttrs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -157,8 +157,8 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr, int nExternItem |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nExternItem = nAttr + 1 + max(int i | i = -1 or exists(e.getExternItem(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExternItem = nAttr + e.getNumberOfExternItems() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -207,7 +207,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nGenericArg |
|
||||
n = 0 and
|
||||
nGenericArg = n + 1 + max(int i | i = -1 or exists(e.getGenericArg(i)) | i) and
|
||||
nGenericArg = n + e.getNumberOfGenericArgs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -222,7 +222,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nGenericParam |
|
||||
n = 0 and
|
||||
nGenericParam = n + 1 + max(int i | i = -1 or exists(e.getGenericParam(i)) | i) and
|
||||
nGenericParam = n + e.getNumberOfGenericParams() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -235,8 +235,8 @@ private module Impl {
|
||||
private Element getImmediateChildOfItemList(ItemList e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nItem |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nItem = nAttr + 1 + max(int i | i = -1 or exists(e.getItem(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nItem = nAttr + e.getNumberOfItems() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -276,7 +276,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfMacroItems(MacroItems e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nItem |
|
||||
n = 0 and
|
||||
nItem = n + 1 + max(int i | i = -1 or exists(e.getItem(i)) | i) and
|
||||
nItem = n + e.getNumberOfItems() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -289,7 +289,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfMatchArm(MatchArm e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr, int nGuard, int nPat |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
nGuard = nExpr + 1 and
|
||||
nPat = nGuard + 1 and
|
||||
@@ -313,8 +313,8 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nArm, int nAttr |
|
||||
n = 0 and
|
||||
nArm = n + 1 + max(int i | i = -1 or exists(e.getArm(i)) | i) and
|
||||
nAttr = nArm + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nArm = n + e.getNumberOfArms() and
|
||||
nAttr = nArm + e.getNumberOfAttrs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -362,7 +362,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfParamList(ParamList e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nParam, int nSelfParam |
|
||||
n = 0 and
|
||||
nParam = n + 1 + max(int i | i = -1 or exists(e.getParam(i)) | i) and
|
||||
nParam = n + e.getNumberOfParams() and
|
||||
nSelfParam = nParam + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -380,7 +380,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nTypeArg |
|
||||
n = 0 and
|
||||
nTypeArg = n + 1 + max(int i | i = -1 or exists(e.getTypeArg(i)) | i) and
|
||||
nTypeArg = n + e.getNumberOfTypeArgs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -487,8 +487,8 @@ private module Impl {
|
||||
private Element getImmediateChildOfSourceFile(SourceFile e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nItem |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nItem = nAttr + 1 + max(int i | i = -1 or exists(e.getItem(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nItem = nAttr + e.getNumberOfItems() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -504,8 +504,8 @@ private module Impl {
|
||||
private Element getImmediateChildOfStmtList(StmtList e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nStatement, int nTailExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nStatement = nAttr + 1 + max(int i | i = -1 or exists(e.getStatement(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nStatement = nAttr + e.getNumberOfStatements() and
|
||||
nTailExpr = nStatement + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -526,7 +526,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr, int nExpr, int nIdentifier |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
nIdentifier = nExpr + 1 and
|
||||
(
|
||||
@@ -547,8 +547,8 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr, int nField, int nSpread |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nField = nAttr + 1 + max(int i | i = -1 or exists(e.getField(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nField = nAttr + e.getNumberOfFields() and
|
||||
nSpread = nField + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -569,7 +569,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr, int nDefault, int nName, int nTypeRepr, int nVisibility |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nDefault = nAttr + 1 and
|
||||
nName = nDefault + 1 and
|
||||
nTypeRepr = nName + 1 and
|
||||
@@ -596,7 +596,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr, int nIdentifier, int nPat |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nIdentifier = nAttr + 1 and
|
||||
nPat = nIdentifier + 1 and
|
||||
(
|
||||
@@ -617,7 +617,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nField, int nRestPat |
|
||||
n = 0 and
|
||||
nField = n + 1 + max(int i | i = -1 or exists(e.getField(i)) | i) and
|
||||
nField = n + e.getNumberOfFields() and
|
||||
nRestPat = nField + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -637,7 +637,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfTupleField(TupleField e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nTypeRepr, int nVisibility |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nTypeRepr = nAttr + 1 and
|
||||
nVisibility = nTypeRepr + 1 and
|
||||
(
|
||||
@@ -681,7 +681,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nBound |
|
||||
n = 0 and
|
||||
nBound = n + 1 + max(int i | i = -1 or exists(e.getBound(i)) | i) and
|
||||
nBound = n + e.getNumberOfBounds() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -696,7 +696,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nUseBoundGenericArg |
|
||||
n = 0 and
|
||||
nUseBoundGenericArg = n + 1 + max(int i | i = -1 or exists(e.getUseBoundGenericArg(i)) | i) and
|
||||
nUseBoundGenericArg = n + e.getNumberOfUseBoundGenericArgs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -729,7 +729,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nUseTree |
|
||||
n = 0 and
|
||||
nUseTree = n + 1 + max(int i | i = -1 or exists(e.getUseTree(i)) | i) and
|
||||
nUseTree = n + e.getNumberOfUseTrees() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -744,7 +744,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nVariant |
|
||||
n = 0 and
|
||||
nVariant = n + 1 + max(int i | i = -1 or exists(e.getVariant(i)) | i) and
|
||||
nVariant = n + e.getNumberOfVariants() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -771,7 +771,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nPredicate |
|
||||
n = 0 and
|
||||
nPredicate = n + 1 + max(int i | i = -1 or exists(e.getPredicate(i)) | i) and
|
||||
nPredicate = n + e.getNumberOfPredicates() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -809,8 +809,8 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nExpr = nAttr + 1 + max(int i | i = -1 or exists(e.getExpr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + e.getNumberOfExprs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -894,7 +894,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAsmOption |
|
||||
n = 0 and
|
||||
nAsmOption = n + 1 + max(int i | i = -1 or exists(e.getAsmOption(i)) | i) and
|
||||
nAsmOption = n + e.getNumberOfAsmOptions() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -991,7 +991,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfAwaitExpr(AwaitExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1007,7 +1007,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfBecomeExpr(BecomeExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1023,7 +1023,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfBinaryExpr(BinaryExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nLhs, int nRhs |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nLhs = nAttr + 1 and
|
||||
nRhs = nLhs + 1 and
|
||||
(
|
||||
@@ -1054,7 +1054,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfBreakExpr(BreakExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr, int nLifetime |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
nLifetime = nExpr + 1 and
|
||||
(
|
||||
@@ -1073,7 +1073,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfCastExpr(CastExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr, int nTypeRepr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
nTypeRepr = nExpr + 1 and
|
||||
(
|
||||
@@ -1095,7 +1095,7 @@ private module Impl {
|
||||
exists(int n, int nParamList, int nAttr, int nClosureBody, int nForBinder, int nRetType |
|
||||
n = 0 and
|
||||
nParamList = n + 1 and
|
||||
nAttr = nParamList + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nParamList + e.getNumberOfAttrs() and
|
||||
nClosureBody = nAttr + 1 and
|
||||
nForBinder = nClosureBody + 1 and
|
||||
nRetType = nForBinder + 1 and
|
||||
@@ -1149,7 +1149,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfConstParam(ConstParam e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nDefaultVal, int nName, int nTypeRepr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nDefaultVal = nAttr + 1 and
|
||||
nName = nDefaultVal + 1 and
|
||||
nTypeRepr = nName + 1 and
|
||||
@@ -1173,7 +1173,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr, int nLifetime |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nLifetime = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1215,7 +1215,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfFieldExpr(FieldExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nContainer, int nIdentifier |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nContainer = nAttr + 1 and
|
||||
nIdentifier = nContainer + 1 and
|
||||
(
|
||||
@@ -1273,10 +1273,10 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nArg, int nAttr, int nTemplate, int nFormat |
|
||||
n = 0 and
|
||||
nArg = n + 1 + max(int i | i = -1 or exists(e.getArg(i)) | i) and
|
||||
nAttr = nArg + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nArg = n + e.getNumberOfArgs() and
|
||||
nAttr = nArg + e.getNumberOfAttrs() and
|
||||
nTemplate = nAttr + 1 and
|
||||
nFormat = nTemplate + 1 + max(int i | i = -1 or exists(e.getFormat(i)) | i) and
|
||||
nFormat = nTemplate + e.getNumberOfFormats() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -1297,7 +1297,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfIdentPat(IdentPat e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nName, int nPat |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nName = nAttr + 1 and
|
||||
nPat = nName + 1 and
|
||||
(
|
||||
@@ -1316,7 +1316,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfIfExpr(IfExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nCondition, int nElse, int nThen |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nCondition = nAttr + 1 and
|
||||
nElse = nCondition + 1 and
|
||||
nThen = nElse + 1 and
|
||||
@@ -1352,7 +1352,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfIndexExpr(IndexExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nBase, int nIndex |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nBase = nAttr + 1 and
|
||||
nIndex = nBase + 1 and
|
||||
(
|
||||
@@ -1377,7 +1377,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfLetExpr(LetExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nScrutinee, int nPat |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nScrutinee = nAttr + 1 and
|
||||
nPat = nScrutinee + 1 and
|
||||
(
|
||||
@@ -1396,7 +1396,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfLetStmt(LetStmt e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nInitializer, int nLetElse, int nPat, int nTypeRepr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nInitializer = nAttr + 1 and
|
||||
nLetElse = nInitializer + 1 and
|
||||
nPat = nLetElse + 1 and
|
||||
@@ -1441,7 +1441,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr, int nLifetime, int nTypeBoundList |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nLifetime = nAttr + 1 and
|
||||
nTypeBoundList = nLifetime + 1 and
|
||||
(
|
||||
@@ -1464,7 +1464,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -1491,7 +1491,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nStatement, int nTailExpr |
|
||||
n = 0 and
|
||||
nStatement = n + 1 + max(int i | i = -1 or exists(e.getStatement(i)) | i) and
|
||||
nStatement = n + e.getNumberOfStatements() and
|
||||
nTailExpr = nStatement + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1545,7 +1545,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfMatchExpr(MatchExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nScrutinee, int nMatchArmList |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nScrutinee = nAttr + 1 and
|
||||
nMatchArmList = nScrutinee + 1 and
|
||||
(
|
||||
@@ -1578,8 +1578,8 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr, int nField, int nTypeRepr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nField = nAttr + 1 + max(int i | i = -1 or exists(e.getField(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nField = nAttr + e.getNumberOfFields() and
|
||||
nTypeRepr = nField + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1598,7 +1598,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfOrPat(OrPat e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nPat |
|
||||
n = 0 and
|
||||
nPat = n + 1 + max(int i | i = -1 or exists(e.getPat(i)) | i) and
|
||||
nPat = n + e.getNumberOfPats() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -1611,7 +1611,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfParam(Param e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nTypeRepr, int nPat |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nTypeRepr = nAttr + 1 and
|
||||
nPat = nTypeRepr + 1 and
|
||||
(
|
||||
@@ -1630,7 +1630,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfParenExpr(ParenExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1698,7 +1698,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfPrefixExpr(PrefixExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1728,7 +1728,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfRangeExpr(RangeExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nEnd, int nStart |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nEnd = nAttr + 1 and
|
||||
nStart = nEnd + 1 and
|
||||
(
|
||||
@@ -1762,7 +1762,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfRefExpr(RefExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1807,7 +1807,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfRestPat(RestPat e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -1820,7 +1820,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfReturnExpr(ReturnExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1836,7 +1836,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfSelfParam(SelfParam e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nTypeRepr, int nLifetime, int nName |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nTypeRepr = nAttr + 1 and
|
||||
nLifetime = nTypeRepr + 1 and
|
||||
nName = nLifetime + 1 and
|
||||
@@ -1858,7 +1858,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfSlicePat(SlicePat e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nPat |
|
||||
n = 0 and
|
||||
nPat = n + 1 + max(int i | i = -1 or exists(e.getPat(i)) | i) and
|
||||
nPat = n + e.getNumberOfPats() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -1904,7 +1904,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nField |
|
||||
n = 0 and
|
||||
nField = n + 1 + max(int i | i = -1 or exists(e.getField(i)) | i) and
|
||||
nField = n + e.getNumberOfFields() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -1934,7 +1934,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfTryExpr(TryExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -1950,8 +1950,8 @@ private module Impl {
|
||||
private Element getImmediateChildOfTupleExpr(TupleExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nField |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nField = nAttr + 1 + max(int i | i = -1 or exists(e.getField(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nField = nAttr + e.getNumberOfFields() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -1969,7 +1969,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nField |
|
||||
n = 0 and
|
||||
nField = n + 1 + max(int i | i = -1 or exists(e.getField(i)) | i) and
|
||||
nField = n + e.getNumberOfFields() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -1982,7 +1982,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfTuplePat(TuplePat e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nField |
|
||||
n = 0 and
|
||||
nField = n + 1 + max(int i | i = -1 or exists(e.getField(i)) | i) and
|
||||
nField = n + e.getNumberOfFields() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -1998,7 +1998,7 @@ private module Impl {
|
||||
exists(int n, int nPath, int nField |
|
||||
n = 0 and
|
||||
nPath = n + 1 and
|
||||
nField = nPath + 1 + max(int i | i = -1 or exists(e.getField(i)) | i) and
|
||||
nField = nPath + e.getNumberOfFields() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -2015,7 +2015,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nField |
|
||||
n = 0 and
|
||||
nField = n + 1 + max(int i | i = -1 or exists(e.getField(i)) | i) and
|
||||
nField = n + e.getNumberOfFields() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -2040,7 +2040,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfTypeParam(TypeParam e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nDefaultType, int nName, int nTypeBoundList |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nDefaultType = nAttr + 1 and
|
||||
nName = nDefaultType + 1 and
|
||||
nTypeBoundList = nName + 1 and
|
||||
@@ -2064,7 +2064,7 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nAttr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -2077,7 +2077,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfVariant(Variant e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nDiscriminant, int nFieldList, int nName, int nVisibility |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nDiscriminant = nAttr + 1 and
|
||||
nFieldList = nDiscriminant + 1 and
|
||||
nName = nFieldList + 1 and
|
||||
@@ -2108,7 +2108,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfYeetExpr(YeetExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -2124,7 +2124,7 @@ private module Impl {
|
||||
private Element getImmediateChildOfYieldExpr(YieldExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr |
|
||||
n = 0 and
|
||||
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = n + e.getNumberOfAttrs() and
|
||||
nExpr = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -2142,8 +2142,8 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nExpr, int nAttr |
|
||||
n = 0 and
|
||||
nExpr = n + 1 + max(int i | i = -1 or exists(e.getExpr(i)) | i) and
|
||||
nAttr = nExpr + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nExpr = n + e.getNumberOfExprs() and
|
||||
nAttr = nExpr + e.getNumberOfAttrs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -2161,8 +2161,8 @@ private module Impl {
|
||||
) {
|
||||
exists(int n, int nExpr, int nAttr, int nRepeatOperand, int nRepeatLength |
|
||||
n = 0 and
|
||||
nExpr = n + 1 + max(int i | i = -1 or exists(e.getExpr(i)) | i) and
|
||||
nAttr = nExpr + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nExpr = n + e.getNumberOfExprs() and
|
||||
nAttr = nExpr + e.getNumberOfAttrs() and
|
||||
nRepeatOperand = nAttr + 1 and
|
||||
nRepeatLength = nRepeatOperand + 1 and
|
||||
(
|
||||
@@ -2187,9 +2187,9 @@ private module Impl {
|
||||
exists(int n, int nAttributeMacroExpansion, int nAsmPiece, int nAttr, int nTemplate |
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAsmPiece = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAsmPiece(i)) | i) and
|
||||
nAttr = nAsmPiece + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nTemplate = nAttr + 1 + max(int i | i = -1 or exists(e.getTemplate(i)) | i) and
|
||||
nAsmPiece = nAttributeMacroExpansion + e.getNumberOfAsmPieces() and
|
||||
nAttr = nAsmPiece + e.getNumberOfAttrs() and
|
||||
nTemplate = nAttr + e.getNumberOfTemplates() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -2213,7 +2213,7 @@ private module Impl {
|
||||
exists(int n, int nLabel, int nAttr, int nStmtList |
|
||||
n = 0 and
|
||||
nLabel = n + 1 and
|
||||
nAttr = nLabel + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nLabel + e.getNumberOfAttrs() and
|
||||
nStmtList = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -2232,7 +2232,7 @@ private module Impl {
|
||||
exists(int n, int nArgList, int nAttr, int nFunction |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nFunction = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -2254,7 +2254,7 @@ private module Impl {
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAbi = nAttributeMacroExpansion + 1 and
|
||||
nAttr = nAbi + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAbi + e.getNumberOfAttrs() and
|
||||
nExternItemList = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
@@ -2283,7 +2283,7 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAttr = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAttributeMacroExpansion + e.getNumberOfAttrs() and
|
||||
nIdentifier = nAttr + 1 and
|
||||
nRename = nIdentifier + 1 and
|
||||
nVisibility = nRename + 1 and
|
||||
@@ -2320,7 +2320,7 @@ private module Impl {
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAssocItemList = nAttributeMacroExpansion + 1 and
|
||||
nAttr = nAssocItemList + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAssocItemList + e.getNumberOfAttrs() and
|
||||
nGenericParamList = nAttr + 1 and
|
||||
nSelfTy = nGenericParamList + 1 and
|
||||
nTrait = nSelfTy + 1 and
|
||||
@@ -2365,7 +2365,7 @@ private module Impl {
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nArgs = nAttributeMacroExpansion + 1 and
|
||||
nAttr = nArgs + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nArgs + e.getNumberOfAttrs() and
|
||||
nBody = nAttr + 1 and
|
||||
nName = nBody + 1 and
|
||||
nVisibility = nName + 1 and
|
||||
@@ -2398,7 +2398,7 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAttr = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAttributeMacroExpansion + e.getNumberOfAttrs() and
|
||||
nName = nAttr + 1 and
|
||||
nTokenTree = nName + 1 and
|
||||
nVisibility = nTokenTree + 1 and
|
||||
@@ -2427,7 +2427,7 @@ private module Impl {
|
||||
exists(int n, int nArgList, int nAttr, int nGenericArgList, int nIdentifier, int nReceiver |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nGenericArgList = nAttr + 1 and
|
||||
nIdentifier = nGenericArgList + 1 and
|
||||
nReceiver = nIdentifier + 1 and
|
||||
@@ -2458,7 +2458,7 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAttr = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAttributeMacroExpansion + e.getNumberOfAttrs() and
|
||||
nItemList = nAttr + 1 and
|
||||
nName = nItemList + 1 and
|
||||
nVisibility = nName + 1 and
|
||||
@@ -2485,7 +2485,7 @@ private module Impl {
|
||||
exists(int n, int nPath, int nAttr |
|
||||
n = 0 and
|
||||
nPath = n + 1 and
|
||||
nAttr = nPath + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nPath + e.getNumberOfAttrs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -2505,7 +2505,7 @@ private module Impl {
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAssocItemList = nAttributeMacroExpansion + 1 and
|
||||
nAttr = nAssocItemList + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAssocItemList + e.getNumberOfAttrs() and
|
||||
nGenericParamList = nAttr + 1 and
|
||||
nName = nGenericParamList + 1 and
|
||||
nTypeBoundList = nName + 1 and
|
||||
@@ -2551,7 +2551,7 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAttr = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAttributeMacroExpansion + e.getNumberOfAttrs() and
|
||||
nGenericParamList = nAttr + 1 and
|
||||
nName = nGenericParamList + 1 and
|
||||
nTypeBoundList = nName + 1 and
|
||||
@@ -2590,7 +2590,7 @@ private module Impl {
|
||||
exists(int n, int nAttributeMacroExpansion, int nAttr, int nUseTree, int nVisibility |
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAttr = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAttributeMacroExpansion + e.getNumberOfAttrs() and
|
||||
nUseTree = nAttr + 1 and
|
||||
nVisibility = nUseTree + 1 and
|
||||
(
|
||||
@@ -2617,7 +2617,7 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAttr = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAttributeMacroExpansion + e.getNumberOfAttrs() and
|
||||
nBody = nAttr + 1 and
|
||||
nGenericParamList = nBody + 1 and
|
||||
nName = nGenericParamList + 1 and
|
||||
@@ -2660,10 +2660,8 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nDeriveMacroExpansion =
|
||||
nAttributeMacroExpansion + 1 +
|
||||
max(int i | i = -1 or exists(e.getDeriveMacroExpansion(i)) | i) and
|
||||
nAttr = nDeriveMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nDeriveMacroExpansion = nAttributeMacroExpansion + e.getNumberOfDeriveMacroExpansions() and
|
||||
nAttr = nDeriveMacroExpansion + e.getNumberOfAttrs() and
|
||||
nGenericParamList = nAttr + 1 and
|
||||
nName = nGenericParamList + 1 and
|
||||
nVariantList = nName + 1 and
|
||||
@@ -2707,7 +2705,7 @@ private module Impl {
|
||||
n = 0 and
|
||||
nLabel = n + 1 and
|
||||
nLoopBody = nLabel + 1 and
|
||||
nAttr = nLoopBody + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nLoopBody + e.getNumberOfAttrs() and
|
||||
nIterable = nAttr + 1 and
|
||||
nPat = nIterable + 1 and
|
||||
(
|
||||
@@ -2735,7 +2733,7 @@ private module Impl {
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nParamList = nAttributeMacroExpansion + 1 and
|
||||
nAttr = nParamList + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nParamList + e.getNumberOfAttrs() and
|
||||
nAbi = nAttr + 1 and
|
||||
nFunctionBody = nAbi + 1 and
|
||||
nGenericParamList = nFunctionBody + 1 and
|
||||
@@ -2783,7 +2781,7 @@ private module Impl {
|
||||
n = 0 and
|
||||
nLabel = n + 1 and
|
||||
nLoopBody = nLabel + 1 and
|
||||
nAttr = nLoopBody + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nLoopBody + e.getNumberOfAttrs() and
|
||||
(
|
||||
none()
|
||||
or
|
||||
@@ -2804,7 +2802,7 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAttr = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAttributeMacroExpansion + e.getNumberOfAttrs() and
|
||||
nPath = nAttr + 1 and
|
||||
nTokenTree = nPath + 1 and
|
||||
nMacroCallExpansion = nTokenTree + 1 and
|
||||
@@ -2836,7 +2834,7 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAttr = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAttributeMacroExpansion + e.getNumberOfAttrs() and
|
||||
nBody = nAttr + 1 and
|
||||
nName = nBody + 1 and
|
||||
nTypeRepr = nName + 1 and
|
||||
@@ -2869,10 +2867,8 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nDeriveMacroExpansion =
|
||||
nAttributeMacroExpansion + 1 +
|
||||
max(int i | i = -1 or exists(e.getDeriveMacroExpansion(i)) | i) and
|
||||
nAttr = nDeriveMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nDeriveMacroExpansion = nAttributeMacroExpansion + e.getNumberOfDeriveMacroExpansions() and
|
||||
nAttr = nDeriveMacroExpansion + e.getNumberOfAttrs() and
|
||||
nFieldList = nAttr + 1 and
|
||||
nGenericParamList = nFieldList + 1 and
|
||||
nName = nGenericParamList + 1 and
|
||||
@@ -2916,7 +2912,7 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nAttr = nAttributeMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nAttributeMacroExpansion + e.getNumberOfAttrs() and
|
||||
nGenericParamList = nAttr + 1 and
|
||||
nName = nGenericParamList + 1 and
|
||||
nTypeRepr = nName + 1 and
|
||||
@@ -2963,10 +2959,8 @@ private module Impl {
|
||||
|
|
||||
n = 0 and
|
||||
nAttributeMacroExpansion = n + 1 and
|
||||
nDeriveMacroExpansion =
|
||||
nAttributeMacroExpansion + 1 +
|
||||
max(int i | i = -1 or exists(e.getDeriveMacroExpansion(i)) | i) and
|
||||
nAttr = nDeriveMacroExpansion + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nDeriveMacroExpansion = nAttributeMacroExpansion + e.getNumberOfDeriveMacroExpansions() and
|
||||
nAttr = nDeriveMacroExpansion + e.getNumberOfAttrs() and
|
||||
nGenericParamList = nAttr + 1 and
|
||||
nName = nGenericParamList + 1 and
|
||||
nStructFieldList = nName + 1 and
|
||||
@@ -3012,7 +3006,7 @@ private module Impl {
|
||||
n = 0 and
|
||||
nLabel = n + 1 and
|
||||
nLoopBody = nLabel + 1 and
|
||||
nAttr = nLoopBody + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
|
||||
nAttr = nLoopBody + e.getNumberOfAttrs() and
|
||||
nCondition = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
|
||||
3390
rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll
generated
3390
rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll
generated
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ private import codeql.rust.Concepts
|
||||
private class PoemHandlerParam extends RemoteSource::Range {
|
||||
PoemHandlerParam() {
|
||||
exists(TupleStructPat param |
|
||||
this.asPat().getPat() = param.getAField() and
|
||||
this.asPat() = param.getAField() and
|
||||
param.getStruct().getCanonicalPath() = ["poem::web::query::Query", "poem::web::path::Path"]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- ["<async_std::net::tcp::stream::TcpStream>::connect", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["<_ as async_std::io::read::ReadExt>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as async_std::io::read::ReadExt>::read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
7
rust/ql/lib/codeql/rust/frameworks/asyncstd/io.model.yml
Normal file
7
rust/ql/lib/codeql/rust/frameworks/asyncstd/io.model.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["<_ as async_std::io::read::ReadExt>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as async_std::io::read::ReadExt>::read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
@@ -0,0 +1,6 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- ["<async_std::net::tcp::stream::TcpStream>::connect", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"]
|
||||
22
rust/ql/lib/codeql/rust/frameworks/poem.model.yml
Normal file
22
rust/ql/lib/codeql/rust/frameworks/poem.model.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["<poem::web::cookie::CookieJar>::add", "Argument[0]", "cookie-use", "manual"]
|
||||
- ["<poem::web::cookie::SignedCookieJar>::add", "Argument[0]", "cookie-use", "manual"]
|
||||
- ["<poem::web::cookie::PrivateCookieJar>::add", "Argument[0]", "cookie-use", "manual"]
|
||||
- ["<poem::session::server_session::ServerSession>::new", "Argument[0]", "cookie-use", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["<poem::web::cookie::Cookie>::set_secure", "Argument[self].OptionalBarrier[cookie-secure-arg0]", "Argument[self]", "taint", "manual"]
|
||||
- ["<poem::session::cookie_config::CookieConfig>::secure", "Argument[self].OptionalBarrier[cookie-secure-arg0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<poem::session::cookie_config::CookieConfig>::partitioned", "Argument[self].OptionalBarrier[cookie-partitioned-arg0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<poem::session::cookie_config::CookieConfig>::name", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<poem::session::cookie_config::CookieConfig>::path", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<poem::session::cookie_config::CookieConfig>::domain", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<poem::session::cookie_config::CookieConfig>::http_only", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<poem::session::cookie_config::CookieConfig>::same_site", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<poem::session::cookie_config::CookieConfig>::max_age", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
@@ -25,7 +25,7 @@ class StreamCipherInit extends Cryptography::CryptographicOperation::Range {
|
||||
// a call to `cipher::KeyInit::new`, `cipher::KeyInit::new_from_slice`,
|
||||
// `cipher::KeyIvInit::new`, `cipher::KeyIvInit::new_from_slices`, `rc2::Rc2::new_with_eff_key_len` or similar.
|
||||
exists(CallExprBase ce, string rawAlgorithmName |
|
||||
ce = this.asExpr().getExpr() and
|
||||
ce = this.asExpr() and
|
||||
ce.getStaticTarget().(Function).getName().getText() =
|
||||
["new", "new_from_slice", "new_with_eff_key_len", "new_from_slices"] and
|
||||
// extract the algorithm name from the type of `ce` or its receiver.
|
||||
|
||||
@@ -136,3 +136,36 @@ class F32 extends FloatingPointTypeImpl {
|
||||
class F64 extends FloatingPointTypeImpl {
|
||||
F64() { this.getName() = "f64" }
|
||||
}
|
||||
|
||||
/** The builtin slice type `[T]`. */
|
||||
class SliceType extends BuiltinType {
|
||||
SliceType() { this.getName() = "Slice" }
|
||||
}
|
||||
|
||||
/** The builtin array type `[T; N]`. */
|
||||
class ArrayType extends BuiltinType {
|
||||
ArrayType() { this.getName() = "Array" }
|
||||
}
|
||||
|
||||
/** The builtin reference type `&T` or `&mut T`. */
|
||||
class RefType extends BuiltinType {
|
||||
RefType() { this.getName() = "Ref" }
|
||||
}
|
||||
|
||||
/** The builtin pointer type `*const T` or `*mut T`. */
|
||||
class PtrType extends BuiltinType {
|
||||
PtrType() { this.getName() = "Ptr" }
|
||||
}
|
||||
|
||||
/** A builtin tuple type `(T1, T2, ...)`. */
|
||||
class TupleType extends BuiltinType {
|
||||
TupleType() { this.getName().matches("Tuple%") }
|
||||
|
||||
/** Gets the arity of this tuple type. */
|
||||
int getArity() {
|
||||
not this.hasGenericParamList() and
|
||||
result = 0
|
||||
or
|
||||
result = this.getGenericParamList().getNumberOfGenericParams()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,20 +4,16 @@
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.Concepts
|
||||
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
|
||||
private import codeql.rust.controlflow.CfgNodes as CfgNodes
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.internal.PathResolution
|
||||
|
||||
/**
|
||||
* A call to the `starts_with` method on a `Path`.
|
||||
*/
|
||||
private class StartswithCall extends Path::SafeAccessCheck::Range, CfgNodes::MethodCallExprCfgNode {
|
||||
StartswithCall() {
|
||||
this.getMethodCallExpr().getStaticTarget().getCanonicalPath() = "<std::path::Path>::starts_with"
|
||||
}
|
||||
private class StartswithCall extends Path::SafeAccessCheck::Range, MethodCallExpr {
|
||||
StartswithCall() { this.getStaticTarget().getCanonicalPath() = "<std::path::Path>::starts_with" }
|
||||
|
||||
override predicate checks(Cfg::CfgNode e, boolean branch) {
|
||||
override predicate checks(Expr e, boolean branch) {
|
||||
e = this.getReceiver() and
|
||||
branch = true
|
||||
}
|
||||
|
||||
@@ -29,16 +29,25 @@ extensions:
|
||||
- ["<alloc::boxed::Box>::into_pin", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
# Fmt
|
||||
- ["alloc::fmt::format", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
# Layout
|
||||
- ["<core::alloc::layout::Layout>::from_size_align", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::from_size_align_unchecked", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::array", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::repeat", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::repeat", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::repeat_packed", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::repeat_packed", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::extend", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::extend", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::extend_packed", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::extend_packed", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::align_to", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::align_to", "Argument[self].Element", "ReturnValue.Field[0,1,2].Reference.Element", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::pad_to_align", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::size", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
# String
|
||||
- ["<core::str>::as_str", "Argument[self]", "ReturnValue", "value", "manual"]
|
||||
- ["<core::str>::as_bytes", "Argument[self]", "ReturnValue", "value", "manual"]
|
||||
- ["<alloc::string::String>::as_str", "Argument[self]", "ReturnValue", "value", "manual"]
|
||||
- ["<alloc::string::String>::as_bytes", "Argument[self]", "ReturnValue", "value", "manual"]
|
||||
- ["<_ as alloc::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<core::str>::parse", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::str>::trim", "Argument[self]", "ReturnValue.Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Add>::add", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
# Vec
|
||||
- ["alloc::vec::from_elem", "Argument[0]", "ReturnValue.Element", "value", "manual"]
|
||||
|
||||
@@ -3,10 +3,13 @@ extensions:
|
||||
pack: codeql/rust-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
# Arithmetic
|
||||
- ["<_ as core::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Add>::add", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
# Clone
|
||||
- ["<_ as core::clone::Clone>::clone", "Argument[self].Reference", "ReturnValue", "value", "manual"]
|
||||
# Conversions
|
||||
- ["<core::alloc::layout::Layout>::align_to", "Argument[self].Element", "ReturnValue.Field[0,1,2].Reference.Element", "taint", "manual"]
|
||||
- ["<_ as core::convert::Into>::into", "Argument[self].Element", "ReturnValue.Element", "taint", "manual"]
|
||||
- ["<_ as core::convert::Into>::into", "Argument[self].Reference.Element", "ReturnValue.Element", "taint", "manual"]
|
||||
# From
|
||||
@@ -23,21 +26,9 @@ extensions:
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
|
||||
# Layout
|
||||
- ["<core::alloc::layout::Layout>::from_size_align", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::from_size_align_unchecked", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::array", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::repeat", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::repeat", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::repeat_packed", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::repeat_packed", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::extend", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::extend", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::extend_packed", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::extend_packed", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::align_to", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::pad_to_align", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::size", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::chain", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::chain", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::take", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
# Pin
|
||||
- ["core::pin::Pin", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["<core::pin::Pin>::new", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
@@ -53,13 +44,11 @@ extensions:
|
||||
- ["core::ptr::write_unaligned", "Argument[1]", "Argument[0].Reference", "value", "manual"]
|
||||
- ["core::ptr::write_volatile", "Argument[1]", "Argument[0].Reference", "value", "manual"]
|
||||
# Str
|
||||
- ["<core::str>::as_str", "Argument[self]", "ReturnValue", "taint", "value"]
|
||||
- ["<alloc::string::String>::as_str", "Argument[self]", "ReturnValue", "taint", "value"]
|
||||
- ["<core::str>::as_bytes", "Argument[self]", "ReturnValue", "taint", "value"]
|
||||
- ["<alloc::string::String>::as_bytes", "Argument[self]", "ReturnValue", "taint", "value"]
|
||||
- ["<core::str>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<core::str>::as_str", "Argument[self]", "ReturnValue", "value", "manual"]
|
||||
- ["<core::str>::as_bytes", "Argument[self]", "ReturnValue", "value", "manual"]
|
||||
- ["<core::str>::parse", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::str>::trim", "Argument[self]", "ReturnValue.Reference", "taint", "manual"]
|
||||
- ["<core::str>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sourceModel
|
||||
|
||||
@@ -46,6 +46,3 @@ extensions:
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>:::read_f32_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_f64", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_f64_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::chain", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::chain", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::take", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
|
||||
@@ -90,24 +90,6 @@ private module UseOption = Option<Use>;
|
||||
|
||||
private class UseOption = UseOption::Option;
|
||||
|
||||
/**
|
||||
* Holds if `n` is superseded by an attribute macro expansion. That is, `n` is
|
||||
* an item or a transitive child of an item with an attribute macro expansion.
|
||||
*/
|
||||
predicate supersededByAttributeMacroExpansion(AstNode n) {
|
||||
n.(Item).hasAttributeMacroExpansion()
|
||||
or
|
||||
exists(AstNode parent |
|
||||
n.getParentNode() = parent and
|
||||
supersededByAttributeMacroExpansion(parent) and
|
||||
// Don't exclude expansions themselves as they supercede other nodes.
|
||||
not n = parent.(Item).getAttributeMacroExpansion() and
|
||||
// Don't consider attributes themselves to be superseded. E.g., in `#[a] fn
|
||||
// f() {}` the macro expansion supercedes `fn f() {}` but not `#[a]`.
|
||||
not n instanceof Attr
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An item that may be referred to by a path, and which is a node in
|
||||
* the _item graph_.
|
||||
@@ -186,10 +168,7 @@ predicate supersededByAttributeMacroExpansion(AstNode n) {
|
||||
* - https://doc.rust-lang.org/reference/names/namespaces.html
|
||||
*/
|
||||
abstract class ItemNode extends Locatable {
|
||||
ItemNode() {
|
||||
// Exclude items that are superseded by the expansion of an attribute macro.
|
||||
not supersededByAttributeMacroExpansion(this)
|
||||
}
|
||||
ItemNode() { not this.(Item).hasAttributeMacroExpansion() }
|
||||
|
||||
/** Gets the (original) name of this item. */
|
||||
abstract string getName();
|
||||
@@ -280,8 +259,7 @@ abstract class ItemNode extends Locatable {
|
||||
kind.isInternal() and
|
||||
useOpt.isNone()
|
||||
or
|
||||
externCrateEdge(this, name, result) and
|
||||
kind.isInternal() and
|
||||
externCrateEdge(this, name, kind, result) and
|
||||
useOpt.isNone()
|
||||
or
|
||||
macroExportEdge(this, name, result) and
|
||||
@@ -297,7 +275,7 @@ abstract class ItemNode extends Locatable {
|
||||
result = use_.getASuccessor(name, kind, _)
|
||||
)
|
||||
or
|
||||
exists(ExternCrateItemNode ec | result = ec.(ItemNode).getASuccessor(name, kind, useOpt) |
|
||||
exists(ExternCrateItemNode ec | result = ec.getASuccessor(name, kind, useOpt) |
|
||||
ec = this.getASuccessor(_, _, _)
|
||||
or
|
||||
// if the extern crate appears in the crate root, then the crate name is also added
|
||||
@@ -548,7 +526,7 @@ class ExternCrateItemNode extends ItemNode instanceof ExternCrate {
|
||||
|
||||
override Namespace getNamespace() { none() }
|
||||
|
||||
override Visibility getVisibility() { none() }
|
||||
override Visibility getVisibility() { result = ExternCrate.super.getVisibility() }
|
||||
|
||||
override Attr getAnAttr() { result = ExternCrate.super.getAnAttr() }
|
||||
|
||||
@@ -734,12 +712,34 @@ abstract class ImplOrTraitItemNode extends ItemNode {
|
||||
predicate hasAssocItem(string name) { name = this.getAnAssocItem().getName() }
|
||||
}
|
||||
|
||||
private TypeItemNode resolveBuiltin(TypeRepr tr) {
|
||||
tr instanceof SliceTypeRepr and
|
||||
result instanceof Builtins::SliceType
|
||||
or
|
||||
tr instanceof ArrayTypeRepr and
|
||||
result instanceof Builtins::ArrayType
|
||||
or
|
||||
tr instanceof RefTypeRepr and
|
||||
result instanceof Builtins::RefType
|
||||
or
|
||||
tr instanceof PtrTypeRepr and
|
||||
result instanceof Builtins::PtrType
|
||||
or
|
||||
result.(Builtins::TupleType).getArity() = tr.(TupleTypeRepr).getNumberOfFields()
|
||||
}
|
||||
|
||||
final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
|
||||
Path getSelfPath() { result = super.getSelfTy().(PathTypeRepr).getPath() }
|
||||
|
||||
Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() }
|
||||
|
||||
TypeItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
|
||||
TypeItemNode resolveSelfTyBuiltin() { result = resolveBuiltin(this.(Impl).getSelfTy()) }
|
||||
|
||||
TypeItemNode resolveSelfTy() {
|
||||
result = resolvePath(this.getSelfPath())
|
||||
or
|
||||
result = this.resolveSelfTyBuiltin()
|
||||
}
|
||||
|
||||
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
|
||||
|
||||
@@ -914,7 +914,11 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module {
|
||||
}
|
||||
|
||||
private class ImplItemNodeImpl extends ImplItemNode {
|
||||
TypeItemNode resolveSelfTyCand() { result = resolvePathCand(this.getSelfPath()) }
|
||||
TypeItemNode resolveSelfTyCand() {
|
||||
result = resolvePathCand(this.getSelfPath())
|
||||
or
|
||||
result = this.resolveSelfTyBuiltin()
|
||||
}
|
||||
|
||||
TraitItemNode resolveTraitTyCand() { result = resolvePathCand(this.getTraitPath()) }
|
||||
}
|
||||
@@ -1457,6 +1461,24 @@ private predicate crateDependencyEdge(SourceFileItemNode file, string name, Crat
|
||||
not hasDeclOrDep(file, name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a `UseTree` that is nested under `tree`, and which needs to be resolved
|
||||
* relative to the path of `tree`.
|
||||
*
|
||||
* `tree` is restricted to either having a path or being a direct child of some
|
||||
* `use` statement without a path.
|
||||
*/
|
||||
private UseTree getAUseTreeUseTree(UseTree tree) {
|
||||
result = tree.getUseTreeList().getAUseTree() and
|
||||
(if tree.hasPath() then any() else tree = any(Use u).getUseTree())
|
||||
or
|
||||
exists(UseTree mid |
|
||||
mid = getAUseTreeUseTree(tree) and
|
||||
not mid.hasPath() and
|
||||
result = mid.getUseTreeList().getAUseTree()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate useTreeDeclares(UseTree tree, string name) {
|
||||
not tree.isGlob() and
|
||||
not exists(tree.getUseTreeList()) and
|
||||
@@ -1470,7 +1492,7 @@ private predicate useTreeDeclares(UseTree tree, string name) {
|
||||
or
|
||||
exists(UseTree mid |
|
||||
useTreeDeclares(mid, name) and
|
||||
mid = tree.getUseTreeList().getAUseTree()
|
||||
mid = getAUseTreeUseTree(tree)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1511,7 +1533,10 @@ class RelevantPath extends Path {
|
||||
pragma[nomagic]
|
||||
predicate isUnqualified(string name) {
|
||||
not exists(this.getQualifier()) and
|
||||
not this = any(UseTreeList list).getAUseTree().getPath().getQualifier*() and
|
||||
not exists(UseTree tree |
|
||||
tree.hasPath() and
|
||||
this = getAUseTreeUseTree(tree).getPath().getQualifier*()
|
||||
) and
|
||||
name = this.getText()
|
||||
}
|
||||
|
||||
@@ -1764,6 +1789,10 @@ private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) {
|
||||
or
|
||||
result = resolveUseTreeListItem(_, _, path, _) and
|
||||
ns = result.getNamespace()
|
||||
or
|
||||
result = resolveBuiltin(path.getSegment().getTypeRepr()) and
|
||||
not path.getSegment().hasTraitTypeRepr() and
|
||||
ns.isType()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1990,7 +2019,7 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path
|
||||
exists(UseOption useOpt | checkQualifiedVisibility(use, result, kind, useOpt) |
|
||||
exists(UseTree midTree, ItemNode mid, string name |
|
||||
mid = resolveUseTreeListItem(use, midTree) and
|
||||
tree = midTree.getUseTreeList().getAUseTree() and
|
||||
tree = getAUseTreeUseTree(midTree) and
|
||||
isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and
|
||||
result = mid.getASuccessor(pragma[only_bind_into](name), kind, useOpt)
|
||||
)
|
||||
@@ -2010,14 +2039,28 @@ private ItemNode resolveUseTreeListItemQualifier(
|
||||
name = path.getText()
|
||||
}
|
||||
|
||||
private UseTree getAUseUseTree(Use use) {
|
||||
exists(UseTree root | root = use.getUseTree() |
|
||||
if root.hasPath() then result = root else result = getAUseTreeUseTree(root)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ItemNode resolveUseTreeListItem(Use use, UseTree tree) {
|
||||
exists(Path path | path = tree.getPath() |
|
||||
tree = use.getUseTree() and
|
||||
tree = getAUseUseTree(use) and
|
||||
result = resolvePathCand(path)
|
||||
or
|
||||
result = resolveUseTreeListItem(use, tree, path, _)
|
||||
)
|
||||
or
|
||||
exists(UseTree midTree |
|
||||
// `use foo::{bar, *}`; midTree = `foo` and tree = `*`
|
||||
result = resolveUseTreeListItem(use, midTree) and
|
||||
tree = getAUseTreeUseTree(midTree) and
|
||||
tree.isGlob() and
|
||||
not tree.hasPath()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `use` imports `item` as `name`. */
|
||||
@@ -2063,8 +2106,11 @@ private predicate useImportEdge(Use use, string name, ItemNode item, SuccessorKi
|
||||
|
||||
/** Holds if `ec` imports `crate` as `name`. */
|
||||
pragma[nomagic]
|
||||
private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItemNode crate) {
|
||||
private predicate externCrateEdge(
|
||||
ExternCrateItemNode ec, string name, SuccessorKind kind, CrateItemNode crate
|
||||
) {
|
||||
name = ec.getName() and
|
||||
(if ec.isPublic() then kind.isBoth() else kind.isInternal()) and
|
||||
exists(SourceFile f, string s |
|
||||
ec.getFile() = f.getFile() and
|
||||
s = ec.(ExternCrate).getIdentifier().getText()
|
||||
@@ -2127,7 +2173,8 @@ pragma[nomagic]
|
||||
private predicate builtin(string name, ItemNode i) {
|
||||
exists(BuiltinSourceFile builtins |
|
||||
builtins.getFile().getBaseName() = "types.rs" and
|
||||
i = builtins.getASuccessor(name)
|
||||
i = builtins.getASuccessor(name) and
|
||||
i.isPublic()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2159,6 +2206,16 @@ private module Debug {
|
||||
result = resolvePath(path)
|
||||
}
|
||||
|
||||
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) {
|
||||
use = getRelevantLocatable() and
|
||||
result = resolveUseTreeListItem(use, tree, path, kind)
|
||||
}
|
||||
|
||||
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree) {
|
||||
use = getRelevantLocatable() and
|
||||
result = resolveUseTreeListItem(use, tree)
|
||||
}
|
||||
|
||||
predicate debugUseImportEdge(Use use, string name, ItemNode item, SuccessorKind kind) {
|
||||
use = getRelevantLocatable() and
|
||||
useImportEdge(use, name, item, kind)
|
||||
|
||||
@@ -7,6 +7,7 @@ private import codeql.rust.internal.CachedStages
|
||||
private import codeql.rust.elements.internal.generated.Raw
|
||||
private import codeql.rust.elements.internal.generated.Synth
|
||||
private import codeql.rust.frameworks.stdlib.Stdlib
|
||||
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
|
||||
|
||||
/**
|
||||
* Holds if a dyn trait type should have a type parameter associated with `n`. A
|
||||
@@ -31,38 +32,21 @@ private predicate dynTraitTypeParameter(Trait trait, AstNode n) {
|
||||
|
||||
cached
|
||||
newtype TType =
|
||||
TTuple(int arity) {
|
||||
arity =
|
||||
[
|
||||
any(TupleTypeRepr t).getNumberOfFields(),
|
||||
any(TupleExpr e).getNumberOfFields(),
|
||||
any(TuplePat p).getNumberOfFields()
|
||||
] and
|
||||
Stages::TypeInferenceStage::ref()
|
||||
} or
|
||||
TStruct(Struct s) or
|
||||
TStruct(Struct s) { Stages::TypeInferenceStage::ref() } or
|
||||
TEnum(Enum e) or
|
||||
TTrait(Trait t) or
|
||||
TUnion(Union u) or
|
||||
TArrayType() or // todo: add size?
|
||||
TRefType() or // todo: add mut?
|
||||
TImplTraitType(ImplTraitTypeRepr impl) or
|
||||
TDynTraitType(Trait t) { t = any(DynTraitTypeRepr dt).getTrait() } or
|
||||
TSliceType() or
|
||||
TNeverType() or
|
||||
TPtrType() or
|
||||
TTupleTypeParameter(int arity, int i) { exists(TTuple(arity)) and i in [0 .. arity - 1] } or
|
||||
TUnknownType() or
|
||||
TTypeParamTypeParameter(TypeParam t) or
|
||||
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
|
||||
TArrayTypeParameter() or
|
||||
TDynTraitTypeParameter(AstNode n) { dynTraitTypeParameter(_, n) } or
|
||||
TImplTraitTypeParameter(ImplTraitTypeRepr implTrait, TypeParam tp) {
|
||||
implTraitTypeParam(implTrait, _, tp)
|
||||
} or
|
||||
TRefTypeParameter() or
|
||||
TSelfTypeParameter(Trait t) or
|
||||
TSliceTypeParameter() or
|
||||
TPtrTypeParameter()
|
||||
TSelfTypeParameter(Trait t)
|
||||
|
||||
private predicate implTraitTypeParam(ImplTraitTypeRepr implTrait, int i, TypeParam tp) {
|
||||
implTrait.isInReturnPos() and
|
||||
@@ -105,26 +89,25 @@ abstract class Type extends TType {
|
||||
}
|
||||
|
||||
/** A tuple type `(T, ...)`. */
|
||||
class TupleType extends Type, TTuple {
|
||||
class TupleType extends StructType {
|
||||
private int arity;
|
||||
|
||||
TupleType() { this = TTuple(arity) }
|
||||
|
||||
override TypeParameter getPositionalTypeParameter(int i) {
|
||||
result = TTupleTypeParameter(arity, i)
|
||||
}
|
||||
TupleType() { arity = this.getStruct().(Builtins::TupleType).getArity() }
|
||||
|
||||
/** Gets the arity of this tuple type. */
|
||||
int getArity() { result = arity }
|
||||
|
||||
override string toString() { result = "(T_" + arity + ")" }
|
||||
}
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
pragma[nomagic]
|
||||
TypeParamTypeParameter getTupleTypeParameter(int arity, int i) {
|
||||
result = any(TupleType t | t.getArity() = arity).getPositionalTypeParameter(i)
|
||||
}
|
||||
|
||||
/** The unit type `()`. */
|
||||
class UnitType extends TupleType {
|
||||
UnitType() { this = TTuple(0) }
|
||||
UnitType() { this.getArity() = 0 }
|
||||
|
||||
override string toString() { result = "()" }
|
||||
}
|
||||
@@ -225,20 +208,17 @@ class UnionType extends Type, TUnion {
|
||||
/**
|
||||
* An array type.
|
||||
*
|
||||
* Array types like `[i64; 5]` are modeled as normal generic types
|
||||
* with a single type argument.
|
||||
* Array types like `[i64; 5]` are modeled as normal generic types.
|
||||
*/
|
||||
class ArrayType extends Type, TArrayType {
|
||||
ArrayType() { this = TArrayType() }
|
||||
class ArrayType extends StructType {
|
||||
ArrayType() { this.getStruct() instanceof Builtins::ArrayType }
|
||||
|
||||
override TypeParameter getPositionalTypeParameter(int i) {
|
||||
result = TArrayTypeParameter() and
|
||||
i = 0
|
||||
}
|
||||
override string toString() { result = "[;]" }
|
||||
}
|
||||
|
||||
override string toString() { result = "[]" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
pragma[nomagic]
|
||||
TypeParamTypeParameter getArrayTypeParameter() {
|
||||
result = any(ArrayType t).getPositionalTypeParameter(0)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,17 +227,15 @@ class ArrayType extends Type, TArrayType {
|
||||
* Reference types like `& i64` are modeled as normal generic types
|
||||
* with a single type argument.
|
||||
*/
|
||||
class RefType extends Type, TRefType {
|
||||
RefType() { this = TRefType() }
|
||||
|
||||
override TypeParameter getPositionalTypeParameter(int i) {
|
||||
result = TRefTypeParameter() and
|
||||
i = 0
|
||||
}
|
||||
class RefType extends StructType {
|
||||
RefType() { this.getStruct() instanceof Builtins::RefType }
|
||||
|
||||
override string toString() { result = "&" }
|
||||
}
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
pragma[nomagic]
|
||||
TypeParamTypeParameter getRefTypeParameter() {
|
||||
result = any(RefType t).getPositionalTypeParameter(0)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -339,17 +317,15 @@ class ImplTraitReturnType extends ImplTraitType {
|
||||
* Slice types like `[i64]` are modeled as normal generic types
|
||||
* with a single type argument.
|
||||
*/
|
||||
class SliceType extends Type, TSliceType {
|
||||
SliceType() { this = TSliceType() }
|
||||
|
||||
override TypeParameter getPositionalTypeParameter(int i) {
|
||||
result = TSliceTypeParameter() and
|
||||
i = 0
|
||||
}
|
||||
class SliceType extends StructType {
|
||||
SliceType() { this.getStruct() instanceof Builtins::SliceType }
|
||||
|
||||
override string toString() { result = "[]" }
|
||||
}
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
pragma[nomagic]
|
||||
TypeParamTypeParameter getSliceTypeParameter() {
|
||||
result = any(SliceType t).getPositionalTypeParameter(0)
|
||||
}
|
||||
|
||||
class NeverType extends Type, TNeverType {
|
||||
@@ -360,17 +336,49 @@ class NeverType extends Type, TNeverType {
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
class PtrType extends Type, TPtrType {
|
||||
override TypeParameter getPositionalTypeParameter(int i) {
|
||||
i = 0 and
|
||||
result = TPtrTypeParameter()
|
||||
}
|
||||
class PtrType extends StructType {
|
||||
PtrType() { this.getStruct() instanceof Builtins::PtrType }
|
||||
|
||||
override string toString() { result = "*" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/**
|
||||
* A special pseudo type used to indicate that the actual type may have to be
|
||||
* inferred by propagating type information back into call arguments.
|
||||
*
|
||||
* For example, in
|
||||
*
|
||||
* ```rust
|
||||
* let x = Default::default();
|
||||
* foo(x);
|
||||
* ```
|
||||
*
|
||||
* `Default::default()` is assigned this type, which allows us to infer the actual
|
||||
* type from the type of `foo`'s first parameter.
|
||||
*
|
||||
* Unknown types are not restricted to root types, for example in a call like
|
||||
* `Vec::new()` we assign this type at the type path corresponding to the type
|
||||
* parameter of `Vec`.
|
||||
*
|
||||
* Unknown types are used to restrict when type information is allowed to flow
|
||||
* into call arguments (including method call receivers), in order to avoid
|
||||
* combinatorial explosions.
|
||||
*/
|
||||
class UnknownType extends Type, TUnknownType {
|
||||
override TypeParameter getPositionalTypeParameter(int i) { none() }
|
||||
|
||||
override string toString() { result = "(context typed)" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
TypeParamTypeParameter getPtrTypeParameter() {
|
||||
result = any(PtrType t).getPositionalTypeParameter(0)
|
||||
}
|
||||
|
||||
/** A type parameter. */
|
||||
abstract class TypeParameter extends Type {
|
||||
override TypeParameter getPositionalTypeParameter(int i) { none() }
|
||||
@@ -430,37 +438,6 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara
|
||||
override Location getLocation() { result = typeAlias.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A tuple type parameter. For instance the `T` in `(T, U)`.
|
||||
*
|
||||
* Since tuples are structural their type parameters can be represented as their
|
||||
* positional index. The type inference library requires that type parameters
|
||||
* belong to a single type, so we also include the arity of the tuple type.
|
||||
*/
|
||||
class TupleTypeParameter extends TypeParameter, TTupleTypeParameter {
|
||||
private int arity;
|
||||
private int index;
|
||||
|
||||
TupleTypeParameter() { this = TTupleTypeParameter(arity, index) }
|
||||
|
||||
override string toString() { result = index.toString() + "(" + arity + ")" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
|
||||
/** Gets the index of this tuple type parameter. */
|
||||
int getIndex() { result = index }
|
||||
|
||||
/** Gets the tuple type that corresponds to this tuple type parameter. */
|
||||
TupleType getTupleType() { result = TTuple(arity) }
|
||||
}
|
||||
|
||||
/** An implicit array type parameter. */
|
||||
class ArrayTypeParameter extends TypeParameter, TArrayTypeParameter {
|
||||
override string toString() { result = "[T;...]" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
class DynTraitTypeParameter extends TypeParameter, TDynTraitTypeParameter {
|
||||
private AstNode n;
|
||||
|
||||
@@ -508,26 +485,6 @@ class ImplTraitTypeParameter extends TypeParameter, TImplTraitTypeParameter {
|
||||
override Location getLocation() { result = typeParam.getLocation() }
|
||||
}
|
||||
|
||||
/** An implicit reference type parameter. */
|
||||
class RefTypeParameter extends TypeParameter, TRefTypeParameter {
|
||||
override string toString() { result = "&T" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/** An implicit slice type parameter. */
|
||||
class SliceTypeParameter extends TypeParameter, TSliceTypeParameter {
|
||||
override string toString() { result = "[T]" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
class PtrTypeParameter extends TypeParameter, TPtrTypeParameter {
|
||||
override string toString() { result = "*T" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/**
|
||||
* The implicit `Self` type parameter of a trait, that refers to the
|
||||
* implementing type of the trait.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,11 +20,11 @@ abstract class TypeMention extends AstNode {
|
||||
class TupleTypeReprMention extends TypeMention instanceof TupleTypeRepr {
|
||||
override Type resolveTypeAt(TypePath path) {
|
||||
path.isEmpty() and
|
||||
result = TTuple(super.getNumberOfFields())
|
||||
result.(TupleType).getArity() = super.getNumberOfFields()
|
||||
or
|
||||
exists(TypePath suffix, int i |
|
||||
result = super.getField(i).(TypeMention).resolveTypeAt(suffix) and
|
||||
path = TypePath::cons(TTupleTypeParameter(super.getNumberOfFields(), i), suffix)
|
||||
path = TypePath::cons(getTupleTypeParameter(super.getNumberOfFields(), i), suffix)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -32,11 +32,11 @@ class TupleTypeReprMention extends TypeMention instanceof TupleTypeRepr {
|
||||
class ParenthesizedArgListMention extends TypeMention instanceof ParenthesizedArgList {
|
||||
override Type resolveTypeAt(TypePath path) {
|
||||
path.isEmpty() and
|
||||
result = TTuple(super.getNumberOfTypeArgs())
|
||||
result.(TupleType).getArity() = super.getNumberOfTypeArgs()
|
||||
or
|
||||
exists(TypePath suffix, int index |
|
||||
result = super.getTypeArg(index).getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
|
||||
path = TypePath::cons(TTupleTypeParameter(super.getNumberOfTypeArgs(), index), suffix)
|
||||
path = TypePath::cons(getTupleTypeParameter(super.getNumberOfTypeArgs(), index), suffix)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -44,11 +44,11 @@ class ParenthesizedArgListMention extends TypeMention instanceof ParenthesizedAr
|
||||
class ArrayTypeReprMention extends TypeMention instanceof ArrayTypeRepr {
|
||||
override Type resolveTypeAt(TypePath path) {
|
||||
path.isEmpty() and
|
||||
result = TArrayType()
|
||||
result instanceof ArrayType
|
||||
or
|
||||
exists(TypePath suffix |
|
||||
result = super.getElementTypeRepr().(TypeMention).resolveTypeAt(suffix) and
|
||||
path = TypePath::cons(TArrayTypeParameter(), suffix)
|
||||
path = TypePath::cons(getArrayTypeParameter(), suffix)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -56,11 +56,11 @@ class ArrayTypeReprMention extends TypeMention instanceof ArrayTypeRepr {
|
||||
class RefTypeReprMention extends TypeMention instanceof RefTypeRepr {
|
||||
override Type resolveTypeAt(TypePath path) {
|
||||
path.isEmpty() and
|
||||
result = TRefType()
|
||||
result instanceof RefType
|
||||
or
|
||||
exists(TypePath suffix |
|
||||
result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
|
||||
path = TypePath::cons(TRefTypeParameter(), suffix)
|
||||
path = TypePath::cons(getRefTypeParameter(), suffix)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -68,11 +68,11 @@ class RefTypeReprMention extends TypeMention instanceof RefTypeRepr {
|
||||
class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr {
|
||||
override Type resolveTypeAt(TypePath path) {
|
||||
path.isEmpty() and
|
||||
result = TSliceType()
|
||||
result instanceof SliceType
|
||||
or
|
||||
exists(TypePath suffix |
|
||||
result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
|
||||
path = TypePath::cons(TSliceTypeParameter(), suffix)
|
||||
path = TypePath::cons(getSliceTypeParameter(), suffix)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,20 @@ class AliasPathTypeMention extends PathTypeMention {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `i`th type argument of `p`.
|
||||
*
|
||||
* Takes into account that variants can have type arguments applied to both the
|
||||
* enum and the variant itself, e.g. `Option::<i32>::Some` is valid in addition
|
||||
* to `Option::Some::<i32>`.
|
||||
*/
|
||||
TypeMention getPathTypeArgument(Path p, int i) {
|
||||
result = p.getSegment().getGenericArgList().getTypeArg(i)
|
||||
or
|
||||
resolvePath(p) instanceof Variant and
|
||||
result = p.getQualifier().getSegment().getGenericArgList().getTypeArg(i)
|
||||
}
|
||||
|
||||
class NonAliasPathTypeMention extends PathTypeMention {
|
||||
TypeItemNode resolved;
|
||||
|
||||
@@ -143,18 +157,6 @@ class NonAliasPathTypeMention extends PathTypeMention {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the positional type argument at index `i` that occurs in this path, if
|
||||
* any.
|
||||
*/
|
||||
private TypeMention getPathPositionalTypeArgument(int i) {
|
||||
result = this.getSegment().getGenericArgList().getTypeArg(i)
|
||||
or
|
||||
// `Option::<i32>::Some` is valid in addition to `Option::Some::<i32>`
|
||||
resolvePath(this) instanceof Variant and
|
||||
result = this.getQualifier().getSegment().getGenericArgList().getTypeArg(i)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type mention that instantiates the implicit `Self` type parameter
|
||||
* for this path, if it occurs in the position of a trait bound.
|
||||
@@ -173,7 +175,7 @@ class NonAliasPathTypeMention extends PathTypeMention {
|
||||
private Type getDefaultPositionalTypeArgument(int i, TypePath path) {
|
||||
// If a type argument is not given in the path, then we use the default for
|
||||
// the type parameter if one exists for the type.
|
||||
not exists(this.getPathPositionalTypeArgument(i)) and
|
||||
not exists(getPathTypeArgument(this, i)) and
|
||||
// Defaults only apply to type mentions in type annotations
|
||||
this = any(PathTypeRepr ptp).getPath().getQualifier*() and
|
||||
exists(Type ty, TypePath prefix |
|
||||
@@ -191,7 +193,7 @@ class NonAliasPathTypeMention extends PathTypeMention {
|
||||
}
|
||||
|
||||
private Type getPositionalTypeArgument(int i, TypePath path) {
|
||||
result = this.getPathPositionalTypeArgument(i).resolveTypeAt(path)
|
||||
result = getPathTypeArgument(this, i).resolveTypeAt(path)
|
||||
or
|
||||
result = this.getDefaultPositionalTypeArgument(i, path)
|
||||
}
|
||||
@@ -207,6 +209,11 @@ class NonAliasPathTypeMention extends PathTypeMention {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private TypeAlias getResolvedAlias(string name) {
|
||||
result = resolved.(TraitItemNode).getAssocItem(name)
|
||||
}
|
||||
|
||||
/** Gets the type mention in this path for the type parameter `tp`, if any. */
|
||||
pragma[nomagic]
|
||||
private TypeMention getTypeMentionForTypeParameter(TypeParameter tp) {
|
||||
@@ -228,16 +235,11 @@ class NonAliasPathTypeMention extends PathTypeMention {
|
||||
// }
|
||||
// ```
|
||||
// the rhs. of the type alias is a type argument to the trait.
|
||||
exists(ImplItemNode impl, AssociatedTypeTypeParameter param, TypeAlias alias, string name |
|
||||
exists(ImplItemNode impl, TypeAlias alias, string name |
|
||||
this = impl.getTraitPath() and
|
||||
param.getTrait() = resolved and
|
||||
name = param.getTypeAlias().getName().getText() and
|
||||
alias = impl.getASuccessor(pragma[only_bind_into](name)) and
|
||||
result = alias.getTypeRepr() and
|
||||
tp =
|
||||
TAssociatedTypeTypeParameter(resolved
|
||||
.(TraitItemNode)
|
||||
.getAssocItem(pragma[only_bind_into](name)))
|
||||
tp = TAssociatedTypeTypeParameter(this.getResolvedAlias(pragma[only_bind_into](name)))
|
||||
)
|
||||
or
|
||||
// Handle the special syntactic sugar for function traits. For now we only
|
||||
@@ -289,6 +291,9 @@ class NonAliasPathTypeMention extends PathTypeMention {
|
||||
result = this.getSelfTraitBoundArg().resolveTypeAt(suffix) and
|
||||
typePath = TypePath::cons(TSelfTypeParameter(resolved), suffix)
|
||||
)
|
||||
or
|
||||
not this.getSegment().hasTraitTypeRepr() and
|
||||
result = this.getSegment().getTypeRepr().(TypeMention).resolveTypeAt(typePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,11 +429,11 @@ class ShorthandSelfParameterMention extends TypeMention instanceof SelfParam {
|
||||
then
|
||||
// `fn f(&self, ...)`
|
||||
typePath.isEmpty() and
|
||||
result = TRefType()
|
||||
result instanceof RefType
|
||||
or
|
||||
exists(TypePath suffix |
|
||||
result = this.resolveSelfType(suffix) and
|
||||
typePath = TypePath::cons(TRefTypeParameter(), suffix)
|
||||
typePath = TypePath::cons(getRefTypeParameter(), suffix)
|
||||
)
|
||||
else
|
||||
// `fn f(self, ...)`
|
||||
@@ -539,11 +544,11 @@ class NeverTypeReprMention extends TypeMention, NeverTypeRepr {
|
||||
class PtrTypeReprMention extends TypeMention instanceof PtrTypeRepr {
|
||||
override Type resolveTypeAt(TypePath path) {
|
||||
path.isEmpty() and
|
||||
result = TPtrType()
|
||||
result instanceof PtrType
|
||||
or
|
||||
exists(TypePath suffix |
|
||||
result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
|
||||
path = TypePath::cons(TPtrTypeParameter(), suffix)
|
||||
path = TypePath::cons(getPtrTypeParameter(), suffix)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,8 @@ module SatisfiesBlanketConstraint<
|
||||
|
||||
Type getTypeAt(TypePath path) {
|
||||
result = at.getTypeAt(blanketPath.appendInverse(path)) and
|
||||
not result = TNeverType()
|
||||
not result = TNeverType() and
|
||||
not result = TUnknownType()
|
||||
}
|
||||
|
||||
string toString() { result = at.toString() + " [blanket at " + blanketPath.toString() + "]" }
|
||||
|
||||
@@ -72,16 +72,24 @@ module FunctionPositionMatchingInput {
|
||||
}
|
||||
|
||||
private newtype TAssocFunctionType =
|
||||
/** An associated function `f` that should be specialized for `i` at `pos`. */
|
||||
MkAssocFunctionType(Function f, ImplOrTraitItemNode i, FunctionPosition pos) {
|
||||
f = i.getASuccessor(_) and exists(pos.getTypeMention(f))
|
||||
/** An associated function `f` in `parent` should be specialized for `i` at `pos`. */
|
||||
MkAssocFunctionType(
|
||||
ImplOrTraitItemNode parent, Function f, ImplOrTraitItemNode i, FunctionPosition pos
|
||||
) {
|
||||
parent.getAnAssocItem() = f and
|
||||
i.getASuccessor(_) = f and
|
||||
// When `f` is not directly in `i`, the `parent` should be satisfiable
|
||||
// through `i`. This ensures that `parent` is either a supertrait of `i` or
|
||||
// `i` in an `impl` block implementing `parent`.
|
||||
(parent = i or BaseTypes::rootTypesSatisfaction(_, TTrait(parent), i, _, _)) and
|
||||
exists(pos.getTypeMention(f))
|
||||
}
|
||||
|
||||
bindingset[condition, constraint, tp]
|
||||
bindingset[abs, constraint, tp]
|
||||
private Type getTraitConstraintTypeAt(
|
||||
TypeMention condition, TypeMention constraint, TypeParameter tp, TypePath path
|
||||
TypeAbstraction abs, TypeMention constraint, TypeParameter tp, TypePath path
|
||||
) {
|
||||
BaseTypes::conditionSatisfiesConstraintTypeAt(_, condition, constraint,
|
||||
BaseTypes::conditionSatisfiesConstraintTypeAt(abs, _, constraint,
|
||||
TypePath::singleton(tp).appendInverse(path), result)
|
||||
}
|
||||
|
||||
@@ -91,28 +99,19 @@ private Type getTraitConstraintTypeAt(
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Type getAssocFunctionTypeAt(Function f, ImplOrTraitItemNode i, FunctionPosition pos, TypePath path) {
|
||||
exists(MkAssocFunctionType(f, i, pos)) and
|
||||
(
|
||||
exists(ImplOrTraitItemNode parent | exists(MkAssocFunctionType(parent, f, i, pos)) |
|
||||
// No specialization needed when the function is directly in the trait or
|
||||
// impl block or the declared type is not a type parameter
|
||||
(i.getAnAssocItem() = f or not result instanceof TypeParameter) and
|
||||
(parent = i or not result instanceof TypeParameter) and
|
||||
result = pos.getTypeMention(f).resolveTypeAt(path)
|
||||
or
|
||||
not i.getAnAssocItem() = f and
|
||||
exists(TypePath prefix, TypePath suffix, TypeParameter tp |
|
||||
exists(TypePath prefix, TypePath suffix, TypeParameter tp, TypeMention constraint |
|
||||
BaseTypes::rootTypesSatisfaction(_, TTrait(parent), i, _, constraint) and
|
||||
path = prefix.append(suffix) and
|
||||
tp = pos.getTypeMention(f).resolveTypeAt(prefix)
|
||||
|
|
||||
tp = pos.getTypeMention(f).resolveTypeAt(prefix) and
|
||||
if tp = TSelfTypeParameter(_)
|
||||
then result = resolveImplOrTraitType(i, suffix)
|
||||
else
|
||||
exists(TraitItemNode trait, TypeMention condition, TypeMention constraint |
|
||||
trait.getAnAssocItem() = f and
|
||||
BaseTypes::rootTypesSatisfaction(_, TTrait(trait), _, condition, constraint) and
|
||||
result = getTraitConstraintTypeAt(condition, constraint, tp, suffix)
|
||||
|
|
||||
condition = i.(Trait) or condition = i.(Impl).getSelfTy()
|
||||
)
|
||||
else result = getTraitConstraintTypeAt(i, constraint, tp, suffix)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -125,32 +124,34 @@ Type getAssocFunctionTypeAt(Function f, ImplOrTraitItemNode i, FunctionPosition
|
||||
*
|
||||
* ```rust
|
||||
* trait T1 {
|
||||
* fn m1(self); // self1
|
||||
* fn m1(self); // T1::m1
|
||||
*
|
||||
* fn m2(self) { ... } // self2
|
||||
* fn m2(self) { ... } // T1::m2
|
||||
* }
|
||||
*
|
||||
* trait T2 : T1 {
|
||||
* fn m3(self); // self3
|
||||
* fn m3(self); // T2::m3
|
||||
* }
|
||||
*
|
||||
* impl T1 for X {
|
||||
* fn m1(self) { ... } // X::m1
|
||||
* }
|
||||
*
|
||||
* impl T2 for X {
|
||||
* fn m1(self) { ... } // self4
|
||||
*
|
||||
* fn m3(self) { ... } // self5
|
||||
* fn m3(self) { ... } // X::m3
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* param | `impl` or trait | type
|
||||
* ------- | --------------- | ----
|
||||
* `self1` | `trait T1` | `T1`
|
||||
* `self1` | `trait T2` | `T2`
|
||||
* `self2` | `trait T1` | `T1`
|
||||
* `self2` | `trait T2` | `T2`
|
||||
* `self2` | `impl T2 for X` | `X`
|
||||
* `self3` | `trait T2` | `T2`
|
||||
* `self4` | `impl T2 for X` | `X`
|
||||
* `self5` | `impl T2 for X` | `X`
|
||||
* f | `impl` or trait | pos | type
|
||||
* -------- | --------------- | ------ | ----
|
||||
* `T1::m1` | `trait T1` | `self` | `T1`
|
||||
* `T1::m1` | `trait T2` | `self` | `T2`
|
||||
* `T1::m2` | `trait T1` | `self` | `T1`
|
||||
* `T1::m2` | `trait T2` | `self` | `T2`
|
||||
* `T1::m2` | `impl T1 for X` | `self` | `X`
|
||||
* `T2::m3` | `trait T2` | `self` | `T2`
|
||||
* `X::m1` | `impl T1 for X` | `self` | `X`
|
||||
* `X::m3` | `impl T2 for X` | `self` | `X`
|
||||
*/
|
||||
class AssocFunctionType extends MkAssocFunctionType {
|
||||
/**
|
||||
@@ -158,7 +159,7 @@ class AssocFunctionType extends MkAssocFunctionType {
|
||||
* when viewed as a member of the `impl` or trait item `i`.
|
||||
*/
|
||||
predicate appliesTo(Function f, ImplOrTraitItemNode i, FunctionPosition pos) {
|
||||
this = MkAssocFunctionType(f, i, pos)
|
||||
this = MkAssocFunctionType(_, f, i, pos)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,7 +230,8 @@ module ArgIsInstantiationOf<
|
||||
private class ArgSubst extends ArgFinal {
|
||||
Type getTypeAt(TypePath path) {
|
||||
result = substituteLookupTraits(super.getTypeAt(path)) and
|
||||
not result = TNeverType()
|
||||
not result = TNeverType() and
|
||||
not result = TUnknownType()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,14 @@ module AccessAfterLifetime {
|
||||
*/
|
||||
abstract class Barrier extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* Holds if the value pointed to by `source` accesses a variable `target` with scope `scope`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate sourceValueScope(Source source, Variable target, BlockExpr scope) {
|
||||
valueScope(source.getTarget(), target, scope)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the pair `(source, sink)`, that represents a flow from a
|
||||
* pointer or reference to a dereference, has its dereference outside the
|
||||
@@ -47,8 +55,8 @@ module AccessAfterLifetime {
|
||||
bindingset[source, sink]
|
||||
predicate dereferenceAfterLifetime(Source source, Sink sink, Variable target) {
|
||||
exists(BlockExpr valueScope, BlockExpr accessScope |
|
||||
valueScope(source.getTarget(), target, valueScope) and
|
||||
accessScope = sink.asExpr().getExpr().getEnclosingBlock() and
|
||||
sourceValueScope(source, target, valueScope) and
|
||||
accessScope = sink.asExpr().getEnclosingBlock() and
|
||||
not mayEncloseOnStack(valueScope, accessScope)
|
||||
)
|
||||
}
|
||||
@@ -104,7 +112,7 @@ module AccessAfterLifetime {
|
||||
private class RefExprSource extends Source {
|
||||
Expr targetValue;
|
||||
|
||||
RefExprSource() { this.asExpr().getExpr().(RefExpr).getExpr() = targetValue }
|
||||
RefExprSource() { this.asExpr().(RefExpr).getExpr() = targetValue }
|
||||
|
||||
override Expr getTarget() { result = targetValue }
|
||||
}
|
||||
@@ -114,6 +122,6 @@ module AccessAfterLifetime {
|
||||
* variables through closures properly.
|
||||
*/
|
||||
private class ClosureBarrier extends Barrier {
|
||||
ClosureBarrier() { this.asExpr().getExpr().getEnclosingCallable() instanceof ClosureExpr }
|
||||
ClosureBarrier() { this.asExpr().getEnclosingCallable() instanceof ClosureExpr }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ module AccessInvalidPointer {
|
||||
* A pointer access using the unary `*` operator.
|
||||
*/
|
||||
private class DereferenceSink extends Sink {
|
||||
DereferenceSink() { any(DerefExpr p).getExpr() = this.asExpr().getExpr() }
|
||||
DereferenceSink() { any(DerefExpr p).getExpr() = this.asExpr() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@ import rust
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
private import codeql.rust.internal.Type
|
||||
private import codeql.rust.frameworks.stdlib.Builtins
|
||||
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
|
||||
|
||||
/**
|
||||
* A node whose type is a numeric or boolean type, which may be an appropriate
|
||||
@@ -16,11 +16,11 @@ private import codeql.rust.frameworks.stdlib.Builtins
|
||||
class NumericTypeBarrier extends DataFlow::Node {
|
||||
NumericTypeBarrier() {
|
||||
exists(StructType t, Struct s |
|
||||
t = TypeInference::inferType(this.asExpr().getExpr()) and
|
||||
t = TypeInference::inferType(this.asExpr()) and
|
||||
s = t.getStruct()
|
||||
|
|
||||
s instanceof NumericType or
|
||||
s instanceof Bool
|
||||
s instanceof Builtins::NumericType or
|
||||
s instanceof Builtins::Bool
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -32,11 +32,11 @@ class NumericTypeBarrier extends DataFlow::Node {
|
||||
class IntegralOrBooleanTypeBarrier extends DataFlow::Node {
|
||||
IntegralOrBooleanTypeBarrier() {
|
||||
exists(StructType t, Struct s |
|
||||
t = TypeInference::inferType(this.asExpr().getExpr()) and
|
||||
t = TypeInference::inferType(this.asExpr()) and
|
||||
s = t.getStruct()
|
||||
|
|
||||
s instanceof IntegralType or
|
||||
s instanceof Bool
|
||||
s instanceof Builtins::IntegralType or
|
||||
s instanceof Builtins::Bool
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ module HardcodedCryptographicValue {
|
||||
* A literal, considered as a flow source.
|
||||
*/
|
||||
private class LiteralSource extends Source {
|
||||
LiteralSource() { this.asExpr().getExpr() instanceof LiteralExpr }
|
||||
LiteralSource() { this.asExpr() instanceof LiteralExpr }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,8 +75,8 @@ module HardcodedCryptographicValue {
|
||||
*/
|
||||
private class ArrayListSource extends Source {
|
||||
ArrayListSource() {
|
||||
this.asExpr().getExpr().(ArrayListExpr).getExpr(_) instanceof LiteralExpr or
|
||||
this.asExpr().getExpr().(ArrayRepeatExpr).getRepeatOperand() instanceof LiteralExpr
|
||||
this.asExpr().(ArrayListExpr).getExpr(_) instanceof LiteralExpr or
|
||||
this.asExpr().(ArrayRepeatExpr).getRepeatOperand() instanceof LiteralExpr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ module HardcodedCryptographicValue {
|
||||
exists(CallExprBase ce |
|
||||
ce.getStaticTarget().(Addressable).getCanonicalPath() =
|
||||
["getrandom::fill", "getrandom::getrandom"] and
|
||||
this.asExpr().getExpr().getParentNode*() = ce.getArgList().getArg(0)
|
||||
this.asExpr().getParentNode*() = ce.getArgList().getArg(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,13 +85,13 @@ module InsecureCookie {
|
||||
cookieOptionalBarrier(summaryNode, attrib, arg) and
|
||||
// find a call and arg referenced by this optional barrier
|
||||
ce.getStaticTarget() = summaryNode.getSummarizedCallable() and
|
||||
ce.getArg(arg) = argNode.asExpr().getExpr() and
|
||||
ce.getArg(arg) = argNode.asExpr() and
|
||||
// check if the argument is always `true`
|
||||
(
|
||||
if
|
||||
forex(DataFlow::Node argSourceNode, BooleanLiteralExpr argSourceValue |
|
||||
DataFlow::localFlow(argSourceNode, argNode) and
|
||||
argSourceValue = argSourceNode.asExpr().getExpr()
|
||||
argSourceValue = argSourceNode.asExpr()
|
||||
|
|
||||
argSourceValue.getTextValue() = "true"
|
||||
)
|
||||
@@ -101,7 +101,7 @@ module InsecureCookie {
|
||||
// and find the node where this happens (we can't just use the flow summary node, since its
|
||||
// shared across all calls to the modeled function, we need a node specific to this call)
|
||||
(
|
||||
node.asExpr().getExpr() = ce.(MethodCallExpr).getReceiver() // e.g. `a` in `a.set_secure(true)`
|
||||
node.asExpr() = ce.(MethodCallExpr).getReceiver() // e.g. `a` in `a.set_secure(true)`
|
||||
or
|
||||
exists(BasicBlock bb, int i |
|
||||
// associated SSA node
|
||||
|
||||
@@ -29,7 +29,7 @@ private class SensitiveDataCall extends SensitiveData {
|
||||
|
||||
SensitiveDataCall() {
|
||||
exists(CallExprBase call, string name |
|
||||
call = this.asExpr().getExpr() and
|
||||
call = this.asExpr() and
|
||||
name =
|
||||
[
|
||||
call.getStaticTarget().(Function).getName().getText(),
|
||||
@@ -50,7 +50,6 @@ private class SensitiveVariableAccess extends SensitiveData {
|
||||
|
||||
SensitiveVariableAccess() {
|
||||
HeuristicNames::nameIndicatesSensitiveData(this.asExpr()
|
||||
.getExpr()
|
||||
.(VariableAccess)
|
||||
.getVariable()
|
||||
.(Variable)
|
||||
@@ -69,7 +68,7 @@ private class SensitiveFieldAccess extends SensitiveData {
|
||||
SensitiveDataClassification classification;
|
||||
|
||||
SensitiveFieldAccess() {
|
||||
exists(FieldExpr fe | fieldExprParentField*(fe) = this.asExpr().getExpr() |
|
||||
exists(FieldExpr fe | fieldExprParentField*(fe) = this.asExpr() |
|
||||
HeuristicNames::nameIndicatesSensitiveData(fe.getIdentifier().getText(), classification)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ private import codeql.rust.dataflow.TaintTracking
|
||||
private import codeql.rust.Concepts
|
||||
private import codeql.rust.dataflow.internal.DataFlowImpl
|
||||
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
|
||||
private import codeql.rust.controlflow.CfgNodes as CfgNodes
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks and barriers for detecting path injection
|
||||
@@ -50,16 +49,16 @@ module TaintedPath {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate sanitizerGuard(CfgNodes::AstCfgNode g, Cfg::CfgNode node, boolean branch) {
|
||||
g.(SanitizerGuard::Range).checks(node, branch)
|
||||
private predicate sanitizerGuard(AstNode g, Expr e, boolean branch) {
|
||||
g.(SanitizerGuard::Range).checks(e, branch)
|
||||
}
|
||||
|
||||
/** Provides a class for modeling new path safety checks. */
|
||||
module SanitizerGuard {
|
||||
/** A data-flow node that checks that a path is safe to access. */
|
||||
abstract class Range extends CfgNodes::AstCfgNode {
|
||||
/** Holds if this guard validates `node` upon evaluating to `branch`. */
|
||||
abstract predicate checks(Cfg::CfgNode node, boolean branch);
|
||||
abstract class Range extends AstNode {
|
||||
/** Holds if this guard validates `e` upon evaluating to `branch`. */
|
||||
abstract predicate checks(Expr e, boolean branch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,15 +66,14 @@ module SanitizerGuard {
|
||||
* A check of the form `!strings.Contains(nd, "..")`, considered as a sanitizer guard for
|
||||
* path traversal.
|
||||
*/
|
||||
private class DotDotCheck extends SanitizerGuard::Range, CfgNodes::MethodCallExprCfgNode {
|
||||
private class DotDotCheck extends SanitizerGuard::Range, MethodCallExpr {
|
||||
DotDotCheck() {
|
||||
this.getAstNode().(CallExprBase).getStaticTarget().(Addressable).getCanonicalPath() =
|
||||
this.getStaticTarget().(Addressable).getCanonicalPath() =
|
||||
["<alloc::string::String>::contains", "<core::str>::contains"] and
|
||||
this.getArgument(0).getAstNode().(LiteralExpr).getTextValue() =
|
||||
["\"..\"", "\"../\"", "\"..\\\""]
|
||||
this.getArg(0).(LiteralExpr).getTextValue() = ["\"..\"", "\"../\"", "\"..\\\""]
|
||||
}
|
||||
|
||||
override predicate checks(Cfg::CfgNode e, boolean branch) {
|
||||
override predicate checks(Expr e, boolean branch) {
|
||||
e = this.getReceiver() and
|
||||
branch = false
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import rust
|
||||
private import codeql.rust.Concepts
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.dataflow.FlowSink
|
||||
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
|
||||
private import codeql.rust.controlflow.CfgNodes as CfgNodes
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks and barriers for detecting uncontrolled
|
||||
@@ -45,23 +43,24 @@ module UncontrolledAllocationSize {
|
||||
|
||||
/**
|
||||
* Holds if comparison `g` having result `branch` indicates an upper bound for the sub-expression
|
||||
* `node`. For example when the comparison `x < 10` is true, we have an upper bound for `x`.
|
||||
* `e`. For example when the comparison `x < 10` is true, we have an upper bound for `x`.
|
||||
*/
|
||||
private predicate isUpperBoundCheck(CfgNodes::AstCfgNode g, Cfg::CfgNode node, boolean branch) {
|
||||
exists(BinaryExpr cmp | g = cmp.getACfgNode() |
|
||||
node = cmp.(RelationalOperation).getLesserOperand().getACfgNode() and
|
||||
branch = true
|
||||
or
|
||||
node = cmp.(RelationalOperation).getGreaterOperand().getACfgNode() and
|
||||
branch = false
|
||||
or
|
||||
cmp instanceof EqualsOperation and
|
||||
[cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and
|
||||
branch = true
|
||||
or
|
||||
cmp instanceof NotEqualsOperation and
|
||||
[cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and
|
||||
branch = false
|
||||
)
|
||||
private predicate isUpperBoundCheck(AstNode g, Expr e, boolean branch) {
|
||||
g =
|
||||
any(BinaryExpr cmp |
|
||||
e = cmp.(RelationalOperation).getLesserOperand() and
|
||||
branch = true
|
||||
or
|
||||
e = cmp.(RelationalOperation).getGreaterOperand() and
|
||||
branch = false
|
||||
or
|
||||
cmp instanceof EqualsOperation and
|
||||
[cmp.getLhs(), cmp.getRhs()] = e and
|
||||
branch = true
|
||||
or
|
||||
cmp instanceof NotEqualsOperation and
|
||||
[cmp.getLhs(), cmp.getRhs()] = e and
|
||||
branch = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ module UseOfHttp {
|
||||
* An HTTP string literal as a source.
|
||||
*/
|
||||
private class HttpStringLiteralAsSource extends Source {
|
||||
HttpStringLiteralAsSource() { this.asExpr().getExpr() instanceof HttpStringLiteral }
|
||||
HttpStringLiteralAsSource() { this.asExpr() instanceof HttpStringLiteral }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -189,7 +189,7 @@ class ModeledHashOperation extends Cryptography::CryptographicOperation::Range {
|
||||
exists(CallExpr call |
|
||||
sinkNode(input, "hasher-input") and
|
||||
call = input.(Node::FlowSummaryNode).getSinkElement().getCall() and
|
||||
call = this.asExpr().getExpr() and
|
||||
call = this.asExpr() and
|
||||
algorithmName = call.getFunction().(PathExpr).getPath().getQualifier().getText()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
private import codeql.util.Unit
|
||||
private import rust
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.dataflow.FlowSink
|
||||
private import codeql.rust.Concepts
|
||||
private import codeql.rust.security.Barriers as Barriers
|
||||
@@ -57,8 +56,8 @@ module RegexInjection {
|
||||
exists(CallExprBase call, Addressable a |
|
||||
call.getStaticTarget() = a and
|
||||
a.getCanonicalPath() = "<regex::regex::string::Regex>::new" and
|
||||
this.asExpr().getExpr() = call.getArg(0) and
|
||||
not this.asExpr() instanceof LiteralExprCfgNode
|
||||
this.asExpr() = call.getArg(0) and
|
||||
not this.asExpr() instanceof LiteralExpr
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -78,7 +77,6 @@ module RegexInjection {
|
||||
// A barrier is any call to a function named `escape`, in particular this
|
||||
// makes calls to `regex::escape` a barrier.
|
||||
this.asExpr()
|
||||
.getExpr()
|
||||
.(CallExpr)
|
||||
.getFunction()
|
||||
.(PathExpr)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/rust-all
|
||||
version: 0.1.20-dev
|
||||
version: 0.1.21-dev
|
||||
groups: rust
|
||||
extractor: rust
|
||||
dbscheme: rust.dbscheme
|
||||
|
||||
@@ -9,6 +9,7 @@ import codeql.rust.elements.ArithmeticOperation
|
||||
import codeql.rust.elements.AssignmentOperation
|
||||
import codeql.rust.elements.BitwiseOperation
|
||||
import codeql.rust.elements.ComparisonOperation
|
||||
import codeql.rust.elements.ConstAccess
|
||||
import codeql.rust.elements.DerefExpr
|
||||
import codeql.rust.elements.LiteralExprExt
|
||||
import codeql.rust.elements.LogicalOperation
|
||||
|
||||
@@ -18,20 +18,20 @@ private import internal.InlineExpectationsTestImpl as InlineExpectationsTestImpl
|
||||
* representation of the path has `name` as a prefix.
|
||||
*/
|
||||
bindingset[name]
|
||||
private predicate callTargetName(CallExprCfgNode call, string name) {
|
||||
call.getFunction().(PathExprCfgNode).toString().matches(name + "%")
|
||||
private predicate callTargetName(CallExpr call, string name) {
|
||||
call.getFunction().(PathExpr).toString().matches(name + "%")
|
||||
}
|
||||
|
||||
private module FlowTestImpl implements InputSig<Location, RustDataFlow> {
|
||||
predicate defaultSource(DataFlow::Node source) { callTargetName(source.asExpr(), "source") }
|
||||
|
||||
predicate defaultSink(DataFlow::Node sink) {
|
||||
any(CallExprCfgNode call | callTargetName(call, "sink")).getArgument(_) = sink.asExpr()
|
||||
any(CallExpr call | callTargetName(call, "sink")).getAnArg() = sink.asExpr()
|
||||
}
|
||||
|
||||
private string getSourceArgString(DataFlow::Node src) {
|
||||
defaultSource(src) and
|
||||
result = src.asExpr().(CallExprCfgNode).getArgument(0).toString()
|
||||
result = src.asExpr().(CallExpr).getArg(0).toString()
|
||||
or
|
||||
sourceNode(src, _) and
|
||||
result = src.(Node::FlowSummaryNode).getSourceElement().getCall().getArg(0).toString() and
|
||||
|
||||
@@ -10,9 +10,8 @@ private import utils.test.InlineExpectationsTest
|
||||
private module ResolveTest implements TestSig {
|
||||
string getARelevantTag() { result = "item" }
|
||||
|
||||
private predicate itemAt(ItemNode i, string filepath, int line, boolean inMacro) {
|
||||
i.getLocation().hasLocationInfo(filepath, _, _, line, _) and
|
||||
if i.(AstNode).isInMacroExpansion() then inMacro = true else inMacro = false
|
||||
private predicate itemAt(ItemNode i, string filepath, int line) {
|
||||
i.getLocation().hasLocationInfo(filepath, _, _, line, _)
|
||||
}
|
||||
|
||||
private predicate commmentAt(string text, string filepath, int line) {
|
||||
@@ -25,7 +24,7 @@ private module ResolveTest implements TestSig {
|
||||
}
|
||||
|
||||
private predicate item(ItemNode i, string value) {
|
||||
exists(string filepath, int line, boolean inMacro | itemAt(i, filepath, line, inMacro) |
|
||||
exists(string filepath, int line | itemAt(i, filepath, line) |
|
||||
if i instanceof SourceFile
|
||||
then value = i.getFile().getBaseName()
|
||||
else (
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
## 0.1.20
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Taint flow barriers have been added to the `rust/regex-injection`, `rust/sql-injection` and `rust/log-injection`, reducing the frequency of false positive results for these queries.
|
||||
|
||||
## 0.1.19
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
4
rust/ql/src/change-notes/2025-11-07-example-queries.md
Normal file
4
rust/ql/src/change-notes/2025-11-07-example-queries.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added three example queries (`rust/examples/empty-if`, `rust/examples/simple-sql-injection` and `rust/examples/simple-constant-password`) to help developers learn to write CodeQL queries for Rust.
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
## 0.1.20
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Taint flow barriers have been added to the `rust/regex-injection`, `rust/sql-injection` and `rust/log-injection`, reducing the frequency of false positive results for these queries.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.1.19
|
||||
lastReleaseVersion: 0.1.20
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/rust-queries
|
||||
version: 0.1.20-dev
|
||||
version: 0.1.21-dev
|
||||
groups:
|
||||
- rust
|
||||
- queries
|
||||
|
||||
@@ -37,7 +37,7 @@ module CleartextLoggingConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// flow from `a` to `&a`
|
||||
node2.asExpr().getExpr().(RefExpr).getExpr() = node1.asExpr().getExpr()
|
||||
node2.asExpr().(RefExpr).getExpr() = node1.asExpr()
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
|
||||
@@ -36,7 +36,7 @@ module CleartextStorageDatabaseConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// flow from `a` to `&a`
|
||||
node2.asExpr().getExpr().(RefExpr).getExpr() = node1.asExpr().getExpr()
|
||||
node2.asExpr().(RefExpr).getExpr() = node1.asExpr()
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
@@ -39,9 +39,9 @@ module InsecureCookieConfig implements DataFlow::ConfigSig {
|
||||
node instanceof Sink
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
// setting the 'secure' attribute to true
|
||||
cookieSetNode(node, "secure", true)
|
||||
predicate isBarrierIn(DataFlow::Node node) {
|
||||
// setting the 'secure' attribute
|
||||
cookieSetNode(node, "secure", _)
|
||||
or
|
||||
node instanceof Barrier
|
||||
}
|
||||
|
||||
@@ -23,40 +23,37 @@ import AccessAfterLifetimeFlow::PathGraph
|
||||
* lifetime has ended.
|
||||
*/
|
||||
module AccessAfterLifetimeConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node instanceof AccessAfterLifetime::Source }
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
node instanceof AccessAfterLifetime::Source and
|
||||
// exclude cases with sources in macros, since these results are difficult to interpret
|
||||
not node.asExpr().isFromMacroExpansion()
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node instanceof AccessAfterLifetime::Sink }
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
node instanceof AccessAfterLifetime::Sink and
|
||||
// exclude cases with sinks in macros, since these results are difficult to interpret
|
||||
not node.asExpr().isFromMacroExpansion() and
|
||||
// include only results inside `unsafe` blocks, as other results tend to be false positives
|
||||
(
|
||||
node.asExpr().getEnclosingBlock*().isUnsafe() or
|
||||
node.asExpr().getEnclosingCallable().(Function).isUnsafe()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof AccessAfterLifetime::Barrier }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) {
|
||||
exists(Variable target, DataFlow::Node sink |
|
||||
exists(Variable target |
|
||||
AccessAfterLifetime::sourceValueScope(source, target, _) and
|
||||
result = [target.getLocation(), source.getLocation()]
|
||||
|
|
||||
isSink(sink) and
|
||||
narrowDereferenceAfterLifetime(source, sink, target)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module AccessAfterLifetimeFlow = TaintTracking::Global<AccessAfterLifetimeConfig>;
|
||||
|
||||
pragma[inline]
|
||||
predicate narrowDereferenceAfterLifetime(DataFlow::Node source, DataFlow::Node sink, Variable target) {
|
||||
// check that the dereference is outside the lifetime of the target
|
||||
AccessAfterLifetime::dereferenceAfterLifetime(source, sink, target) and
|
||||
// include only results inside `unsafe` blocks, as other results tend to be false positives
|
||||
(
|
||||
sink.asExpr().getExpr().getEnclosingBlock*().isUnsafe() or
|
||||
sink.asExpr().getExpr().getEnclosingCallable().(Function).isUnsafe()
|
||||
) and
|
||||
// exclude cases with sources / sinks in macros, since these results are difficult to interpret
|
||||
not source.asExpr().getExpr().isFromMacroExpansion() and
|
||||
not sink.asExpr().getExpr().isFromMacroExpansion()
|
||||
}
|
||||
|
||||
from
|
||||
AccessAfterLifetimeFlow::PathNode sourceNode, AccessAfterLifetimeFlow::PathNode sinkNode,
|
||||
Variable target
|
||||
@@ -64,6 +61,6 @@ where
|
||||
// flow from a pointer or reference to the dereference
|
||||
AccessAfterLifetimeFlow::flowPath(sourceNode, sinkNode) and
|
||||
// check that the dereference is outside the lifetime of the target
|
||||
narrowDereferenceAfterLifetime(sourceNode.getNode(), sinkNode.getNode(), target)
|
||||
AccessAfterLifetime::dereferenceAfterLifetime(sourceNode.getNode(), sinkNode.getNode(), target)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode,
|
||||
"Access of a pointer to $@ after its lifetime has ended.", target, target.toString()
|
||||
|
||||
@@ -33,7 +33,7 @@ predicate hiddenNode(AstNode n) {
|
||||
n instanceof ControlFlowGraphImpl::PostOrderTree and // location is counter-intuitive
|
||||
not n instanceof MacroExpr
|
||||
or
|
||||
n.isInMacroExpansion()
|
||||
n.isFromMacroExpansion()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,10 +18,10 @@ from AstNode write, Ssa::Variable v
|
||||
where
|
||||
variableWrite(_, write, v) and
|
||||
not v instanceof DiscardVariable and
|
||||
not write.isInMacroExpansion() and
|
||||
not write.isFromMacroExpansion() and
|
||||
not isAllowableUnused(v) and
|
||||
// SSA definitions are only created for live writes
|
||||
not write = any(Ssa::WriteDefinition def).getWriteAccess().getAstNode() and
|
||||
not write = any(Ssa::WriteDefinition def).getWriteAccess() and
|
||||
// avoid overlap with the unused variable query
|
||||
not isUnused(v)
|
||||
select write, "Variable $@ is assigned a value that is never used.", v, v.getText()
|
||||
|
||||
@@ -36,7 +36,7 @@ class IncompleteCallable extends Callable {
|
||||
*/
|
||||
predicate isAllowableUnused(Variable v) {
|
||||
// in a macro expansion
|
||||
v.getPat().isInMacroExpansion()
|
||||
v.getPat().isInMacroExpansion() // TODO: replace with `isFromMacroExpansion()` when false positives have been removed
|
||||
or
|
||||
// declared in an incomplete callable
|
||||
v.getEnclosingCfgScope() instanceof IncompleteCallable
|
||||
|
||||
@@ -120,7 +120,7 @@ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputS
|
||||
}
|
||||
|
||||
QualifiedCallable getAsExprEnclosingCallable(NodeExtended node) {
|
||||
result.getFunction() = node.asExpr().getScope()
|
||||
result.getFunction() = node.asExpr().getEnclosingCfgScope()
|
||||
}
|
||||
|
||||
Parameter asParameter(NodeExtended node) { result = node.asParameter() }
|
||||
|
||||
@@ -16,30 +16,32 @@ stringLiteral
|
||||
| literal.rs:21:5:21:8 | r"R" |
|
||||
| literal.rs:22:5:22:11 | "\\\\x52" |
|
||||
| literal.rs:23:5:23:11 | r"\\x52" |
|
||||
| literal.rs:25:5:29:5 | "\n A normal string literal\n... |
|
||||
| literal.rs:31:5:34:6 | r#"\n A raw string literal\n ... |
|
||||
integerLiteral
|
||||
| literal.rs:28:5:28:7 | 123 | |
|
||||
| literal.rs:29:5:29:10 | 123i32 | i32 |
|
||||
| literal.rs:30:5:30:10 | 123u32 | u32 |
|
||||
| literal.rs:31:5:31:11 | 123_u32 | u32 |
|
||||
| literal.rs:33:5:33:8 | 0xff | |
|
||||
| literal.rs:34:5:34:11 | 0xff_u8 | u8 |
|
||||
| literal.rs:35:5:35:12 | 0x01_f32 | |
|
||||
| literal.rs:36:5:36:11 | 0x01_e3 | |
|
||||
| literal.rs:38:5:38:8 | 0o70 | |
|
||||
| literal.rs:39:5:39:12 | 0o70_i16 | i16 |
|
||||
| literal.rs:41:5:41:25 | 0b1111_1111_1001_0000 | |
|
||||
| literal.rs:42:5:42:28 | 0b1111_1111_1001_0000i64 | i64 |
|
||||
| literal.rs:43:5:43:15 | 0b________1 | |
|
||||
| literal.rs:45:5:45:10 | 0usize | usize |
|
||||
| literal.rs:48:5:49:10 | 128_i8 | i8 |
|
||||
| literal.rs:50:5:51:10 | 256_u8 | u8 |
|
||||
| literal.rs:39:5:39:7 | 123 | |
|
||||
| literal.rs:40:5:40:10 | 123i32 | i32 |
|
||||
| literal.rs:41:5:41:10 | 123u32 | u32 |
|
||||
| literal.rs:42:5:42:11 | 123_u32 | u32 |
|
||||
| literal.rs:44:5:44:8 | 0xff | |
|
||||
| literal.rs:45:5:45:11 | 0xff_u8 | u8 |
|
||||
| literal.rs:46:5:46:12 | 0x01_f32 | |
|
||||
| literal.rs:47:5:47:11 | 0x01_e3 | |
|
||||
| literal.rs:49:5:49:8 | 0o70 | |
|
||||
| literal.rs:50:5:50:12 | 0o70_i16 | i16 |
|
||||
| literal.rs:52:5:52:25 | 0b1111_1111_1001_0000 | |
|
||||
| literal.rs:53:5:53:28 | 0b1111_1111_1001_0000i64 | i64 |
|
||||
| literal.rs:54:5:54:15 | 0b________1 | |
|
||||
| literal.rs:56:5:56:10 | 0usize | usize |
|
||||
| literal.rs:59:5:60:10 | 128_i8 | i8 |
|
||||
| literal.rs:61:5:62:10 | 256_u8 | u8 |
|
||||
floatLiteral
|
||||
| literal.rs:56:5:56:8 | 5f32 | f32 |
|
||||
| literal.rs:58:5:58:12 | 123.0f64 | f64 |
|
||||
| literal.rs:59:5:59:10 | 0.1f64 | f64 |
|
||||
| literal.rs:60:5:60:10 | 0.1f32 | f32 |
|
||||
| literal.rs:61:5:61:14 | 12E+99_f64 | f64 |
|
||||
| literal.rs:62:18:62:19 | 2. | |
|
||||
| literal.rs:67:5:67:8 | 5f32 | f32 |
|
||||
| literal.rs:69:5:69:12 | 123.0f64 | f64 |
|
||||
| literal.rs:70:5:70:10 | 0.1f64 | f64 |
|
||||
| literal.rs:71:5:71:10 | 0.1f32 | f32 |
|
||||
| literal.rs:72:5:72:14 | 12E+99_f64 | f64 |
|
||||
| literal.rs:73:18:73:19 | 2. | |
|
||||
booleanLiteral
|
||||
| literal.rs:66:5:66:8 | true |
|
||||
| literal.rs:67:5:67:9 | false |
|
||||
| literal.rs:77:5:77:8 | true |
|
||||
| literal.rs:78:5:78:9 | false |
|
||||
|
||||
@@ -21,6 +21,17 @@ fn string_literals() {
|
||||
r"R"; // R
|
||||
"\\x52";
|
||||
r"\x52"; // \x52
|
||||
|
||||
"
|
||||
A normal string literal
|
||||
across many
|
||||
lines
|
||||
";
|
||||
|
||||
r#"
|
||||
A raw string literal
|
||||
across multiple lines
|
||||
"#;
|
||||
}
|
||||
|
||||
fn integer_literals() {
|
||||
|
||||
@@ -174,7 +174,7 @@ macro_expansion.rs:
|
||||
# 1| getPath(): [Path] MyTrait
|
||||
# 1| getSegment(): [PathSegment] MyTrait
|
||||
# 1| getIdentifier(): [NameRef] MyTrait
|
||||
# 3| getItem(1): [Function] fn foo
|
||||
# 3| getItem(1): [Function] (item with attribute macro expansion)
|
||||
# 4| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 4| getItem(0): [Function] fn foo
|
||||
# 4| getParamList(): [ParamList] ParamList
|
||||
@@ -190,7 +190,7 @@ macro_expansion.rs:
|
||||
# 5| getIdentifier(): [NameRef] concat
|
||||
# 5| getTokenTree(): [TokenTree] TokenTree
|
||||
# 5| getMacroCallExpansion(): [StringLiteralExpr] "Hello world!"
|
||||
# 7| getStatement(1): [Function] fn inner
|
||||
# 7| getStatement(1): [Function] (item with attribute macro expansion)
|
||||
# 8| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 8| getItem(0): [Function] fn inner_0
|
||||
# 8| getParamList(): [ParamList] ParamList
|
||||
@@ -202,16 +202,12 @@ macro_expansion.rs:
|
||||
# 8| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 8| getStmtList(): [StmtList] StmtList
|
||||
# 8| getName(): [Name] inner_1
|
||||
# 8| getParamList(): [ParamList] ParamList
|
||||
# 7| getAttr(0): [Attr] Attr
|
||||
# 7| getMeta(): [Meta] Meta
|
||||
# 7| getPath(): [Path] repeat
|
||||
# 7| getSegment(): [PathSegment] repeat
|
||||
# 7| getIdentifier(): [NameRef] repeat
|
||||
# 7| getTokenTree(): [TokenTree] TokenTree
|
||||
# 8| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 8| getStmtList(): [StmtList] StmtList
|
||||
# 8| getName(): [Name] inner
|
||||
# 10| getStatement(2): [ExprStmt] ExprStmt
|
||||
# 10| getExpr(): [CallExpr] inner_0(...)
|
||||
# 10| getArgList(): [ArgList] ArgList
|
||||
@@ -242,7 +238,7 @@ macro_expansion.rs:
|
||||
# 5| getIdentifier(): [NameRef] concat
|
||||
# 5| getTokenTree(): [TokenTree] TokenTree
|
||||
# 5| getMacroCallExpansion(): [StringLiteralExpr] "Hello world!"
|
||||
# 7| getStatement(1): [Function] fn inner
|
||||
# 7| getStatement(1): [Function] (item with attribute macro expansion)
|
||||
# 8| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 8| getItem(0): [Function] fn inner_0
|
||||
# 8| getParamList(): [ParamList] ParamList
|
||||
@@ -254,16 +250,12 @@ macro_expansion.rs:
|
||||
# 8| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 8| getStmtList(): [StmtList] StmtList
|
||||
# 8| getName(): [Name] inner_1
|
||||
# 8| getParamList(): [ParamList] ParamList
|
||||
# 7| getAttr(0): [Attr] Attr
|
||||
# 7| getMeta(): [Meta] Meta
|
||||
# 7| getPath(): [Path] repeat
|
||||
# 7| getSegment(): [PathSegment] repeat
|
||||
# 7| getIdentifier(): [NameRef] repeat
|
||||
# 7| getTokenTree(): [TokenTree] TokenTree
|
||||
# 8| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 8| getStmtList(): [StmtList] StmtList
|
||||
# 8| getName(): [Name] inner
|
||||
# 10| getStatement(2): [ExprStmt] ExprStmt
|
||||
# 10| getExpr(): [CallExpr] inner_0(...)
|
||||
# 10| getArgList(): [ArgList] ArgList
|
||||
@@ -280,53 +272,14 @@ macro_expansion.rs:
|
||||
# 11| getIdentifier(): [NameRef] inner_1
|
||||
# 4| getName(): [Name] foo_new
|
||||
# 4| getVisibility(): [Visibility] Visibility
|
||||
# 4| getParamList(): [ParamList] ParamList
|
||||
# 3| getAttr(0): [Attr] Attr
|
||||
# 3| getMeta(): [Meta] Meta
|
||||
# 3| getPath(): [Path] add_one
|
||||
# 3| getSegment(): [PathSegment] add_one
|
||||
# 3| getIdentifier(): [NameRef] add_one
|
||||
# 4| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 4| getStmtList(): [StmtList] StmtList
|
||||
# 5| getStatement(0): [ExprStmt] ExprStmt
|
||||
# 5| getExpr(): [AssignmentExpr] ... = ...
|
||||
# 5| getLhs(): [UnderscoreExpr] _
|
||||
# 5| getRhs(): [MacroExpr] MacroExpr
|
||||
# 5| getMacroCall(): [MacroCall] concat!...
|
||||
# 5| getPath(): [Path] concat
|
||||
# 5| getSegment(): [PathSegment] concat
|
||||
# 5| getIdentifier(): [NameRef] concat
|
||||
# 5| getTokenTree(): [TokenTree] TokenTree
|
||||
# 7| getStatement(1): [Function] fn inner
|
||||
# 8| getParamList(): [ParamList] ParamList
|
||||
# 7| getAttr(0): [Attr] Attr
|
||||
# 7| getMeta(): [Meta] Meta
|
||||
# 7| getPath(): [Path] repeat
|
||||
# 7| getSegment(): [PathSegment] repeat
|
||||
# 7| getIdentifier(): [NameRef] repeat
|
||||
# 7| getTokenTree(): [TokenTree] TokenTree
|
||||
# 8| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 8| getStmtList(): [StmtList] StmtList
|
||||
# 8| getName(): [Name] inner
|
||||
# 10| getStatement(2): [ExprStmt] ExprStmt
|
||||
# 10| getExpr(): [CallExpr] inner_0(...)
|
||||
# 10| getArgList(): [ArgList] ArgList
|
||||
# 10| getFunction(): [PathExpr] inner_0
|
||||
# 10| getPath(): [Path] inner_0
|
||||
# 10| getSegment(): [PathSegment] inner_0
|
||||
# 10| getIdentifier(): [NameRef] inner_0
|
||||
# 11| getStatement(3): [ExprStmt] ExprStmt
|
||||
# 11| getExpr(): [CallExpr] inner_1(...)
|
||||
# 11| getArgList(): [ArgList] ArgList
|
||||
# 11| getFunction(): [PathExpr] inner_1
|
||||
# 11| getPath(): [Path] inner_1
|
||||
# 11| getSegment(): [PathSegment] inner_1
|
||||
# 11| getIdentifier(): [NameRef] inner_1
|
||||
# 4| getName(): [Name] foo
|
||||
# 4| getVisibility(): [Visibility] Visibility
|
||||
# 14| getItem(2): [Function] fn bar
|
||||
# 14| getItem(2): [Function] (item with attribute macro expansion)
|
||||
# 15| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 15| getItem(0): [Function] fn bar_0
|
||||
# 15| getItem(0): [Function] (item with attribute macro expansion)
|
||||
# 16| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 16| getItem(0): [Function] fn bar_0
|
||||
# 16| getParamList(): [ParamList] ParamList
|
||||
@@ -340,17 +293,12 @@ macro_expansion.rs:
|
||||
# 16| getStmtList(): [StmtList] StmtList
|
||||
# 16| getName(): [Name] bar_0_new
|
||||
# 16| getVisibility(): [Visibility] Visibility
|
||||
# 16| getParamList(): [ParamList] ParamList
|
||||
# 15| getAttr(0): [Attr] Attr
|
||||
# 15| getMeta(): [Meta] Meta
|
||||
# 15| getPath(): [Path] add_one
|
||||
# 15| getSegment(): [PathSegment] add_one
|
||||
# 15| getIdentifier(): [NameRef] add_one
|
||||
# 16| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 16| getStmtList(): [StmtList] StmtList
|
||||
# 16| getName(): [Name] bar_0
|
||||
# 16| getVisibility(): [Visibility] Visibility
|
||||
# 15| getItem(1): [Function] fn bar_1
|
||||
# 15| getItem(1): [Function] (item with attribute macro expansion)
|
||||
# 16| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 16| getItem(0): [Function] fn bar_1
|
||||
# 16| getParamList(): [ParamList] ParamList
|
||||
@@ -364,17 +312,11 @@ macro_expansion.rs:
|
||||
# 16| getStmtList(): [StmtList] StmtList
|
||||
# 16| getName(): [Name] bar_1_new
|
||||
# 16| getVisibility(): [Visibility] Visibility
|
||||
# 16| getParamList(): [ParamList] ParamList
|
||||
# 15| getAttr(0): [Attr] Attr
|
||||
# 15| getMeta(): [Meta] Meta
|
||||
# 15| getPath(): [Path] add_one
|
||||
# 15| getSegment(): [PathSegment] add_one
|
||||
# 15| getIdentifier(): [NameRef] add_one
|
||||
# 16| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 16| getStmtList(): [StmtList] StmtList
|
||||
# 16| getName(): [Name] bar_1
|
||||
# 16| getVisibility(): [Visibility] Visibility
|
||||
# 16| getParamList(): [ParamList] ParamList
|
||||
# 14| getAttr(0): [Attr] Attr
|
||||
# 14| getMeta(): [Meta] Meta
|
||||
# 14| getPath(): [Path] repeat
|
||||
@@ -386,22 +328,13 @@ macro_expansion.rs:
|
||||
# 15| getPath(): [Path] add_one
|
||||
# 15| getSegment(): [PathSegment] add_one
|
||||
# 15| getIdentifier(): [NameRef] add_one
|
||||
# 16| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 16| getStmtList(): [StmtList] StmtList
|
||||
# 16| getName(): [Name] bar
|
||||
# 16| getVisibility(): [Visibility] Visibility
|
||||
# 18| getItem(3): [Function] fn baz
|
||||
# 18| getItem(3): [Function] (item with attribute macro expansion)
|
||||
# 18| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 19| getParamList(): [ParamList] ParamList
|
||||
# 18| getAttr(0): [Attr] Attr
|
||||
# 18| getMeta(): [Meta] Meta
|
||||
# 18| getPath(): [Path] erase
|
||||
# 18| getSegment(): [PathSegment] erase
|
||||
# 18| getIdentifier(): [NameRef] erase
|
||||
# 19| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 19| getStmtList(): [StmtList] StmtList
|
||||
# 19| getName(): [Name] baz
|
||||
# 19| getVisibility(): [Visibility] Visibility
|
||||
# 22| getItem(4): [MacroRules] MacroRules
|
||||
# 22| getName(): [Name] hello
|
||||
# 22| getTokenTree(): [TokenTree] TokenTree
|
||||
@@ -410,7 +343,7 @@ macro_expansion.rs:
|
||||
# 28| getVisibility(): [Visibility] Visibility
|
||||
# 30| getItem(6): [Impl] impl S { ... }
|
||||
# 30| getAssocItemList(): [AssocItemList] AssocItemList
|
||||
# 31| getAssocItem(0): [Function] fn bzz
|
||||
# 31| getAssocItem(0): [Function] (item with attribute macro expansion)
|
||||
# 32| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 32| getItem(0): [Function] fn bzz_0
|
||||
# 32| getParamList(): [ParamList] ParamList
|
||||
@@ -556,24 +489,12 @@ macro_expansion.rs:
|
||||
# 31| getIdentifier(): [NameRef] _print
|
||||
# 32| getName(): [Name] bzz_2
|
||||
# 32| getVisibility(): [Visibility] Visibility
|
||||
# 32| getParamList(): [ParamList] ParamList
|
||||
# 31| getAttr(0): [Attr] Attr
|
||||
# 31| getMeta(): [Meta] Meta
|
||||
# 31| getPath(): [Path] repeat
|
||||
# 31| getSegment(): [PathSegment] repeat
|
||||
# 31| getIdentifier(): [NameRef] repeat
|
||||
# 31| getTokenTree(): [TokenTree] TokenTree
|
||||
# 32| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 32| getStmtList(): [StmtList] StmtList
|
||||
# 33| getStatement(0): [ExprStmt] ExprStmt
|
||||
# 33| getExpr(): [MacroExpr] MacroExpr
|
||||
# 33| getMacroCall(): [MacroCall] hello!...
|
||||
# 33| getPath(): [Path] hello
|
||||
# 33| getSegment(): [PathSegment] hello
|
||||
# 33| getIdentifier(): [NameRef] hello
|
||||
# 33| getTokenTree(): [TokenTree] TokenTree
|
||||
# 32| getName(): [Name] bzz
|
||||
# 32| getVisibility(): [Visibility] Visibility
|
||||
# 30| getSelfTy(): [PathTypeRepr] S
|
||||
# 30| getPath(): [Path] S
|
||||
# 30| getSegment(): [PathSegment] S
|
||||
@@ -1043,7 +964,7 @@ macro_expansion.rs:
|
||||
# 98| getParamList(): [ParamList] ParamList
|
||||
# 99| getFunctionBody(): [BlockExpr] { ... }
|
||||
# 99| getStmtList(): [StmtList] StmtList
|
||||
# 99| getTailExpr(): [PathExpr] CONST_MyDeriveUnion
|
||||
# 99| getTailExpr(): [ConstAccess] CONST_MyDeriveUnion
|
||||
# 99| getPath(): [Path] CONST_MyDeriveUnion
|
||||
# 99| getSegment(): [PathSegment] CONST_MyDeriveUnion
|
||||
# 99| getIdentifier(): [NameRef] CONST_MyDeriveUnion
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
attribute_macros
|
||||
| macro_expansion.rs:3:1:12:1 | fn foo | 0 | macro_expansion.rs:4:1:12:1 | fn foo |
|
||||
| macro_expansion.rs:3:1:12:1 | fn foo | 1 | macro_expansion.rs:4:1:12:1 | fn foo_new |
|
||||
| macro_expansion.rs:7:5:8:17 | fn inner | 0 | macro_expansion.rs:8:5:8:17 | fn inner_0 |
|
||||
| macro_expansion.rs:7:5:8:17 | fn inner | 0 | macro_expansion.rs:8:5:8:17 | fn inner_0 |
|
||||
| macro_expansion.rs:7:5:8:17 | fn inner | 1 | macro_expansion.rs:8:5:8:17 | fn inner_1 |
|
||||
| macro_expansion.rs:7:5:8:17 | fn inner | 1 | macro_expansion.rs:8:5:8:17 | fn inner_1 |
|
||||
| macro_expansion.rs:14:1:16:15 | fn bar | 0 | macro_expansion.rs:15:1:16:15 | fn bar_0 |
|
||||
| macro_expansion.rs:14:1:16:15 | fn bar | 1 | macro_expansion.rs:15:1:16:15 | fn bar_1 |
|
||||
| macro_expansion.rs:15:1:16:15 | fn bar_0 | 0 | macro_expansion.rs:16:1:16:15 | fn bar_0 |
|
||||
| macro_expansion.rs:15:1:16:15 | fn bar_0 | 1 | macro_expansion.rs:16:1:16:15 | fn bar_0_new |
|
||||
| macro_expansion.rs:15:1:16:15 | fn bar_1 | 0 | macro_expansion.rs:16:1:16:15 | fn bar_1 |
|
||||
| macro_expansion.rs:15:1:16:15 | fn bar_1 | 1 | macro_expansion.rs:16:1:16:15 | fn bar_1_new |
|
||||
| macro_expansion.rs:31:5:34:5 | fn bzz | 0 | macro_expansion.rs:32:5:34:5 | fn bzz_0 |
|
||||
| macro_expansion.rs:31:5:34:5 | fn bzz | 1 | macro_expansion.rs:32:5:34:5 | fn bzz_1 |
|
||||
| macro_expansion.rs:31:5:34:5 | fn bzz | 2 | macro_expansion.rs:32:5:34:5 | fn bzz_2 |
|
||||
| macro_expansion.rs:3:1:12:1 | (item with attribute macro expansion) | 0 | macro_expansion.rs:4:1:12:1 | fn foo |
|
||||
| macro_expansion.rs:3:1:12:1 | (item with attribute macro expansion) | 1 | macro_expansion.rs:4:1:12:1 | fn foo_new |
|
||||
| macro_expansion.rs:7:5:8:17 | (item with attribute macro expansion) | 0 | macro_expansion.rs:8:5:8:17 | fn inner_0 |
|
||||
| macro_expansion.rs:7:5:8:17 | (item with attribute macro expansion) | 0 | macro_expansion.rs:8:5:8:17 | fn inner_0 |
|
||||
| macro_expansion.rs:7:5:8:17 | (item with attribute macro expansion) | 1 | macro_expansion.rs:8:5:8:17 | fn inner_1 |
|
||||
| macro_expansion.rs:7:5:8:17 | (item with attribute macro expansion) | 1 | macro_expansion.rs:8:5:8:17 | fn inner_1 |
|
||||
| macro_expansion.rs:14:1:16:15 | (item with attribute macro expansion) | 0 | macro_expansion.rs:15:1:16:15 | (item with attribute macro expansion) |
|
||||
| macro_expansion.rs:14:1:16:15 | (item with attribute macro expansion) | 1 | macro_expansion.rs:15:1:16:15 | (item with attribute macro expansion) |
|
||||
| macro_expansion.rs:15:1:16:15 | (item with attribute macro expansion) | 0 | macro_expansion.rs:16:1:16:15 | fn bar_0 |
|
||||
| macro_expansion.rs:15:1:16:15 | (item with attribute macro expansion) | 0 | macro_expansion.rs:16:1:16:15 | fn bar_1 |
|
||||
| macro_expansion.rs:15:1:16:15 | (item with attribute macro expansion) | 1 | macro_expansion.rs:16:1:16:15 | fn bar_0_new |
|
||||
| macro_expansion.rs:15:1:16:15 | (item with attribute macro expansion) | 1 | macro_expansion.rs:16:1:16:15 | fn bar_1_new |
|
||||
| macro_expansion.rs:31:5:34:5 | (item with attribute macro expansion) | 0 | macro_expansion.rs:32:5:34:5 | fn bzz_0 |
|
||||
| macro_expansion.rs:31:5:34:5 | (item with attribute macro expansion) | 1 | macro_expansion.rs:32:5:34:5 | fn bzz_1 |
|
||||
| macro_expansion.rs:31:5:34:5 | (item with attribute macro expansion) | 2 | macro_expansion.rs:32:5:34:5 | fn bzz_2 |
|
||||
derive_macros
|
||||
| macro_expansion.rs:83:1:86:1 | struct MyDerive | 0 | 0 | macro_expansion.rs:84:8:85:9 | impl ...::Debug for MyDerive::<...> { ... } |
|
||||
| macro_expansion.rs:88:1:92:1 | enum MyDeriveEnum | 0 | 0 | macro_expansion.rs:89:6:91:12 | impl ...::PartialEq for MyDeriveEnum::<...> { ... } |
|
||||
@@ -46,8 +46,6 @@ macro_calls
|
||||
| macro_expansion.rs:79:12:79:20 | my_int!... | macro_expansion.rs:79:12:79:18 | i32 |
|
||||
unexpanded_macro_calls
|
||||
| included/included.rs:2:9:2:39 | concat!... |
|
||||
| macro_expansion.rs:5:9:5:35 | concat!... |
|
||||
| macro_expansion.rs:33:9:33:16 | hello!... |
|
||||
| macro_expansion.rs:56:9:56:31 | concat!... |
|
||||
| macro_expansion.rs:63:9:63:32 | include_str!... |
|
||||
warnings
|
||||
|
||||
@@ -5,7 +5,7 @@ lib.rs:
|
||||
# 1| getVisibility(): [Visibility] Visibility
|
||||
macro_in_library.rs:
|
||||
# 1| [SourceFile] SourceFile
|
||||
# 1| getItem(0): [MacroCall]
|
||||
# 1| getItem(0): [MacroCall] (item with attribute macro expansion)
|
||||
# 2| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 2| getItem(0): [Function] fn foo
|
||||
# 2| getParamList(): [ParamList] ParamList
|
||||
|
||||
7
rust/ql/test/library-tests/const_access/Cargo.lock
generated
Normal file
7
rust/ql/test/library-tests/const_access/Cargo.lock
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "test"
|
||||
version = "0.0.1"
|
||||
@@ -0,0 +1,8 @@
|
||||
testFailures
|
||||
constAccess
|
||||
| main.rs:17:13:17:24 | GLOBAL_CONST | main.rs:1:1:1:29 | Const |
|
||||
| main.rs:19:13:19:24 | STRING_CONST | main.rs:2:1:2:35 | Const |
|
||||
| main.rs:21:13:21:33 | ...::ASSOC_CONST | main.rs:9:5:9:33 | Const |
|
||||
| main.rs:23:13:23:35 | ...::MODULE_CONST | main.rs:13:5:13:38 | Const |
|
||||
| main.rs:25:8:25:19 | GLOBAL_CONST | main.rs:1:1:1:29 | Const |
|
||||
| main.rs:29:16:29:36 | ...::ASSOC_CONST | main.rs:9:5:9:33 | Const |
|
||||
21
rust/ql/test/library-tests/const_access/const_access.ql
Normal file
21
rust/ql/test/library-tests/const_access/const_access.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
import rust
|
||||
import utils.test.InlineExpectationsTest
|
||||
import TestUtils
|
||||
|
||||
query predicate constAccess(ConstAccess ca, Const c) { toBeTested(ca) and c = ca.getConst() }
|
||||
|
||||
module ConstAccessTest implements TestSig {
|
||||
string getARelevantTag() { result = "const_access" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(ConstAccess ca |
|
||||
toBeTested(ca) and
|
||||
location = ca.getLocation() and
|
||||
element = ca.toString() and
|
||||
tag = "const_access" and
|
||||
value = ca.getConst().getName().getText()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<ConstAccessTest>
|
||||
34
rust/ql/test/library-tests/const_access/main.rs
Normal file
34
rust/ql/test/library-tests/const_access/main.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
const GLOBAL_CONST: i32 = 42;
|
||||
const STRING_CONST: &str = "hello";
|
||||
|
||||
struct MyStruct {
|
||||
value: i32,
|
||||
}
|
||||
|
||||
impl MyStruct {
|
||||
const ASSOC_CONST: i32 = 100;
|
||||
}
|
||||
|
||||
mod my_module {
|
||||
pub const MODULE_CONST: i32 = 200;
|
||||
}
|
||||
|
||||
fn use_consts() {
|
||||
let x = GLOBAL_CONST; // $ const_access=GLOBAL_CONST
|
||||
|
||||
let s = STRING_CONST; // $ const_access=STRING_CONST
|
||||
|
||||
let y = MyStruct::ASSOC_CONST; // $ const_access=ASSOC_CONST
|
||||
|
||||
let z = my_module::MODULE_CONST; // $ const_access=MODULE_CONST
|
||||
|
||||
if GLOBAL_CONST > 0 { // $ const_access=GLOBAL_CONST
|
||||
println!("positive");
|
||||
}
|
||||
|
||||
let arr = [MyStruct::ASSOC_CONST; 5]; // $ const_access=ASSOC_CONST
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use_consts();
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
models
|
||||
edges
|
||||
| main.rs:9:13:9:19 | ...: ... | main.rs:10:11:10:11 | s | provenance | |
|
||||
| main.rs:10:11:10:11 | s | main.rs:9:30:14:1 | { ... } | provenance | |
|
||||
| main.rs:10:11:10:11 | s | main.rs:12:9:12:9 | s | provenance | |
|
||||
| main.rs:12:9:12:9 | s | main.rs:9:30:14:1 | { ... } | provenance | |
|
||||
| main.rs:21:9:21:9 | s | main.rs:22:10:22:10 | s | provenance | |
|
||||
| main.rs:21:13:21:21 | source(...) | main.rs:21:9:21:9 | s | provenance | |
|
||||
| main.rs:26:9:26:9 | s | main.rs:27:22:27:22 | s | provenance | |
|
||||
@@ -16,6 +17,7 @@ nodes
|
||||
| main.rs:9:13:9:19 | ...: ... | semmle.label | ...: ... |
|
||||
| main.rs:9:30:14:1 | { ... } | semmle.label | { ... } |
|
||||
| main.rs:10:11:10:11 | s | semmle.label | s |
|
||||
| main.rs:12:9:12:9 | s | semmle.label | s |
|
||||
| main.rs:17:10:17:18 | source(...) | semmle.label | source(...) |
|
||||
| main.rs:21:9:21:9 | s | semmle.label | s |
|
||||
| main.rs:21:13:21:21 | source(...) | semmle.label | source(...) |
|
||||
|
||||
@@ -82,12 +82,14 @@ localStep
|
||||
| main.rs:57:9:57:9 | a | main.rs:57:9:57:9 | [SSA] a |
|
||||
| main.rs:57:9:57:9 | a | main.rs:57:9:57:9 | a |
|
||||
| main.rs:57:13:59:5 | loop { ... } | main.rs:57:9:57:9 | a |
|
||||
| main.rs:57:18:59:5 | { ... } | main.rs:57:13:59:5 | loop { ... } |
|
||||
| main.rs:58:9:58:15 | break 1 | main.rs:57:13:59:5 | loop { ... } |
|
||||
| main.rs:58:15:58:15 | 1 | main.rs:58:9:58:15 | break 1 |
|
||||
| main.rs:61:9:61:9 | [SSA] b | main.rs:64:10:64:10 | b |
|
||||
| main.rs:61:9:61:9 | b | main.rs:61:9:61:9 | [SSA] b |
|
||||
| main.rs:61:9:61:9 | b | main.rs:61:9:61:9 | b |
|
||||
| main.rs:61:13:63:5 | loop { ... } | main.rs:61:9:61:9 | b |
|
||||
| main.rs:61:18:63:5 | { ... } | main.rs:61:13:63:5 | loop { ... } |
|
||||
| main.rs:62:9:62:23 | break ... | main.rs:61:13:63:5 | loop { ... } |
|
||||
| main.rs:62:15:62:23 | source(...) | main.rs:62:9:62:23 | break ... |
|
||||
| main.rs:68:9:68:13 | mut i | main.rs:68:13:68:13 | i |
|
||||
@@ -131,6 +133,7 @@ localStep
|
||||
| main.rs:92:9:92:9 | a | main.rs:92:9:92:9 | [SSA] a |
|
||||
| main.rs:92:9:92:9 | a | main.rs:92:9:92:9 | a |
|
||||
| main.rs:92:13:97:5 | 'block: { ... } | main.rs:92:9:92:9 | a |
|
||||
| main.rs:93:14:95:9 | { ... } | main.rs:93:9:95:9 | if b {...} |
|
||||
| main.rs:94:13:94:26 | break 'block 1 | main.rs:92:13:97:5 | 'block: { ... } |
|
||||
| main.rs:94:26:94:26 | 1 | main.rs:94:13:94:26 | break 'block 1 |
|
||||
| main.rs:96:9:96:9 | 2 | main.rs:92:13:97:5 | 'block: { ... } |
|
||||
@@ -143,6 +146,7 @@ localStep
|
||||
| main.rs:102:9:102:9 | a | main.rs:102:9:102:9 | [SSA] a |
|
||||
| main.rs:102:9:102:9 | a | main.rs:102:9:102:9 | a |
|
||||
| main.rs:102:13:107:5 | 'block: { ... } | main.rs:102:9:102:9 | a |
|
||||
| main.rs:103:14:105:9 | { ... } | main.rs:103:9:105:9 | if b {...} |
|
||||
| main.rs:104:13:104:26 | break 'block 1 | main.rs:102:13:107:5 | 'block: { ... } |
|
||||
| main.rs:104:26:104:26 | 1 | main.rs:104:13:104:26 | break 'block 1 |
|
||||
| main.rs:106:9:106:22 | break 'block 2 | main.rs:102:13:107:5 | 'block: { ... } |
|
||||
@@ -713,6 +717,7 @@ localStep
|
||||
| main.rs:480:16:480:19 | name | main.rs:480:16:480:19 | [SSA] name |
|
||||
| main.rs:480:16:480:19 | name | main.rs:480:16:480:19 | name |
|
||||
| main.rs:481:9:485:9 | if cond {...} | main.rs:480:31:486:5 | { ... } |
|
||||
| main.rs:481:17:485:9 | { ... } | main.rs:481:9:485:9 | if cond {...} |
|
||||
| main.rs:482:17:482:17 | [SSA] n | main.rs:483:18:483:18 | n |
|
||||
| main.rs:482:17:482:17 | n | main.rs:482:17:482:17 | [SSA] n |
|
||||
| main.rs:482:17:482:17 | n | main.rs:482:17:482:17 | n |
|
||||
|
||||
@@ -163,8 +163,9 @@ edges
|
||||
| main.rs:352:11:352:12 | s1 [A] | main.rs:356:11:356:12 | s1 [A] | provenance | |
|
||||
| main.rs:353:9:353:25 | ...::A(...) [A] | main.rs:353:24:353:24 | n | provenance | |
|
||||
| main.rs:353:24:353:24 | n | main.rs:353:35:353:35 | n | provenance | |
|
||||
| main.rs:356:11:356:12 | s1 [A] | main.rs:357:9:357:25 | ...::A(...) [A] | provenance | |
|
||||
| main.rs:356:11:356:12 | s1 [A] | main.rs:357:9:357:45 | ... \| ... [A] | provenance | |
|
||||
| main.rs:357:9:357:25 | ...::A(...) [A] | main.rs:357:24:357:24 | n | provenance | |
|
||||
| main.rs:357:9:357:45 | ... \| ... [A] | main.rs:357:9:357:25 | ...::A(...) [A] | provenance | |
|
||||
| main.rs:357:24:357:24 | n | main.rs:357:55:357:55 | n | provenance | |
|
||||
| main.rs:368:9:368:10 | s1 [A] | main.rs:370:11:370:12 | s1 [A] | provenance | |
|
||||
| main.rs:368:14:368:26 | A(...) [A] | main.rs:368:9:368:10 | s1 [A] | provenance | |
|
||||
@@ -173,8 +174,9 @@ edges
|
||||
| main.rs:370:11:370:12 | s1 [A] | main.rs:374:11:374:12 | s1 [A] | provenance | |
|
||||
| main.rs:371:9:371:12 | A(...) [A] | main.rs:371:11:371:11 | n | provenance | |
|
||||
| main.rs:371:11:371:11 | n | main.rs:371:22:371:22 | n | provenance | |
|
||||
| main.rs:374:11:374:12 | s1 [A] | main.rs:375:9:375:12 | A(...) [A] | provenance | |
|
||||
| main.rs:374:11:374:12 | s1 [A] | main.rs:375:9:375:19 | ... \| ... [A] | provenance | |
|
||||
| main.rs:375:9:375:12 | A(...) [A] | main.rs:375:11:375:11 | n | provenance | |
|
||||
| main.rs:375:9:375:19 | ... \| ... [A] | main.rs:375:9:375:12 | A(...) [A] | provenance | |
|
||||
| main.rs:375:11:375:11 | n | main.rs:375:29:375:29 | n | provenance | |
|
||||
| main.rs:389:9:389:10 | s1 [C] | main.rs:393:11:393:12 | s1 [C] | provenance | |
|
||||
| main.rs:389:14:391:5 | ...::C {...} [C] | main.rs:389:9:389:10 | s1 [C] | provenance | |
|
||||
@@ -183,8 +185,9 @@ edges
|
||||
| main.rs:393:11:393:12 | s1 [C] | main.rs:397:11:397:12 | s1 [C] | provenance | |
|
||||
| main.rs:394:9:394:38 | ...::C {...} [C] | main.rs:394:36:394:36 | n | provenance | |
|
||||
| main.rs:394:36:394:36 | n | main.rs:394:48:394:48 | n | provenance | |
|
||||
| main.rs:397:11:397:12 | s1 [C] | main.rs:398:9:398:38 | ...::C {...} [C] | provenance | |
|
||||
| main.rs:397:11:397:12 | s1 [C] | main.rs:398:9:398:71 | ... \| ... [C] | provenance | |
|
||||
| main.rs:398:9:398:38 | ...::C {...} [C] | main.rs:398:36:398:36 | n | provenance | |
|
||||
| main.rs:398:9:398:71 | ... \| ... [C] | main.rs:398:9:398:38 | ...::C {...} [C] | provenance | |
|
||||
| main.rs:398:36:398:36 | n | main.rs:398:81:398:81 | n | provenance | |
|
||||
| main.rs:409:9:409:10 | s1 [C] | main.rs:413:11:413:12 | s1 [C] | provenance | |
|
||||
| main.rs:409:14:411:5 | C {...} [C] | main.rs:409:9:409:10 | s1 [C] | provenance | |
|
||||
@@ -193,8 +196,9 @@ edges
|
||||
| main.rs:413:11:413:12 | s1 [C] | main.rs:417:11:417:12 | s1 [C] | provenance | |
|
||||
| main.rs:414:9:414:24 | C {...} [C] | main.rs:414:22:414:22 | n | provenance | |
|
||||
| main.rs:414:22:414:22 | n | main.rs:414:34:414:34 | n | provenance | |
|
||||
| main.rs:417:11:417:12 | s1 [C] | main.rs:418:9:418:24 | C {...} [C] | provenance | |
|
||||
| main.rs:417:11:417:12 | s1 [C] | main.rs:418:9:418:43 | ... \| ... [C] | provenance | |
|
||||
| main.rs:418:9:418:24 | C {...} [C] | main.rs:418:22:418:22 | n | provenance | |
|
||||
| main.rs:418:9:418:43 | ... \| ... [C] | main.rs:418:9:418:24 | C {...} [C] | provenance | |
|
||||
| main.rs:418:22:418:22 | n | main.rs:418:53:418:53 | n | provenance | |
|
||||
| main.rs:430:9:430:12 | arr1 [element] | main.rs:431:14:431:17 | arr1 [element] | provenance | |
|
||||
| main.rs:430:16:430:33 | [...] [element] | main.rs:430:9:430:12 | arr1 [element] | provenance | |
|
||||
@@ -443,6 +447,7 @@ nodes
|
||||
| main.rs:353:35:353:35 | n | semmle.label | n |
|
||||
| main.rs:356:11:356:12 | s1 [A] | semmle.label | s1 [A] |
|
||||
| main.rs:357:9:357:25 | ...::A(...) [A] | semmle.label | ...::A(...) [A] |
|
||||
| main.rs:357:9:357:45 | ... \| ... [A] | semmle.label | ... \| ... [A] |
|
||||
| main.rs:357:24:357:24 | n | semmle.label | n |
|
||||
| main.rs:357:55:357:55 | n | semmle.label | n |
|
||||
| main.rs:368:9:368:10 | s1 [A] | semmle.label | s1 [A] |
|
||||
@@ -454,6 +459,7 @@ nodes
|
||||
| main.rs:371:22:371:22 | n | semmle.label | n |
|
||||
| main.rs:374:11:374:12 | s1 [A] | semmle.label | s1 [A] |
|
||||
| main.rs:375:9:375:12 | A(...) [A] | semmle.label | A(...) [A] |
|
||||
| main.rs:375:9:375:19 | ... \| ... [A] | semmle.label | ... \| ... [A] |
|
||||
| main.rs:375:11:375:11 | n | semmle.label | n |
|
||||
| main.rs:375:29:375:29 | n | semmle.label | n |
|
||||
| main.rs:389:9:389:10 | s1 [C] | semmle.label | s1 [C] |
|
||||
@@ -465,6 +471,7 @@ nodes
|
||||
| main.rs:394:48:394:48 | n | semmle.label | n |
|
||||
| main.rs:397:11:397:12 | s1 [C] | semmle.label | s1 [C] |
|
||||
| main.rs:398:9:398:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
|
||||
| main.rs:398:9:398:71 | ... \| ... [C] | semmle.label | ... \| ... [C] |
|
||||
| main.rs:398:36:398:36 | n | semmle.label | n |
|
||||
| main.rs:398:81:398:81 | n | semmle.label | n |
|
||||
| main.rs:409:9:409:10 | s1 [C] | semmle.label | s1 [C] |
|
||||
@@ -476,6 +483,7 @@ nodes
|
||||
| main.rs:414:34:414:34 | n | semmle.label | n |
|
||||
| main.rs:417:11:417:12 | s1 [C] | semmle.label | s1 [C] |
|
||||
| main.rs:418:9:418:24 | C {...} [C] | semmle.label | C {...} [C] |
|
||||
| main.rs:418:9:418:43 | ... \| ... [C] | semmle.label | ... \| ... [C] |
|
||||
| main.rs:418:22:418:22 | n | semmle.label | n |
|
||||
| main.rs:418:53:418:53 | n | semmle.label | n |
|
||||
| main.rs:430:9:430:12 | arr1 [element] | semmle.label | arr1 [element] |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user