Merge remote-tracking branch 'upstream/main' into cert-checks

This commit is contained in:
Geoffrey White
2025-11-21 18:40:40 +00:00
892 changed files with 69976 additions and 39807 deletions

View File

@@ -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
View File

@@ -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

View File

@@ -0,0 +1,4 @@
---
dependencies: {}
compiled: false
lockVersion: 1.0.0

View File

@@ -0,0 +1,7 @@
name: codeql/rust-examples
groups:
- rust
- examples
dependencies:
codeql/rust-all: ${workspace}
warnOnImplicitThis: true

View 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."

View 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()

View 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"

View File

@@ -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
}

View File

@@ -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 |

View File

@@ -15,3 +15,5 @@ mod macros {
}
pub mod a_module;
pub extern crate self as extern_crate_alias;

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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

View 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.

View File

@@ -0,0 +1,5 @@
## 0.1.20
### Minor Analysis Improvements
* Added models for cookie methods in the `poem` crate.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.1.19
lastReleaseVersion: 0.1.20

View File

@@ -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);
}
}
}

View File

@@ -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.

View File

@@ -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
)

View File

@@ -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
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)
)

View File

@@ -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() =

View File

@@ -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" }
}

View File

@@ -0,0 +1,7 @@
/**
* This module provides the public class `ConstAccess`.
*/
private import internal.ConstImpl
final class ConstAccess = Impl::ConstAccess;

View File

@@ -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.

View File

@@ -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() }
}
}

View File

@@ -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" }
}
}

View File

@@ -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() }
/**

View File

@@ -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)" }
}
}

View File

@@ -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" }
}

View File

@@ -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))
}
}

View File

@@ -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.

View File

@@ -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 = "(...)"
}
}
}

View File

@@ -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 }

View File

@@ -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

View File

@@ -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()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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"]
)
}

View File

@@ -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"]

View 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"]

View File

@@ -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"]

View 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"]

View File

@@ -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.

View File

@@ -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()
}
}

View File

@@ -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
}

View File

@@ -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"]

View File

@@ -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

View File

@@ -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"]

View File

@@ -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)

View File

@@ -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

View File

@@ -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)
)
}
}

View File

@@ -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() + "]" }

View File

@@ -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()
}
}

View File

@@ -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 }
}
}

View File

@@ -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() }
}
/**

View File

@@ -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
)
}
}

View File

@@ -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)
)
}
}

View File

@@ -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

View File

@@ -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)
)
}

View File

@@ -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
}

View File

@@ -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
)
}
}

View File

@@ -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 }
}
/**

View File

@@ -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()
)
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 (

View File

@@ -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

View 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.

View File

@@ -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.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.1.19
lastReleaseVersion: 0.1.20

View File

@@ -1,5 +1,5 @@
name: codeql/rust-queries
version: 0.1.20-dev
version: 0.1.21-dev
groups:
- rust
- queries

View File

@@ -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) {

View File

@@ -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() }

View File

@@ -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
}

View File

@@ -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()

View File

@@ -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()
}
/**

View File

@@ -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()

View File

@@ -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

View File

@@ -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() }

View File

@@ -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 |

View File

@@ -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() {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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"

View File

@@ -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 |

View 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>

View 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();
}

View File

@@ -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(...) |

View File

@@ -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 |

View File

@@ -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