mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'main' into copilot/add-ecb-cbc-test-cases
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
description: Added the `@call_expr_base` union type
|
||||
compatibility: backwards
|
||||
|
||||
call_expr_arg_lists.rel: delete
|
||||
call_expr_attrs.rel: delete
|
||||
method_call_expr_arg_lists.rel: delete
|
||||
method_call_expr_attrs.rel: delete
|
||||
|
||||
call_expr_base_arg_lists.rel: run upgrade.ql call_expr_base_arg_lists
|
||||
call_expr_base_attrs.rel: run upgrade.ql call_expr_base_attrs
|
||||
@@ -0,0 +1,19 @@
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class ArgList extends Element, @arg_list { }
|
||||
|
||||
class Attr extends Element, @attr { }
|
||||
|
||||
query predicate call_expr_base_arg_lists(Element c, ArgList l) {
|
||||
call_expr_base_arg_lists(c, l)
|
||||
or
|
||||
method_call_expr_arg_lists(c, l)
|
||||
}
|
||||
|
||||
query predicate call_expr_base_attrs(Element c, int i, Attr a) {
|
||||
call_expr_attrs(c, i, a)
|
||||
or
|
||||
method_call_expr_attrs(c, i, a)
|
||||
}
|
||||
2
rust/extractor/src/generated/.generated.list
generated
2
rust/extractor/src/generated/.generated.list
generated
@@ -1,2 +1,2 @@
|
||||
mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7
|
||||
top.rs 460e827738766301a137f1750be7cd3016e6b7e4e487c6c95972bd3e1d21b814 460e827738766301a137f1750be7cd3016e6b7e4e487c6c95972bd3e1d21b814
|
||||
top.rs b829c8ab9ec5ff07b997b9ee0b2c333d63e24eddcf7c5fc2b95a9a7f17a84a69 b829c8ab9ec5ff07b997b9ee0b2c333d63e24eddcf7c5fc2b95a9a7f17a84a69
|
||||
|
||||
289
rust/extractor/src/generated/top.rs
generated
289
rust/extractor/src/generated/top.rs
generated
@@ -4315,44 +4315,66 @@ impl From<trap::Label<BreakExpr>> for trap::Label<Element> {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CallExprBase {
|
||||
_unused: ()
|
||||
pub struct CallExpr {
|
||||
pub id: trap::TrapId<CallExpr>,
|
||||
pub arg_list: Option<trap::Label<ArgList>>,
|
||||
pub attrs: Vec<trap::Label<Attr>>,
|
||||
pub function: Option<trap::Label<Expr>>,
|
||||
}
|
||||
|
||||
impl trap::TrapClass for CallExprBase {
|
||||
fn class_name() -> &'static str { "CallExprBase" }
|
||||
impl trap::TrapEntry for CallExpr {
|
||||
fn extract_id(&mut self) -> trap::TrapId<Self> {
|
||||
std::mem::replace(&mut self.id, trap::TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
|
||||
out.add_tuple("call_exprs", vec![id.into()]);
|
||||
if let Some(v) = self.arg_list {
|
||||
out.add_tuple("call_expr_arg_lists", vec![id.into(), v.into()]);
|
||||
}
|
||||
for (i, v) in self.attrs.into_iter().enumerate() {
|
||||
out.add_tuple("call_expr_attrs", vec![id.into(), i.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.function {
|
||||
out.add_tuple("call_expr_functions", vec![id.into(), v.into()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExprBase>> for trap::Label<Expr> {
|
||||
fn from(value: trap::Label<CallExprBase>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExprBase is a subclass of Expr
|
||||
impl trap::TrapClass for CallExpr {
|
||||
fn class_name() -> &'static str { "CallExpr" }
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExpr>> for trap::Label<Expr> {
|
||||
fn from(value: trap::Label<CallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExpr is a subclass of Expr
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExprBase>> for trap::Label<AstNode> {
|
||||
fn from(value: trap::Label<CallExprBase>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExprBase is a subclass of AstNode
|
||||
impl From<trap::Label<CallExpr>> for trap::Label<AstNode> {
|
||||
fn from(value: trap::Label<CallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExpr is a subclass of AstNode
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExprBase>> for trap::Label<Locatable> {
|
||||
fn from(value: trap::Label<CallExprBase>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExprBase is a subclass of Locatable
|
||||
impl From<trap::Label<CallExpr>> for trap::Label<Locatable> {
|
||||
fn from(value: trap::Label<CallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExpr is a subclass of Locatable
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExprBase>> for trap::Label<Element> {
|
||||
fn from(value: trap::Label<CallExprBase>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExprBase is a subclass of Element
|
||||
impl From<trap::Label<CallExpr>> for trap::Label<Element> {
|
||||
fn from(value: trap::Label<CallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExpr is a subclass of Element
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
@@ -6430,6 +6452,81 @@ impl From<trap::Label<MatchExpr>> for trap::Label<Element> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MethodCallExpr {
|
||||
pub id: trap::TrapId<MethodCallExpr>,
|
||||
pub arg_list: Option<trap::Label<ArgList>>,
|
||||
pub attrs: Vec<trap::Label<Attr>>,
|
||||
pub generic_arg_list: Option<trap::Label<GenericArgList>>,
|
||||
pub identifier: Option<trap::Label<NameRef>>,
|
||||
pub receiver: Option<trap::Label<Expr>>,
|
||||
}
|
||||
|
||||
impl trap::TrapEntry for MethodCallExpr {
|
||||
fn extract_id(&mut self) -> trap::TrapId<Self> {
|
||||
std::mem::replace(&mut self.id, trap::TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
|
||||
out.add_tuple("method_call_exprs", vec![id.into()]);
|
||||
if let Some(v) = self.arg_list {
|
||||
out.add_tuple("method_call_expr_arg_lists", vec![id.into(), v.into()]);
|
||||
}
|
||||
for (i, v) in self.attrs.into_iter().enumerate() {
|
||||
out.add_tuple("method_call_expr_attrs", vec![id.into(), i.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.generic_arg_list {
|
||||
out.add_tuple("method_call_expr_generic_arg_lists", vec![id.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.identifier {
|
||||
out.add_tuple("method_call_expr_identifiers", vec![id.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.receiver {
|
||||
out.add_tuple("method_call_expr_receivers", vec![id.into(), v.into()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl trap::TrapClass for MethodCallExpr {
|
||||
fn class_name() -> &'static str { "MethodCallExpr" }
|
||||
}
|
||||
|
||||
impl From<trap::Label<MethodCallExpr>> for trap::Label<Expr> {
|
||||
fn from(value: trap::Label<MethodCallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme MethodCallExpr is a subclass of Expr
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<MethodCallExpr>> for trap::Label<AstNode> {
|
||||
fn from(value: trap::Label<MethodCallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme MethodCallExpr is a subclass of AstNode
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<MethodCallExpr>> for trap::Label<Locatable> {
|
||||
fn from(value: trap::Label<MethodCallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme MethodCallExpr is a subclass of Locatable
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<MethodCallExpr>> for trap::Label<Element> {
|
||||
fn from(value: trap::Label<MethodCallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme MethodCallExpr is a subclass of Element
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NameRef {
|
||||
pub id: trap::TrapId<NameRef>,
|
||||
@@ -9242,82 +9339,6 @@ impl From<trap::Label<BlockExpr>> for trap::Label<Element> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CallExpr {
|
||||
pub id: trap::TrapId<CallExpr>,
|
||||
pub arg_list: Option<trap::Label<ArgList>>,
|
||||
pub attrs: Vec<trap::Label<Attr>>,
|
||||
pub function: Option<trap::Label<Expr>>,
|
||||
}
|
||||
|
||||
impl trap::TrapEntry for CallExpr {
|
||||
fn extract_id(&mut self) -> trap::TrapId<Self> {
|
||||
std::mem::replace(&mut self.id, trap::TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
|
||||
out.add_tuple("call_exprs", vec![id.into()]);
|
||||
if let Some(v) = self.arg_list {
|
||||
out.add_tuple("call_expr_base_arg_lists", vec![id.into(), v.into()]);
|
||||
}
|
||||
for (i, v) in self.attrs.into_iter().enumerate() {
|
||||
out.add_tuple("call_expr_base_attrs", vec![id.into(), i.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.function {
|
||||
out.add_tuple("call_expr_functions", vec![id.into(), v.into()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl trap::TrapClass for CallExpr {
|
||||
fn class_name() -> &'static str { "CallExpr" }
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExpr>> for trap::Label<CallExprBase> {
|
||||
fn from(value: trap::Label<CallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExpr is a subclass of CallExprBase
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExpr>> for trap::Label<Expr> {
|
||||
fn from(value: trap::Label<CallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExpr is a subclass of Expr
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExpr>> for trap::Label<AstNode> {
|
||||
fn from(value: trap::Label<CallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExpr is a subclass of AstNode
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExpr>> for trap::Label<Locatable> {
|
||||
fn from(value: trap::Label<CallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExpr is a subclass of Locatable
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<CallExpr>> for trap::Label<Element> {
|
||||
fn from(value: trap::Label<CallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme CallExpr is a subclass of Element
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExternBlock {
|
||||
pub id: trap::TrapId<ExternBlock>,
|
||||
@@ -9908,90 +9929,6 @@ impl From<trap::Label<MacroRules>> for trap::Label<Addressable> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MethodCallExpr {
|
||||
pub id: trap::TrapId<MethodCallExpr>,
|
||||
pub arg_list: Option<trap::Label<ArgList>>,
|
||||
pub attrs: Vec<trap::Label<Attr>>,
|
||||
pub generic_arg_list: Option<trap::Label<GenericArgList>>,
|
||||
pub identifier: Option<trap::Label<NameRef>>,
|
||||
pub receiver: Option<trap::Label<Expr>>,
|
||||
}
|
||||
|
||||
impl trap::TrapEntry for MethodCallExpr {
|
||||
fn extract_id(&mut self) -> trap::TrapId<Self> {
|
||||
std::mem::replace(&mut self.id, trap::TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
|
||||
out.add_tuple("method_call_exprs", vec![id.into()]);
|
||||
if let Some(v) = self.arg_list {
|
||||
out.add_tuple("call_expr_base_arg_lists", vec![id.into(), v.into()]);
|
||||
}
|
||||
for (i, v) in self.attrs.into_iter().enumerate() {
|
||||
out.add_tuple("call_expr_base_attrs", vec![id.into(), i.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.generic_arg_list {
|
||||
out.add_tuple("method_call_expr_generic_arg_lists", vec![id.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.identifier {
|
||||
out.add_tuple("method_call_expr_identifiers", vec![id.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.receiver {
|
||||
out.add_tuple("method_call_expr_receivers", vec![id.into(), v.into()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl trap::TrapClass for MethodCallExpr {
|
||||
fn class_name() -> &'static str { "MethodCallExpr" }
|
||||
}
|
||||
|
||||
impl From<trap::Label<MethodCallExpr>> for trap::Label<CallExprBase> {
|
||||
fn from(value: trap::Label<MethodCallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme MethodCallExpr is a subclass of CallExprBase
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<MethodCallExpr>> for trap::Label<Expr> {
|
||||
fn from(value: trap::Label<MethodCallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme MethodCallExpr is a subclass of Expr
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<MethodCallExpr>> for trap::Label<AstNode> {
|
||||
fn from(value: trap::Label<MethodCallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme MethodCallExpr is a subclass of AstNode
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<MethodCallExpr>> for trap::Label<Locatable> {
|
||||
fn from(value: trap::Label<MethodCallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme MethodCallExpr is a subclass of Locatable
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trap::Label<MethodCallExpr>> for trap::Label<Element> {
|
||||
fn from(value: trap::Label<MethodCallExpr>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme MethodCallExpr is a subclass of Element
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Module {
|
||||
pub id: trap::TrapId<Module>,
|
||||
|
||||
35
rust/ql/.generated.list
generated
35
rust/ql/.generated.list
generated
@@ -1,4 +1,4 @@
|
||||
lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 11c7521ec2231a4d0447f30fc3d0bb14aebb659bd8cf75935af1050673a3b1d6 d0a77b572a032e43f1c47622315c0cdfe17e68c2b057534b9322fc528029fb40
|
||||
lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 1eac5a95247dec5cf51a453788b5bdebcf612590014b1e28f6b6f7e841c96a20 d4d8c9664ca406c3fd14d96a488eea97c42401e2791f41d7248ee5d3f299805c
|
||||
lib/codeql/rust/elements/Abi.qll 485a2e79f6f7bfd1c02a6e795a71e62dede3c3e150149d5f8f18b761253b7208 6159ba175e7ead0dd2e3f2788f49516c306ee11b1a443bd4bdc00b7017d559bd
|
||||
lib/codeql/rust/elements/Addressable.qll 13011bfd2e1556694c3d440cc34af8527da4df49ad92b62f2939d3699ff2cea5 ddb25935f7553a1a384b1abe2e4b4fa90ab50b952dadec32fd867afcb054f4be
|
||||
lib/codeql/rust/elements/Adt.qll c2afed4ac2e17039ccd98f74ea22111f4d765c4e232c50ccd3128da0d26da837 1380bde2eb667c6ec2ef5f8710aa24e926851c9e321ebc72ba514fa92c369dc3
|
||||
@@ -32,8 +32,7 @@ lib/codeql/rust/elements/BinaryExpr.qll 394522da3bc3a716fc7bc40c3560143ca840f5d2
|
||||
lib/codeql/rust/elements/BlockExpr.qll b5cf57119b15f27d0bc258dfa375b0ef2730c157870ff543f0dc7a8cfe514182 f6a01999606b010c81ef9c6ff1385e6640632b6f5ce067ffeb0ef0af0a0aeb92
|
||||
lib/codeql/rust/elements/BoxPat.qll 1b2c3fff171aa6aa238c9460b122f26c79e04577cea67fa856de99842ba873d4 0caf8d23ed6e0997a6b8751def27641582151fba6e24fccf798712a4690b42f1
|
||||
lib/codeql/rust/elements/BreakExpr.qll 7ca3807a20e9a9a988d1fd7abebf240325ed422fcb45c719ba46272f031f94db dffb7379d3f3ba220acfbd05eb7bb6cfd9cfda211e9c8b1f5240ca5fa61be3fc
|
||||
lib/codeql/rust/elements/CallExpr.qll f336500ca7a611b164d48b90e80edb0c0d3816792b0ececce659ac1ff1ffeb3e f99a9c55466418ef53860c44d9f2d6161af4b492178ddd9e5870dff742b70ae5
|
||||
lib/codeql/rust/elements/CallExprBase.qll 2846202b5208b541977500286951d96487bf555838c6c16cdd006a71e383745a c789d412bf099c624329379e0c7d94fa0d23ae2edea7a25a2ea0f3c0042ccf62
|
||||
lib/codeql/rust/elements/CallExpr.qll ee3997f265dc1b6b2fc7134548dd88d509b6bcbc26cf65061a31980f9900ae26 7e86e0ab24ce78c3f592a5614eac083d00f331664f021a438f74e2e0785f4609
|
||||
lib/codeql/rust/elements/Callable.qll 08a46e987b8fde29069795a536fcd1ad1a96f60341f72293e4d07e20334d554f cfc2be9287000718e5ff3c2a35bb45ffc93fd36d97f2e034888e9aa2ae9af555
|
||||
lib/codeql/rust/elements/CastExpr.qll 2fe1f36ba31fa29de309baf0a665cfcae67b61c73345e8f9bbd41e8c235fec45 c5b4c1e9dc24eb2357799defcb2df25989075e3a80e8663b74204a1c1b70e29a
|
||||
lib/codeql/rust/elements/ClosureExpr.qll 69e0b7a7c7a4c348fcada5ad4da22dd2f51747109f856be239cede315a56d695 93400650282e2d4e682b826e9f5f844aa893dda126548e41ea1c703d2bf209ca
|
||||
@@ -103,7 +102,7 @@ lib/codeql/rust/elements/MatchArmList.qll f221c5e344814fa44db06ab897afdc249e8e88
|
||||
lib/codeql/rust/elements/MatchExpr.qll e9ef1664f020823b6f4bb72d906a9dc0c1ee6432d4a9a13f7dbdbab2b2b1ee4d 38d71e5c487abcb5682293c573343be66e499a6e131bb630604c120d34b7777b
|
||||
lib/codeql/rust/elements/MatchGuard.qll 58256689a90f24b16401543452c2a32f00d619ddac6c0fe8b65a8cd3e46401bb 8efb2ac03c69a9db687e382331085d7a6cfbf8eca559174ba2727a9549ec7ddd
|
||||
lib/codeql/rust/elements/Meta.qll b17d7bf605bd0cf4f6d6c6cf4f39a16cfc431d256d45b93663a7569181d36168 815cdfef06231de4b4b1c85e321b8ccb3e22379e5a4e111df9cc9ca6be593841
|
||||
lib/codeql/rust/elements/MethodCallExpr.qll 91b411e0fb1a0547dcad8726db460dccc61bed972741598d5cb3740593fe75a7 538d23b6db115bb699389d29a1829bb0449c08424a1fff80377828eb7ceb2563
|
||||
lib/codeql/rust/elements/MethodCallExpr.qll 914633f304c587addced988a7f161a1a4b3297ce370f6a959b7a042b1c04dace 289a0854d6323df915ee5f268523ee597ba20a37c646bbb2a79c9ed1f7aa2260
|
||||
lib/codeql/rust/elements/Missing.qll 70e6ac9790314752849c9888443c98223ccfc93a193998b7ce350b2c6ebe8ea4 e2f0623511acaa76b091f748d417714137a8b94f1f2bdbbd177f1c682c786dad
|
||||
lib/codeql/rust/elements/Module.qll 0bc85019177709256f8078d9de2a36f62f848d476225bff7bba1e35f249875c7 3fbb70e0c417a644dd0cada2c364c6e6876cfa16f37960e219c87e49c966c94e
|
||||
lib/codeql/rust/elements/Name.qll af41479d4260fe931d46154dda15484e4733c952b98f0e370106e6e9e8ce398b e188a0d0309dd1b684c0cb88df435b38e306eb94d6b66a2b748e75252f15e095
|
||||
@@ -160,8 +159,8 @@ lib/codeql/rust/elements/Trait.qll f78a917c2f2e5a0dfcd7c36e95ad67b1fa218484ee509
|
||||
lib/codeql/rust/elements/TraitAlias.qll 1d82d043f24dbac04baa7aa3882c6884b8ffbc5d9b97669ce8efb7e2c8d3d2c8 505ba5426e87b3c49721f440fbc9ad6b0e7d89d1b1a51ca3fa3a6cc2d36f8b82
|
||||
lib/codeql/rust/elements/TryExpr.qll cb452f53292a1396139f64a35f05bb11501f6b363f8affc9f2d5f1945ad4a647 d60ad731bfe256d0f0b688bdc31708759a3d990c11dee4f1d85ccc0d9e07bec9
|
||||
lib/codeql/rust/elements/TupleExpr.qll 1b1be270198f9d3db1c28c4caaa4a7fe9b5ae14651f1a10e2891a7d78d6ad18b 4f585aa684dfbff753e342903ddd60ee4d7c374b8bddeb645784d10903c90ae0
|
||||
lib/codeql/rust/elements/TupleField.qll e20a991f7f1322cc7c05b2a8946d5017edb119812efa3e44daa94a5dff2d0c7b 8c25c9577fef8b5b9a4b285ceb7cfffcd8d89448035b1967cd7fda1503adfe13
|
||||
lib/codeql/rust/elements/TupleFieldList.qll b67cd2dec918d09e582467e5db7a38c8fa18350af591b43a1b450cd2026dbb67 22fdd1e77c16e3be4627ee7a45985b94785492d36056eeeff2c94b43450b48c8
|
||||
lib/codeql/rust/elements/TupleField.qll 8d6288fd79959d5ef3732397c0a05a47fcb09091383058d1dba7268a950f8c32 1518cdd0fd9746d09fcdbecabc2a3ce6b36b6d983883850beed3f55c2bdf2c16
|
||||
lib/codeql/rust/elements/TupleFieldList.qll 2fa47599f78aa4639a40239cf49bc2f97d84118125b949c71fec4390589caaf0 3f71a86e38bdc6fe9f0c082a43d763c4f34b4bdab99c383cdc5d8b59e887cee0
|
||||
lib/codeql/rust/elements/TuplePat.qll 028cdea43868b0fdd2fc4c31ff25b6bbb40813e8aaccf72186051a280db7632e 38c56187971671e6a9dd0c6ccccb2ee4470aa82852110c6b89884496eb4abc64
|
||||
lib/codeql/rust/elements/TupleStructPat.qll da398a23eb616bf7dd586b2a87f4ab00f28623418f081cd7b1cc3de497ef1819 6573bf3f8501c30af3aeb23d96db9f5bea7ab73e2b7ef3473095c03e96c20a5c
|
||||
lib/codeql/rust/elements/TupleTypeRepr.qll 1ac5abf6281ea31680a4098407fbe55459d08f92a50dec20d1f8b93d498eee41 6d9625cce4e4abf6b6e6c22e47880fbd23740d07b621137bd7fa0a2ee13badd9
|
||||
@@ -406,7 +405,7 @@ lib/codeql/rust/elements/internal/TupleExprConstructor.qll 71c38786723225d3d9039
|
||||
lib/codeql/rust/elements/internal/TupleExprImpl.qll daabbc7dd36c615cdd8d3b59e06f4992a302b26554115711f733508836887abe 4c43a26e5f8b68d9d032bb5cd0af88cf9ac9b4b4e40af47dc85dd931ce9db6f8
|
||||
lib/codeql/rust/elements/internal/TupleFieldConstructor.qll 89d3cf2540235044ed5a89706cfbdebc5cdf9180fd5b6d3376c79a1b2c0430c0 16861fe089aac8e42a5a90d81dd48d5015391d0a06c78ca02bd876d65378699f
|
||||
lib/codeql/rust/elements/internal/TupleFieldListConstructor.qll 4335ba2061b6e4968db9ec05c0b4d3e6a564db89a2df69e036f317672a7900b1 0b8dded875dbf696cf588e8c21acc27332a2ff66ced7bfabdfc1ad621991f888
|
||||
lib/codeql/rust/elements/internal/TupleFieldListImpl.qll 74869e92a3cbdd7895adaaa418d29d5e97387daf46c17315f219ad967af15d76 5815e4b37db958663df1f6fedc9667a11b261c9c2133e3f983a3aedc452c01fc
|
||||
lib/codeql/rust/elements/internal/TupleFieldListImpl.qll 2e5141d5894d1cebadef9cd3afe7585779327c4e24390201e1ef05a29401caf8 bbfa1e0b513393012bf2ae43a3aa0e33fce6ea4d110d1be0f039562071f3c547
|
||||
lib/codeql/rust/elements/internal/TuplePatConstructor.qll 2a5e83ad5b8713a732e610128aeddf14e9b344402d6cf30ff0b43aa39e838418 6d467f7141307523994f03ed7b8e8b1a5bcf860963c9934b90e54582ea38096a
|
||||
lib/codeql/rust/elements/internal/TupleStructPatConstructor.qll 9d68f67a17a5cec0e78907a53eccfa7696be5b0571da4b486c8184274e56344a 3ffa29f546cd6c644be4fecc7415477a3a4dc00d69b8764be9119abe4c6d8b9e
|
||||
lib/codeql/rust/elements/internal/TupleTypeReprConstructor.qll 80c31c25fd27e330690fb500d757a4bbd33f226186d88ea73bfe4cf29a7db508 d572a72fa361990a3d0a3f9b81d1e966e2ba1ac0a60314ec824c1b8b2814c857
|
||||
@@ -434,7 +433,6 @@ lib/codeql/rust/elements/internal/VariantConstructor.qll 0297d4a9a9b32448d6d6063
|
||||
lib/codeql/rust/elements/internal/VariantListConstructor.qll c841fb345eb46ea3978a0ed7a689f8955efc9178044b140b74d98a6bcd0c926a c9e52d112abdba2b60013fa01a944c8770766bf7368f9878e6b13daaa4eed446
|
||||
lib/codeql/rust/elements/internal/VariantListImpl.qll 4ceeda617696eb547c707589ba26103cf4c5c3d889955531be24cbf224e79dff 4258196c126fd2fad0e18068cb3d570a67034a8b26e2f13f8223d7f1a246d1a4
|
||||
lib/codeql/rust/elements/internal/VisibilityConstructor.qll 1fd30663d87945f08d15cfaca54f586a658f26b7a98ea45ac73a35d36d4f65d0 6ddaf11742cc8fbbe03af2aa578394041ae077911e62d2fa6c885ae0543ba53a
|
||||
lib/codeql/rust/elements/internal/VisibilityImpl.qll 85c1e75d6a7f9246cfef5c261e2aea40891c016724de49b3d6632623ccc30dcf 278be4648a8aefb0d926480c4d98e1605196ad64d1e4dbad42aa58499e6d485d
|
||||
lib/codeql/rust/elements/internal/WhereClauseConstructor.qll 6d6f0f0376cf45fac37ea0c7c4345d08718d2a3d6d913e591de1de9e640317c9 ff690f3d4391e5f1fae6e9014365810105e8befe9d6b52a82625994319af9ffd
|
||||
lib/codeql/rust/elements/internal/WhereClauseImpl.qll 006e330df395183d15896e5f81128e24b8274d849fe45afb5040444e4b764226 ed5e8317b5f33104e5c322588dc400755c8852bbb77ef835177b13af7480fd43
|
||||
lib/codeql/rust/elements/internal/WherePredConstructor.qll f331c37085792a01159e8c218e9ef827e80e99b7c3d5978b6489808f05bd11f8 179cad3e4c5aaaf27755891694ef3569322fcf34c5290e6af49e5b5e3f8aa732
|
||||
@@ -479,8 +477,7 @@ lib/codeql/rust/elements/internal/generated/BinaryExpr.qll 64e9bd9c571edd6e5f3e7
|
||||
lib/codeql/rust/elements/internal/generated/BlockExpr.qll 5a5ddbe34bc478a7bd9b0d07d3b6f017c2d1f20581d859251a963314e6514d1f 9804c30b8b279038b864c52557535f854bd012bacdfe8e5840f1f777c74e52df
|
||||
lib/codeql/rust/elements/internal/generated/BoxPat.qll 597bed52f7489e0addce3266f7bee5be7c53d2d1263eceec3a252d041ca0908f b8ccf363ca5f1a988547caf1fd266a55aec7cbf8623578deea99765d264b0151
|
||||
lib/codeql/rust/elements/internal/generated/BreakExpr.qll 0f428a8b2f4209b134c2ffc3e1c93c30bc6b0e9c9172f140cefa88c1f77d8690 957b39f38ff6befe9061f55bc0b403c2f1c366dd0cf63b874bae6f8216576d76
|
||||
lib/codeql/rust/elements/internal/generated/CallExpr.qll f1b8dae487077cc9d1dccf8c3cd61fd17afe860585f17ce8b860be4859be7ca4 6034fc03778e38802cdf3a6e460364b74e92912622581b31e6179951022bbbd6
|
||||
lib/codeql/rust/elements/internal/generated/CallExprBase.qll 2268e01d65015014c05166161bb28e5a1e78164d525ca16fc1e3106866cf231d b2f9b912153ba4d3e3612df4f74ac0e83077c31d5b31383bd277974081417a56
|
||||
lib/codeql/rust/elements/internal/generated/CallExpr.qll 6096035ba2ef1ce3e6254d5b8497dcb6cd7570253423c778a9dd7e158f928644 e56caf9ba094ddfc4952ed5072c5f6f139db8029fa6bd6328d1a118e96a1d5fe
|
||||
lib/codeql/rust/elements/internal/generated/Callable.qll 12368b998c771c6b80f54123cea4d3600af7432ab34c9e571bc0bf3894ceb17e 273a9fd9cdae56cf2edbdc9c49b15da49cd5ad04be70acbbe2475c9c50200183
|
||||
lib/codeql/rust/elements/internal/generated/CastExpr.qll ddc20054b0b339ad4d40298f3461490d25d00af87c876da5ffbc6a11c0832295 f4247307afcd74d80e926f29f8c57e78c50800984483e6b6003a44681e4a71f3
|
||||
lib/codeql/rust/elements/internal/generated/ClosureExpr.qll 818aff75d86821c670d8ba0720c3270681b3e070140a9c41beab2a811b43eee6 9bf2d1d38f6c4a99d7c058f8ed096141f5ba6a75d2d26a464f0d65ed4e554222
|
||||
@@ -551,7 +548,7 @@ lib/codeql/rust/elements/internal/generated/MatchArmList.qll 12d969ecb267a749918
|
||||
lib/codeql/rust/elements/internal/generated/MatchExpr.qll b686842e7000fd61e3a0598bf245fb4e18167b99eca9162fdfdff0b0963def22 00f1743b1b0f1a92c5a687f5260fda02d80cc5871694cad0d5e7d94bac7fe977
|
||||
lib/codeql/rust/elements/internal/generated/MatchGuard.qll 58fa1d6979ef22de2bd68574c7ffcf4a021d7543445f68834d879ff8cee3abcb 072f22a7929df3c0e764b2a770b4cdf03504b3053067d9b9008d6655fb5837e1
|
||||
lib/codeql/rust/elements/internal/generated/Meta.qll 15e98e8d38f5618b7053057a629b135aae5e105fbf72731833a644fb695244c0 2977b6a0781c89383e87c595b14a39851f27b2508296f3e77466eea44c916188
|
||||
lib/codeql/rust/elements/internal/generated/MethodCallExpr.qll 0cd0f84147e5f3887d609cc58246eb493d3461aee00ff37e7d26282c835f73af 6f4c5dc1decbce54fc12300d34798b890a85129208b25565130205c9d8ee2e29
|
||||
lib/codeql/rust/elements/internal/generated/MethodCallExpr.qll ffce98a6a1921822b12ead721cff0878553eb3e049c5d2184a7abce32b6615b4 d1408a0f47ee5764fe7b484494daf6e1f99b1c6a505274c48545b3e650ef8baf
|
||||
lib/codeql/rust/elements/internal/generated/Missing.qll 16735d91df04a4e1ae52fae25db5f59a044e540755734bbab46b5fbb0fe6b0bd 28ca4e49fb7e6b4734be2f2f69e7c224c570344cc160ef80c5a5cd413e750dad
|
||||
lib/codeql/rust/elements/internal/generated/Module.qll ebae5d8963c9fd569c0fbad1d7770abd3fd2479437f236cbce0505ba9f9af52c fa3c382115fed18a26f1a755d8749a201b9489f82c09448a88fb8e9e1435fe5f
|
||||
lib/codeql/rust/elements/internal/generated/Name.qll e6bd6240a051383a52b21ab539bc204ce7bcd51a1a4379e497dff008d4eef5b4 578a3b45e70f519d57b3e3a3450f6272716c849940daee49889717c7aaa85fc9
|
||||
@@ -566,7 +563,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 f04ca3d02170f7e532a480cc81748cf04f1b022d5e0e32ffcdf0f15c8f1961aa 999104d69a5435c9cab594e04b82ed26ae38b1b1d2ac1dbbb315a433c586f941
|
||||
lib/codeql/rust/elements/internal/generated/ParentChild.qll 8a6e4335bcf6f7d72f5ed6ffba5448ae88b00323fe7dac6f406c8746c03ef2dc 867a0fb166b53d7a8218a02d671f117ba7ea4e67cb16abeea6e746dc5823b85e
|
||||
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
|
||||
@@ -581,7 +578,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 14758dc2e2a9af251f24e24516eab0fc95d334c1da06f418ea5da3c5521642c9 a8b6637f57293a85714cc8761f8fd1e23780d58f3873acaa3c77acd9cbfcf19f
|
||||
lib/codeql/rust/elements/internal/generated/Raw.qll f207067167f8597ddf6de483372fc9e281d1661d3fc0a5da0d6d6bd7e32aa9c7 1c27c65c3ab4d07553bbd269c6737576feca3f5c29c8b02f81a0d65c209d4621
|
||||
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
|
||||
@@ -606,7 +603,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 a8ea364358a2bc3a9226d451c0867e89c29509a0f54dd88ed23c77045db2c85a a44de5e84a63cb5a1bfa66b0df33bf28c9f8b6628393d0f3b2f6215dabee47bd
|
||||
lib/codeql/rust/elements/internal/generated/Synth.qll 61147c264e863dc5234b391ad2b7a01e0a2fe99e18ea237ba06e31340fd0a50a 6d33624a9b571d05aba1e9459a211f75b762e72fa716259abcd994f5098e15a6
|
||||
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
|
||||
@@ -614,8 +611,8 @@ lib/codeql/rust/elements/internal/generated/Trait.qll 8fa41b50fa0f68333534f2b66b
|
||||
lib/codeql/rust/elements/internal/generated/TraitAlias.qll 40a296cf89eceaf02a32db90acb42bdc90df10e717bae3ab95bc09d842360a5b af85cf1f8fa46a8b04b763cdcacc6643b83c074c58c1344e485157d2ceb26306
|
||||
lib/codeql/rust/elements/internal/generated/TryExpr.qll 73052d7d309427a30019ad962ee332d22e7e48b9cc98ee60261ca2df2f433f93 d9dd70bf69eaa22475acd78bea504341e3574742a51ad9118566f39038a02d85
|
||||
lib/codeql/rust/elements/internal/generated/TupleExpr.qll 98f10bc72d09f98e3be87f41b1a3cbf037f4a7e3d3560dfa6d5759905a8177a5 6a9eb5568c518876b2912371e2b7b774cf5245097c5a0206eda35b749995f00b
|
||||
lib/codeql/rust/elements/internal/generated/TupleField.qll d546b4e0c1a0b243c2bf88b371377cf9a396ca497cd5e78915e0e552910b6093 c0a754d15e0de590ee15139d8d366e4d7e4d33882c943e6ea8fa5fa8dce790e3
|
||||
lib/codeql/rust/elements/internal/generated/TupleFieldList.qll fb76d1a395326361859177c05e90e5bbb22d37518758752e9d89906006fb683e f31508b120c36f569cc7dcae06c9e55cf875abfb2fbe54a64ec12d8b3d2db108
|
||||
lib/codeql/rust/elements/internal/generated/TupleField.qll 121f7b35e28b86592f83e00993f9041acbe7ab636db894d03055149c7f15fd32 b1ba9e1182307a44bb5afc11e92d62e7eb2c819ccdfb28ef54943b6fec676827
|
||||
lib/codeql/rust/elements/internal/generated/TupleFieldList.qll e7874518ce353f58312b02fb646f19eb109b3d868f8b550c84b7d6fc3a85fd5a f4bff793bbdbc252688296953116146f5c9a0894e14a7d3e4883a5ac211c122f
|
||||
lib/codeql/rust/elements/internal/generated/TuplePat.qll 4e13b509e1c9dd1581a9dc50d38e0a6e36abc1254ea9c732b5b3e6503335afeb 298028df9eb84e106e625ed09d6b20038ad47bfc2faf634a0ffea50b17b5805d
|
||||
lib/codeql/rust/elements/internal/generated/TupleStructPat.qll 6539d0edbdc16e7df849514d51980d4cd1a2c9cbb58ca9e5273851f96df4eb36 45a13bae5220d5737cbd04713a17af5b33d8bb4cfdf17ddd64b298ab0c1eea24
|
||||
lib/codeql/rust/elements/internal/generated/TupleTypeRepr.qll 1756cdbad56d634bf4726bc39c768386754e62650492d7d6344012038236a05b 3ac0997a47f95f28cc70c782173ce345fcb5b073be10f3c0b414d1df8443e04c
|
||||
@@ -643,7 +640,7 @@ lib/codeql/rust/elements/internal/generated/WhileExpr.qll 0353aab87c49569e1fbf58
|
||||
lib/codeql/rust/elements/internal/generated/WildcardPat.qll d74b70b57a0a66bfae017a329352a5b27a6b9e73dd5521d627f680e810c6c59e 4b913b548ba27ff3c82fcd32cf996ff329cb57d176d3bebd0fcef394486ea499
|
||||
lib/codeql/rust/elements/internal/generated/YeetExpr.qll cac328200872a35337b4bcb15c851afb4743f82c080f9738d295571eb01d7392 94af734eea08129b587fed849b643e7572800e8330c0b57d727d41abda47930b
|
||||
lib/codeql/rust/elements/internal/generated/YieldExpr.qll 37e5f0c1e373a22bbc53d8b7f2c0e1f476e5be5080b8437c5e964f4e83fad79a 4a9a68643401637bf48e5c2b2f74a6bf0ddcb4ff76f6bffb61d436b685621e85
|
||||
lib/codeql/rust/elements.qll d3beb3a35f2b5ea47d60aeefd86fb0d6406dd0a1b7cd89aecbb2732b4e72da38 d3beb3a35f2b5ea47d60aeefd86fb0d6406dd0a1b7cd89aecbb2732b4e72da38
|
||||
lib/codeql/rust/elements.qll 5cc722db81259ee5d5b9cbed1a4d2795060ad996c80fd7121e7ce43dc392b62f 5cc722db81259ee5d5b9cbed1a4d2795060ad996c80fd7121e7ce43dc392b62f
|
||||
test/extractor-tests/generated/Abi/Abi.ql 086ed104ab1a7e7fe5c1ed29e03f1719a797c7096c738868bf6ebe872ab8fdaa fe23fe67ab0d9201e1177ea3f844b18ed428e13e3ce77381bf2b6910adfa3a0e
|
||||
test/extractor-tests/generated/ArgList/ArgList.ql da97b5b25418b2aa8cb8df793f48870c89fa00759cdade8ddba60d7f1f4bbc01 acfd5d2caf67282ad2d57b961068472100482d0f770a52a3c00214c647d18c75
|
||||
test/extractor-tests/generated/ArrayListExpr/ArrayListExpr.ql 42b365276aa43e2cad588338463542d3ce1dd0db3a428621554584b07a1431d5 08a66a8b69af35ee3bc64c35c453a19a6c9881cc6cc7e65275d1fff056121270
|
||||
@@ -669,7 +666,7 @@ test/extractor-tests/generated/BinaryExpr/BinaryExpr.ql 4e849e6eaae581f487aa74d0
|
||||
test/extractor-tests/generated/BlockExpr/BlockExpr.ql cd6ef66de9e56ebb74964e59617d47999fb8c9081e885acece17a3b747a35ae1 6766844c1b87e518688565f2469575af5ca4e0ff4eb0c0b620df73a451d86a0b
|
||||
test/extractor-tests/generated/BoxPat/BoxPat.ql 854c9ba4e045dbe7ea1666866c1c443a92597df0ce02f4ca5993142925941c39 a22c17cce0bff7d1df51b817d2cb1a61045357f91be14465166971efa5f5daad
|
||||
test/extractor-tests/generated/BreakExpr/BreakExpr.ql c2181211da3dfe983cfca93ead32d5d211e91181899b9477152c58124eaa846d 57e57b926e14db2efb2e88e04699608b2ba9797ee4f6c4f710135b6858982256
|
||||
test/extractor-tests/generated/CallExpr/CallExpr.ql 2a1cd4485ccd8d4eb24a75889e832612adef9bb7feae414c90572796380bc6d7 95060b92aa04d7ad1fc6603c5ec14a275a5788ecb5a19932732e28105607a3b7
|
||||
test/extractor-tests/generated/CallExpr/CallExpr.ql 16d85d6e5cb68384d0b932fb4506c1855019b819f2c5faa39a4472f39427623a 14df8383948cedaff88f514f7239c1ec8c424720d24e3546cbcd0b689acecdb1
|
||||
test/extractor-tests/generated/CastExpr/CastExpr.ql 3480ec51072399409b7553ab6139c832db6ed4ca991f3a7a2282a39afe07c6f2 614c8ea7a2fe30d57583dbf84ed7a12743c2aba49d8c6252d31af3ed10853a39
|
||||
test/extractor-tests/generated/ClosureExpr/ClosureExpr.ql 675ae07193241fbd710ece4f74f86e9b00f47841299b1c5934f55dbf13a4b4af 21fb0664619c9c889e9491bfd651c2814dcf0f158dd6269937bd0acc18be6b0e
|
||||
test/extractor-tests/generated/Comment/Comment.ql 0e0454911d2cf2e7ef5c6d860b84c57b9d490090914ebcf4fa0e8a70f777f066 cbd1c195276ef163f8d3c122344738c884dc9fb70eb2f9b7067829d735d48c4c
|
||||
@@ -728,7 +725,7 @@ test/extractor-tests/generated/MatchArmList/MatchArmList.ql bbc679fe6d8dedf9131d
|
||||
test/extractor-tests/generated/MatchExpr/MatchExpr.ql b75a5936401bb5ca38686f1413f5c8267ad685722560a2e9041dacf2f8d54abc 7da57118fe5b1f7f5cbe8d6b5f3ae70816fd4837b1c2e6401b98175b36ca233f
|
||||
test/extractor-tests/generated/MatchGuard/MatchGuard.ql 91de18a0a18d120db568b2c329e5cb26f83e327cf22c5825c555ea17249d7d23 0bcdb25895362128517227c860b9dad76851215c2cdf9b2d0e5cc3534278f4ec
|
||||
test/extractor-tests/generated/Meta/Meta.ql 43dd1cd669099b38396b316616992af6d84b0c1cee953b19235a00ab3d3bb43c 80b1885809aa074357e21707d1f8c6dca19f0b968ccff43229bb0d5c6fffb2b2
|
||||
test/extractor-tests/generated/MethodCallExpr/MethodCallExpr.ql 05ca29fdab8ce600469728b964c369368e5097b2a5eb35b84a7630ef044ac6b6 aa45fdbb7fba8afee9f6cef10d337622429d3f0fb71f7fbf861afb4906bdef71
|
||||
test/extractor-tests/generated/MethodCallExpr/MethodCallExpr.ql 9d5af6b4771a8725fa5b56ccb3e2a33158b18c876546b88e6dc63da1f887910a 494c8c2fe5584aac45c828b38d8bb20c113927a1e909773d4a2dbd3965d26170
|
||||
test/extractor-tests/generated/Module/Module.ql d7c442fd1b1f4f00da87e2228fc1aeeab0bb86648b2aa06a9dd6f40dbae1ee28 3229388727d14048e87238bcda5fde1bed503e5cac088922381e5833cfc32fa9
|
||||
test/extractor-tests/generated/Name/Name.ql b2fe417f7c816f71d12622b4f84ece74eba3c128c806266a55b53f8120fa4fb3 8bc65bbf3f2909637485f5db7830d6fc110a94c9b12eefe12d7627f41eae2256
|
||||
test/extractor-tests/generated/NameRef/NameRef.ql 210a70e0957f3444195eed3a3dfbb5806e349238c0b390dc00597e6b8b05fcec d74fbce3c71aa7b08ae4cb646ccb114335767cb4fe000322f9dd371c1bb3784f
|
||||
|
||||
3
rust/ql/.gitattributes
generated
vendored
3
rust/ql/.gitattributes
generated
vendored
@@ -35,7 +35,6 @@
|
||||
/lib/codeql/rust/elements/BoxPat.qll linguist-generated
|
||||
/lib/codeql/rust/elements/BreakExpr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/CallExpr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/CallExprBase.qll linguist-generated
|
||||
/lib/codeql/rust/elements/Callable.qll linguist-generated
|
||||
/lib/codeql/rust/elements/CastExpr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/ClosureExpr.qll linguist-generated
|
||||
@@ -436,7 +435,6 @@
|
||||
/lib/codeql/rust/elements/internal/VariantListConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/VariantListImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/VisibilityConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/VisibilityImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/WhereClauseConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/WhereClauseImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/WherePredConstructor.qll linguist-generated
|
||||
@@ -482,7 +480,6 @@
|
||||
/lib/codeql/rust/elements/internal/generated/BoxPat.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/BreakExpr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/CallExpr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/CallExprBase.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/Callable.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/CastExpr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/ClosureExpr.qll linguist-generated
|
||||
|
||||
@@ -15,8 +15,8 @@ class SourceLocatable extends Locatable {
|
||||
SourceLocatable() { this.fromSource() }
|
||||
}
|
||||
|
||||
query predicate multipleCallTargets(SourceLocatable a) {
|
||||
PathResolutionConsistency::multipleCallTargets(a, _)
|
||||
query predicate multipleResolvedTargets(SourceLocatable a) {
|
||||
PathResolutionConsistency::multipleResolvedTargets(a, _)
|
||||
}
|
||||
|
||||
query predicate multiplePathResolutions(SourceLocatable a) {
|
||||
|
||||
@@ -30,11 +30,11 @@ module ConstantPasswordConfig implements DataFlow::ConfigSig {
|
||||
|
||||
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 |
|
||||
exists(Call 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()
|
||||
call.getPositionalArgument(argIndex) = node.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ module SqlInjectionConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
// `node` is the first argument of a call to `sqlx_core::query::query`
|
||||
exists(CallExpr call |
|
||||
exists(Call call |
|
||||
call.getStaticTarget().getCanonicalPath() = "sqlx_core::query::query" and
|
||||
call.getArg(0) = node.asExpr()
|
||||
call.getPositionalArgument(0) = node.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import rust
|
||||
import codeql.rust.internal.PathResolution
|
||||
import utils.test.PathResolutionInlineExpectationsTest
|
||||
|
||||
query predicate resolveDollarCrate(RelevantPath p, Crate c) {
|
||||
query predicate resolveDollarCrate(PathExt p, Crate c) {
|
||||
c = resolvePath(p) and
|
||||
p.isDollarCrate() and
|
||||
p.fromSource() and
|
||||
|
||||
@@ -10,7 +10,9 @@ ql/rust/ql/src/queries/diagnostics/UnextractedElements.ql
|
||||
ql/rust/ql/src/queries/diagnostics/UnresolvedMacroCalls.ql
|
||||
ql/rust/ql/src/queries/security/CWE-020/RegexInjection.ql
|
||||
ql/rust/ql/src/queries/security/CWE-022/TaintedPath.ql
|
||||
ql/rust/ql/src/queries/security/CWE-079/XSS.ql
|
||||
ql/rust/ql/src/queries/security/CWE-089/SqlInjection.ql
|
||||
ql/rust/ql/src/queries/security/CWE-295/DisabledCertificateCheck.ql
|
||||
ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql
|
||||
ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
|
||||
ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql
|
||||
|
||||
@@ -10,8 +10,10 @@ ql/rust/ql/src/queries/diagnostics/UnextractedElements.ql
|
||||
ql/rust/ql/src/queries/diagnostics/UnresolvedMacroCalls.ql
|
||||
ql/rust/ql/src/queries/security/CWE-020/RegexInjection.ql
|
||||
ql/rust/ql/src/queries/security/CWE-022/TaintedPath.ql
|
||||
ql/rust/ql/src/queries/security/CWE-079/XSS.ql
|
||||
ql/rust/ql/src/queries/security/CWE-089/SqlInjection.ql
|
||||
ql/rust/ql/src/queries/security/CWE-117/LogInjection.ql
|
||||
ql/rust/ql/src/queries/security/CWE-295/DisabledCertificateCheck.ql
|
||||
ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql
|
||||
ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
|
||||
ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql
|
||||
|
||||
@@ -10,8 +10,10 @@ ql/rust/ql/src/queries/diagnostics/UnextractedElements.ql
|
||||
ql/rust/ql/src/queries/diagnostics/UnresolvedMacroCalls.ql
|
||||
ql/rust/ql/src/queries/security/CWE-020/RegexInjection.ql
|
||||
ql/rust/ql/src/queries/security/CWE-022/TaintedPath.ql
|
||||
ql/rust/ql/src/queries/security/CWE-079/XSS.ql
|
||||
ql/rust/ql/src/queries/security/CWE-089/SqlInjection.ql
|
||||
ql/rust/ql/src/queries/security/CWE-117/LogInjection.ql
|
||||
ql/rust/ql/src/queries/security/CWE-295/DisabledCertificateCheck.ql
|
||||
ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql
|
||||
ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
|
||||
ql/rust/ql/src/queries/security/CWE-312/CleartextStorageDatabase.ql
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
## 0.2.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* 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.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added more detailed models for `std::fs` and `std::path`.
|
||||
|
||||
## 0.1.20
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
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.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved type inference for raw pointers (`*const` and `*mut`). This includes type inference for the raw borrow operators (`&raw const` and `&raw mut`) and dereferencing of raw pointers.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The call graph is now more precise for calls that target a trait function with a default implemention. This reduces the number of false positives for data flow queries.
|
||||
9
rust/ql/lib/change-notes/released/0.2.0.md
Normal file
9
rust/ql/lib/change-notes/released/0.2.0.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## 0.2.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* 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.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added more detailed models for `std::fs` and `std::path`.
|
||||
3
rust/ql/lib/change-notes/released/0.2.1.md
Normal file
3
rust/ql/lib/change-notes/released/0.2.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.2.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.1.20
|
||||
lastReleaseVersion: 0.2.1
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.elements.Call
|
||||
private import ControlFlowGraph
|
||||
private import internal.ControlFlowGraphImpl as CfgImpl
|
||||
private import internal.CfgNodes
|
||||
@@ -200,20 +199,6 @@ final class BreakExprCfgNode extends Nodes::BreakExprCfgNode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
|
||||
*/
|
||||
final class CallExprBaseCfgNode extends Nodes::CallExprBaseCfgNode {
|
||||
private CallExprBaseChildMapping node;
|
||||
|
||||
CallExprBaseCfgNode() { node = this.getAstNode() }
|
||||
|
||||
/** Gets the `i`th argument of this call. */
|
||||
ExprCfgNode getArgument(int i) {
|
||||
any(ChildMapping mapping).hasCfgChild(node, node.getArgList().getArg(i), this, result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method call expression. For example:
|
||||
* ```rust
|
||||
@@ -221,7 +206,16 @@ final class CallExprBaseCfgNode extends Nodes::CallExprBaseCfgNode {
|
||||
* x.foo::<u32, u64>(42);
|
||||
* ```
|
||||
*/
|
||||
final class MethodCallExprCfgNode extends CallExprBaseCfgNode, Nodes::MethodCallExprCfgNode { }
|
||||
final class MethodCallExprCfgNode extends Nodes::MethodCallExprCfgNode {
|
||||
private MethodCallExprChildMapping node;
|
||||
|
||||
MethodCallExprCfgNode() { node = this.getAstNode() }
|
||||
|
||||
/** Gets the `i`th argument of this call. */
|
||||
ExprCfgNode getPositionalArgument(int i) {
|
||||
any(ChildMapping mapping).hasCfgChild(node, node.getPositionalArgument(i), this, result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A CFG node that calls a function.
|
||||
@@ -238,7 +232,7 @@ final class CallCfgNode extends ExprCfgNode {
|
||||
|
||||
/** Gets the receiver of this call if it is a method call. */
|
||||
ExprCfgNode getReceiver() {
|
||||
any(ChildMapping mapping).hasCfgChild(node, node.getReceiver(), this, result)
|
||||
any(ChildMapping mapping).hasCfgChild(node, node.(MethodCall).getReceiver(), this, result)
|
||||
}
|
||||
|
||||
/** Gets the `i`th argument of this call, if any. */
|
||||
@@ -248,15 +242,26 @@ final class CallCfgNode extends ExprCfgNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* A function call expression. For example:
|
||||
* An expression with parenthesized arguments. For example:
|
||||
* ```rust
|
||||
* foo(42);
|
||||
* foo::<u32, u64>(42);
|
||||
* foo[0](42);
|
||||
* foo(1) = 4;
|
||||
* Option::Some(42);
|
||||
* ```
|
||||
*/
|
||||
final class CallExprCfgNode extends CallExprBaseCfgNode, Nodes::CallExprCfgNode { }
|
||||
final class CallExprCfgNode extends Nodes::CallExprCfgNode {
|
||||
private CallExprChildMapping node;
|
||||
|
||||
CallExprCfgNode() { node = this.getAstNode() }
|
||||
|
||||
/** Gets the `i`th argument of this call. */
|
||||
ExprCfgNode getSyntacticArgument(int i) {
|
||||
any(ChildMapping mapping)
|
||||
.hasCfgChild(node, node.getSyntacticPositionalArgument(i), this, result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A FormatArgsExpr. For example:
|
||||
|
||||
@@ -57,8 +57,12 @@ class BreakExprTargetChildMapping extends ParentAstNode, Expr {
|
||||
override predicate relevantChild(AstNode child) { child.(BreakExpr).getTarget() = this }
|
||||
}
|
||||
|
||||
class CallExprBaseChildMapping extends ParentAstNode, CallExprBase {
|
||||
override predicate relevantChild(AstNode child) { child = this.getAnArg() }
|
||||
class CallExprChildMapping extends ParentAstNode, CallExpr {
|
||||
override predicate relevantChild(AstNode child) { child = this.getArgList().getAnArg() }
|
||||
}
|
||||
|
||||
class MethodCallExprChildMapping extends ParentAstNode, MethodCallExpr {
|
||||
override predicate relevantChild(AstNode child) { child = this.getArgList().getAnArg() }
|
||||
}
|
||||
|
||||
class StructExprChildMapping extends ParentAstNode, StructExpr {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
private import codeql.util.Boolean
|
||||
private import codeql.rust.controlflow.ControlFlowGraph
|
||||
private import codeql.rust.elements.internal.VariableImpl::Impl as VariableImpl
|
||||
private import rust
|
||||
|
||||
newtype TCompletion =
|
||||
@@ -123,13 +124,7 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion {
|
||||
*/
|
||||
private predicate cannotCauseMatchFailure(Pat pat) {
|
||||
pat instanceof RangePat or
|
||||
// Identifier patterns that are in fact path patterns can cause failures. For
|
||||
// instance `None`. Only if an `@ ...` part is present can we be sure that
|
||||
// it's an actual identifier pattern. As a heuristic, if the identifier starts
|
||||
// with a lower case letter, then we assume that it's an identifier. This
|
||||
// works for code that follows the Rust naming convention for enums and
|
||||
// constants.
|
||||
pat = any(IdentPat p | p.hasPat() or p.getName().getText().charAt(0).isLowercase()) or
|
||||
pat = any(IdentPat p | p.hasPat() or VariableImpl::variableDecl(_, p.getName(), _)) or
|
||||
pat instanceof WildcardPat or
|
||||
pat instanceof RestPat or
|
||||
pat instanceof RefPat or
|
||||
|
||||
@@ -210,13 +210,17 @@ module ExprTrees {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class BinaryOpExprTree extends StandardPostOrderTree instanceof BinaryExpr {
|
||||
BinaryOpExprTree() { not this instanceof BinaryLogicalOperation }
|
||||
class InvocationExprTree extends StandardPostOrderTree instanceof InvocationExpr {
|
||||
InvocationExprTree() {
|
||||
not this instanceof CallExpr and
|
||||
not this instanceof BinaryLogicalOperation
|
||||
}
|
||||
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getLhs()
|
||||
i = 0 and
|
||||
result = super.getSyntacticReceiver()
|
||||
or
|
||||
i = 1 and result = super.getRhs()
|
||||
result = super.getSyntacticPositionalArgument(i - 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,7 +300,7 @@ module ExprTrees {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getFunction()
|
||||
or
|
||||
result = super.getArgList().getArg(i - 1)
|
||||
result = super.getSyntacticPositionalArgument(i - 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,14 +375,6 @@ module ExprTrees {
|
||||
}
|
||||
}
|
||||
|
||||
class IndexExprTree extends StandardPostOrderTree instanceof IndexExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getBase()
|
||||
or
|
||||
i = 1 and result = super.getIndex()
|
||||
}
|
||||
}
|
||||
|
||||
class LetExprTree extends StandardPostOrderTree, LetExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and
|
||||
@@ -510,12 +506,6 @@ module ExprTrees {
|
||||
}
|
||||
}
|
||||
|
||||
class MethodCallExprTree extends StandardPostOrderTree, MethodCallExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
if i = 0 then result = this.getReceiver() else result = this.getArg(i - 1)
|
||||
}
|
||||
}
|
||||
|
||||
class OffsetOfExprTree extends LeafTree instanceof OffsetOfExpr { }
|
||||
|
||||
class ParenExprTree extends ControlFlowTree, ParenExpr {
|
||||
@@ -534,10 +524,6 @@ module ExprTrees {
|
||||
|
||||
class PathExprTree extends LeafTree instanceof PathExpr { }
|
||||
|
||||
class PrefixExprTree extends StandardPostOrderTree instanceof PrefixExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class RangeExprTree extends StandardPostOrderTree instanceof RangeExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getStart()
|
||||
@@ -552,10 +538,6 @@ module ExprTrees {
|
||||
}
|
||||
}
|
||||
|
||||
class RefExprTree extends StandardPostOrderTree instanceof RefExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class ReturnExprTree extends StandardPostOrderTree instanceof ReturnExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
@@ -654,15 +654,18 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A function call expression. For example:
|
||||
* NOTE: Consider using `Call` instead, as that excludes call expressions that are
|
||||
* instantiations of tuple structs and tuple variants.
|
||||
*
|
||||
* A call expression. For example:
|
||||
* ```rust
|
||||
* foo(42);
|
||||
* foo::<u32, u64>(42);
|
||||
* foo[0](42);
|
||||
* foo(1) = 4;
|
||||
* Option::Some(42); // tuple variant instantiation
|
||||
* ```
|
||||
*/
|
||||
final class CallExprCfgNode extends CfgNodeFinal, CallExprBaseCfgNode {
|
||||
final class CallExprCfgNode extends CfgNodeFinal, ExprCfgNode {
|
||||
private CallExpr node;
|
||||
|
||||
CallExprCfgNode() { node = this.getAstNode() }
|
||||
@@ -670,6 +673,31 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
|
||||
/** Gets the underlying `CallExpr`. */
|
||||
CallExpr getCallExpr() { result = node }
|
||||
|
||||
/**
|
||||
* Gets the argument list of this call expression, if it exists.
|
||||
*/
|
||||
ArgList getArgList() { result = node.getArgList() }
|
||||
|
||||
/**
|
||||
* Holds if `getArgList()` exists.
|
||||
*/
|
||||
predicate hasArgList() { exists(this.getArgList()) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th attr of this call expression (0-based).
|
||||
*/
|
||||
Attr getAttr(int index) { result = node.getAttr(index) }
|
||||
|
||||
/**
|
||||
* Gets any of the attrs of this call expression.
|
||||
*/
|
||||
Attr getAnAttr() { result = this.getAttr(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of attrs of this call expression.
|
||||
*/
|
||||
int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) }
|
||||
|
||||
/**
|
||||
* Gets the function of this call expression, if it exists.
|
||||
*/
|
||||
@@ -683,62 +711,6 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
|
||||
predicate hasFunction() { exists(this.getFunction()) }
|
||||
}
|
||||
|
||||
final private class ParentCallExprBase extends ParentAstNode, CallExprBase {
|
||||
override predicate relevantChild(AstNode child) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
|
||||
*/
|
||||
final class CallExprBaseCfgNode extends CfgNodeFinal, ExprCfgNode {
|
||||
private CallExprBase node;
|
||||
|
||||
CallExprBaseCfgNode() { node = this.getAstNode() }
|
||||
|
||||
/** Gets the underlying `CallExprBase`. */
|
||||
CallExprBase getCallExprBase() { result = node }
|
||||
|
||||
/**
|
||||
* Gets the argument list of this call expression base, if it exists.
|
||||
*/
|
||||
ArgList getArgList() { result = node.getArgList() }
|
||||
|
||||
/**
|
||||
* Holds if `getArgList()` exists.
|
||||
*/
|
||||
predicate hasArgList() { exists(this.getArgList()) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th attr of this call expression base (0-based).
|
||||
*/
|
||||
Attr getAttr(int index) { result = node.getAttr(index) }
|
||||
|
||||
/**
|
||||
* Gets any of the attrs of this call expression base.
|
||||
*/
|
||||
Attr getAnAttr() { result = this.getAttr(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of attrs of this call expression base.
|
||||
*/
|
||||
int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th argument of this call expression base (0-based).
|
||||
*/
|
||||
Expr getArg(int index) { result = node.getArg(index) }
|
||||
|
||||
/**
|
||||
* Gets any of the arguments of this call expression base.
|
||||
*/
|
||||
Expr getAnArg() { result = this.getArg(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of arguments of this call expression base.
|
||||
*/
|
||||
int getNumberOfArgs() { result = count(int i | exists(this.getArg(i))) }
|
||||
}
|
||||
|
||||
final private class ParentCastExpr extends ParentAstNode, CastExpr {
|
||||
override predicate relevantChild(AstNode child) {
|
||||
none()
|
||||
@@ -2071,13 +2043,17 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: Consider using `MethodCall` instead, as that also includes calls to methods using
|
||||
* call syntax (such as `Foo::method(x)`), operation syntax (such as `x + y`), and
|
||||
* indexing syntax (such as `x[y]`).
|
||||
*
|
||||
* A method call expression. For example:
|
||||
* ```rust
|
||||
* x.foo(42);
|
||||
* x.foo::<u32, u64>(42);
|
||||
* ```
|
||||
*/
|
||||
final class MethodCallExprCfgNode extends CfgNodeFinal, CallExprBaseCfgNode {
|
||||
final class MethodCallExprCfgNode extends CfgNodeFinal, ExprCfgNode {
|
||||
private MethodCallExpr node;
|
||||
|
||||
MethodCallExprCfgNode() { node = this.getAstNode() }
|
||||
@@ -2085,6 +2061,31 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
|
||||
/** Gets the underlying `MethodCallExpr`. */
|
||||
MethodCallExpr getMethodCallExpr() { result = node }
|
||||
|
||||
/**
|
||||
* Gets the argument list of this method call expression, if it exists.
|
||||
*/
|
||||
ArgList getArgList() { result = node.getArgList() }
|
||||
|
||||
/**
|
||||
* Holds if `getArgList()` exists.
|
||||
*/
|
||||
predicate hasArgList() { exists(this.getArgList()) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th attr of this method call expression (0-based).
|
||||
*/
|
||||
Attr getAttr(int index) { result = node.getAttr(index) }
|
||||
|
||||
/**
|
||||
* Gets any of the attrs of this method call expression.
|
||||
*/
|
||||
Attr getAnAttr() { result = this.getAttr(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of attrs of this method call expression.
|
||||
*/
|
||||
int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) }
|
||||
|
||||
/**
|
||||
* Gets the generic argument list of this method call expression, if it exists.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
private import rust
|
||||
private import codeql.rust.frameworks.stdlib.Builtins
|
||||
private import DataFlowImpl
|
||||
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
|
||||
|
||||
/**
|
||||
* A path to a value contained in an object. For example a field name of a struct.
|
||||
@@ -163,7 +164,7 @@ final class TuplePositionContent extends FieldContent, TTuplePositionContent {
|
||||
}
|
||||
|
||||
/**
|
||||
* A content for the index of an argument to at function call.
|
||||
* A content for the index of an argument to at closure call.
|
||||
*
|
||||
* Used by the model generator to create flow summaries for higher-order
|
||||
* functions.
|
||||
@@ -270,7 +271,7 @@ newtype TContent =
|
||||
} or
|
||||
TFunctionCallReturnContent() or
|
||||
TFunctionCallArgumentContent(int pos) {
|
||||
pos in [0 .. any(CallExpr c).getArgList().getNumberOfArgs() - 1]
|
||||
pos in [0 .. any(CallExprImpl::DynamicCallExpr c).getNumberOfPositionalArguments()]
|
||||
} or
|
||||
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
|
||||
TReferenceContent()
|
||||
|
||||
@@ -19,10 +19,6 @@ private module Input implements InputSig<Location, RustDataFlow> {
|
||||
predicate postWithInFlowExclude(RustDataFlow::Node n) {
|
||||
n instanceof Node::FlowSummaryNode
|
||||
or
|
||||
// We allow flow into post-update node for receiver expressions (from the
|
||||
// synthetic post receiever node).
|
||||
n.(Node::PostUpdateNode).getPreUpdateNode().asExpr() = any(Node::ReceiverNode r).getReceiver()
|
||||
or
|
||||
n.(Node::PostUpdateNode).getPreUpdateNode().asExpr() = getPostUpdateReverseStep(_, _)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::sourceLocalStep(_, n, _)
|
||||
|
||||
@@ -8,11 +8,10 @@ private import codeql.util.Boolean
|
||||
private import codeql.dataflow.DataFlow
|
||||
private import codeql.dataflow.internal.DataFlowImpl
|
||||
private import rust
|
||||
private import codeql.rust.elements.Call
|
||||
private import SsaImpl as SsaImpl
|
||||
private import codeql.rust.controlflow.internal.Scope as Scope
|
||||
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
|
||||
private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
private import codeql.rust.controlflow.ControlFlowGraph
|
||||
private import codeql.rust.dataflow.Ssa
|
||||
private import codeql.rust.dataflow.FlowSummary
|
||||
@@ -58,7 +57,7 @@ final class DataFlowCallable extends TDataFlowCallable {
|
||||
}
|
||||
|
||||
final class DataFlowCall extends TDataFlowCall {
|
||||
/** Gets the underlying call in the CFG, if any. */
|
||||
/** Gets the underlying call, if any. */
|
||||
Call asCall() { this = TCall(result) }
|
||||
|
||||
predicate isSummaryCall(
|
||||
@@ -87,72 +86,11 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
Location getLocation() { result = this.asCall().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of a parameter in a function.
|
||||
*
|
||||
* In Rust there is a 1-to-1 correspondence between parameter positions and
|
||||
* arguments positions, so we use the same underlying type for both.
|
||||
*/
|
||||
final class ParameterPosition extends TParameterPosition {
|
||||
/** Gets the underlying integer position, if any. */
|
||||
int getPosition() { this = TPositionalParameterPosition(result) }
|
||||
|
||||
predicate hasPosition() { exists(this.getPosition()) }
|
||||
|
||||
/** Holds if this position represents the `self` position. */
|
||||
predicate isSelf() { this = TSelfParameterPosition() }
|
||||
|
||||
/**
|
||||
* Holds if this position represents a reference to a closure itself. Only
|
||||
* used for tracking flow through captured variables.
|
||||
*/
|
||||
predicate isClosureSelf() { this = TClosureSelfParameterPosition() }
|
||||
|
||||
/** Gets a textual representation of this position. */
|
||||
string toString() {
|
||||
result = this.getPosition().toString()
|
||||
or
|
||||
result = "self" and this.isSelf()
|
||||
or
|
||||
result = "closure self" and this.isClosureSelf()
|
||||
}
|
||||
|
||||
ParamBase getParameterIn(ParamList ps) {
|
||||
result = ps.getParam(this.getPosition())
|
||||
or
|
||||
result = ps.getSelfParam() and this.isSelf()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of an argument in a call.
|
||||
*
|
||||
* In Rust there is a 1-to-1 correspondence between parameter positions and
|
||||
* arguments positions, so we use the same underlying type for both.
|
||||
*/
|
||||
final class ArgumentPosition extends ParameterPosition {
|
||||
/** Gets the argument of `call` at this position, if any. */
|
||||
Expr getArgument(Call call) {
|
||||
result = call.getPositionalArgument(this.getPosition())
|
||||
or
|
||||
result = call.getReceiver() and this.isSelf()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is an argument of `call` at the position `pos`.
|
||||
*
|
||||
* 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(Expr arg, Call call, ParameterPosition pos) {
|
||||
// TODO: Handle index expressions as calls in data flow.
|
||||
not call instanceof IndexExpr and
|
||||
(
|
||||
call.getPositionalArgument(pos.getPosition()) = arg
|
||||
or
|
||||
call.getReceiver() = arg and pos.isSelf() and not call.receiverImplicitlyBorrowed()
|
||||
)
|
||||
predicate isArgumentForCall(Expr arg, Call call, RustDataFlow::ArgumentPosition pos) {
|
||||
arg = pos.getArgument(call)
|
||||
}
|
||||
|
||||
/** Provides logic related to SSA. */
|
||||
@@ -266,8 +204,11 @@ module LocalFlow {
|
||||
)
|
||||
or
|
||||
// An edge from a pattern/expression to its corresponding SSA definition.
|
||||
nodeFrom.(AstNodeNode).getAstNode() =
|
||||
nodeTo.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess()
|
||||
exists(AstNode n |
|
||||
n = nodeTo.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess() and
|
||||
n = nodeFrom.(AstNodeNode).getAstNode() and
|
||||
not n = any(CompoundAssignmentExpr cae).getLhs()
|
||||
)
|
||||
or
|
||||
nodeFrom.(SourceParameterNode).getParameter().(Param).getPat() = nodeTo.asPat()
|
||||
or
|
||||
@@ -283,14 +224,6 @@ module LocalFlow {
|
||||
or
|
||||
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.
|
||||
nodeFrom.asExpr() = nodeTo.(ReceiverNode).getReceiver()
|
||||
or
|
||||
// The dual step of the above, for the post-update nodes.
|
||||
nodeFrom.(PostUpdateNode).getPreUpdateNode().(ReceiverNode).getReceiver() =
|
||||
nodeTo.(PostUpdateNode).getPreUpdateNode().asExpr()
|
||||
or
|
||||
nodeTo.(PostUpdateNode).getPreUpdateNode().asExpr() =
|
||||
getPostUpdateReverseStep(nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr(), true)
|
||||
}
|
||||
@@ -309,10 +242,8 @@ predicate lambdaCreationExpr(Expr creation) {
|
||||
* Holds if `call` is a lambda call of kind `kind` where `receiver` is the
|
||||
* invoked expression.
|
||||
*/
|
||||
predicate lambdaCallExpr(CallExpr call, LambdaCallKind kind, Expr receiver) {
|
||||
predicate lambdaCallExpr(CallExprImpl::DynamicCallExpr call, LambdaCallKind kind, Expr receiver) {
|
||||
receiver = call.getFunction() and
|
||||
// All calls to complex expressions and local variable accesses are lambda call.
|
||||
(receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess()) and
|
||||
exists(kind)
|
||||
}
|
||||
|
||||
@@ -324,10 +255,6 @@ private module Aliases {
|
||||
|
||||
class DataFlowCallAlias = DataFlowCall;
|
||||
|
||||
class ParameterPositionAlias = ParameterPosition;
|
||||
|
||||
class ArgumentPositionAlias = ArgumentPosition;
|
||||
|
||||
class ContentAlias = Content;
|
||||
|
||||
class ContentSetAlias = ContentSet;
|
||||
@@ -335,6 +262,30 @@ private module Aliases {
|
||||
class LambdaCallKindAlias = LambdaCallKind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Index assignments like `a[i] = rhs` are treated as `*a.index_mut(i) = rhs`,
|
||||
* so they should in principle be handled by `referenceAssignment`.
|
||||
*
|
||||
* However, this would require support for [generalized reverse flow][1], which
|
||||
* is not yet implemented, so instead we simulate reverse flow where it would
|
||||
* have applied via the model for `<_ as core::ops::index::IndexMut>::index_mut`.
|
||||
*
|
||||
* The same is the case for compound assignments like `a[i] += rhs`, which are
|
||||
* treated as `(*a.index_mut(i)).add_assign(rhs)`.
|
||||
*
|
||||
* [1]: https://github.com/github/codeql/pull/18109
|
||||
*/
|
||||
predicate indexAssignment(
|
||||
AssignmentOperation assignment, IndexExpr index, Node rhs, PostUpdateNode base, Content c
|
||||
) {
|
||||
assignment.getLhs() = index and
|
||||
rhs.asExpr() = assignment.getRhs() and
|
||||
base.getPreUpdateNode().asExpr() = index.getBase() and
|
||||
c instanceof ElementContent and
|
||||
// simulate that the flow summary applies
|
||||
not index.getResolvedTarget().fromSource()
|
||||
}
|
||||
|
||||
module RustDataFlow implements InputSig<Location> {
|
||||
private import Aliases
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
@@ -359,6 +310,58 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
final class CastNode = Node::CastNode;
|
||||
|
||||
/**
|
||||
* The position of a parameter in a function.
|
||||
*
|
||||
* In Rust there is a 1-to-1 correspondence between parameter positions and
|
||||
* arguments positions, so we use the same underlying type for both.
|
||||
*/
|
||||
final class ParameterPosition extends TParameterPosition {
|
||||
/** Gets the underlying integer position, if any. */
|
||||
int getPosition() { this = TPositionalParameterPosition(result) }
|
||||
|
||||
predicate hasPosition() { exists(this.getPosition()) }
|
||||
|
||||
/** Holds if this position represents the `self` position. */
|
||||
predicate isSelf() { this = TSelfParameterPosition() }
|
||||
|
||||
/**
|
||||
* Holds if this position represents a reference to a closure itself. Only
|
||||
* used for tracking flow through captured variables.
|
||||
*/
|
||||
predicate isClosureSelf() { this = TClosureSelfParameterPosition() }
|
||||
|
||||
/** Gets a textual representation of this position. */
|
||||
string toString() {
|
||||
result = this.getPosition().toString()
|
||||
or
|
||||
result = "self" and this.isSelf()
|
||||
or
|
||||
result = "closure self" and this.isClosureSelf()
|
||||
}
|
||||
|
||||
ParamBase getParameterIn(ParamList ps) {
|
||||
result = ps.getParam(this.getPosition())
|
||||
or
|
||||
result = ps.getSelfParam() and this.isSelf()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of an argument in a call.
|
||||
*
|
||||
* In Rust there is a 1-to-1 correspondence between parameter positions and
|
||||
* arguments positions, so we use the same underlying type for both.
|
||||
*/
|
||||
final class ArgumentPosition extends ParameterPosition {
|
||||
/** Gets the argument of `call` at this position, if any. */
|
||||
Expr getArgument(Call call) {
|
||||
result = call.getPositionalArgument(this.getPosition())
|
||||
or
|
||||
result = call.(MethodCall).getReceiver() and this.isSelf()
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `p` is a parameter of `c` at the position `pos`. */
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
p.isParameterOf(c, pos)
|
||||
@@ -380,7 +383,9 @@ module RustDataFlow implements InputSig<Location> {
|
||||
node.(FlowSummaryNode).getSummaryNode().isHidden() or
|
||||
node instanceof CaptureNode or
|
||||
node instanceof ClosureParameterNode or
|
||||
node instanceof ReceiverNode or
|
||||
node instanceof DerefBorrowNode or
|
||||
node instanceof DerefOutNode or
|
||||
node instanceof IndexOutNode or
|
||||
node.asExpr() instanceof ParenExpr or
|
||||
nodeIsHidden(node.(PostUpdateNode).getPreUpdateNode())
|
||||
}
|
||||
@@ -420,13 +425,26 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
final class ReturnKind = ReturnKindAlias;
|
||||
|
||||
private Function getStaticTargetExt(Call c) {
|
||||
result = c.getStaticTarget()
|
||||
or
|
||||
// If the static target of an overloaded operation cannot be resolved, we fall
|
||||
// back to the trait method as the target. This ensures that the flow models
|
||||
// still apply.
|
||||
not exists(c.getStaticTarget()) and
|
||||
exists(TraitItemNode t, string methodName |
|
||||
c.(Operation).isOverloaded(t, methodName, _) and
|
||||
result = t.getAssocItem(methodName)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a viable implementation of the target of the given `Call`. */
|
||||
DataFlowCallable viableCallable(DataFlowCall call) {
|
||||
exists(Call c | c = call.asCall() |
|
||||
result.asCfgScope() = c.getARuntimeTarget()
|
||||
or
|
||||
exists(SummarizedCallable sc, Function staticTarget |
|
||||
staticTarget = c.getStaticTarget() and
|
||||
staticTarget = getStaticTargetExt(c) and
|
||||
sc = result.asSummarizedCallable()
|
||||
|
|
||||
sc = staticTarget
|
||||
@@ -467,10 +485,6 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
ContentApprox getContentApprox(Content c) { result = c }
|
||||
|
||||
class ParameterPosition = ParameterPositionAlias;
|
||||
|
||||
class ArgumentPosition = ArgumentPositionAlias;
|
||||
|
||||
/**
|
||||
* Holds if the parameter position `ppos` matches the argument position
|
||||
* `apos`.
|
||||
@@ -520,16 +534,16 @@ module RustDataFlow implements InputSig<Location> {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate implicitDerefToReceiver(Node node1, ReceiverNode node2, ReferenceContent c) {
|
||||
TypeInference::receiverHasImplicitDeref(node1.asExpr()) and
|
||||
node1.asExpr() = node2.getReceiver() and
|
||||
private predicate implicitDeref(Node node1, DerefBorrowNode node2, ReferenceContent c) {
|
||||
not node2.isBorrow() and
|
||||
node1.asExpr() = node2.getNode() and
|
||||
exists(c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate implicitBorrowToReceiver(Node node1, ReceiverNode node2, ReferenceContent c) {
|
||||
TypeInference::receiverHasImplicitBorrow(node1.asExpr()) and
|
||||
node1.asExpr() = node2.getReceiver() and
|
||||
private predicate implicitBorrow(Node node1, DerefBorrowNode node2, ReferenceContent c) {
|
||||
node2.isBorrow() and
|
||||
node1.asExpr() = node2.getNode() and
|
||||
exists(c)
|
||||
}
|
||||
|
||||
@@ -539,6 +553,15 @@ module RustDataFlow implements InputSig<Location> {
|
||||
exists(c)
|
||||
}
|
||||
|
||||
private Node getFieldExprContainerNode(FieldExpr fe) {
|
||||
exists(Expr container | container = fe.getContainer() |
|
||||
not any(DerefBorrowNode n).getNode() = container and
|
||||
result.asExpr() = container
|
||||
or
|
||||
result.(DerefBorrowNode).getNode() = container
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate readContentStep(Node node1, Content c, Node node2) {
|
||||
exists(TupleStructPat pat, int pos |
|
||||
@@ -563,17 +586,11 @@ module RustDataFlow implements InputSig<Location> {
|
||||
node1.asPat().(RefPat).getPat() = node2.asPat()
|
||||
or
|
||||
exists(FieldExpr access |
|
||||
node1.asExpr() = access.getContainer() and
|
||||
node1 = getFieldExprContainerNode(access) and
|
||||
node2.asExpr() = access and
|
||||
access = c.(FieldContent).getAnAccess()
|
||||
)
|
||||
or
|
||||
exists(IndexExpr arr |
|
||||
c instanceof ElementContent and
|
||||
node1.asExpr() = arr.getBase() and
|
||||
node2.asExpr() = arr
|
||||
)
|
||||
or
|
||||
exists(ForExpr for |
|
||||
c instanceof ElementContent and
|
||||
node1.asExpr() = for.getIterable() and
|
||||
@@ -593,13 +610,18 @@ module RustDataFlow implements InputSig<Location> {
|
||||
.isVariantField([any(OptionEnum o).getSome(), any(ResultEnum r).getOk()], 0)
|
||||
)
|
||||
or
|
||||
exists(PrefixExpr deref |
|
||||
exists(DerefExpr deref |
|
||||
c instanceof ReferenceContent and
|
||||
deref.getOperatorName() = "*" and
|
||||
node1.asExpr() = deref.getExpr() and
|
||||
node1.(DerefOutNode).getDerefExpr() = deref and
|
||||
node2.asExpr() = deref
|
||||
)
|
||||
or
|
||||
exists(IndexExpr index |
|
||||
c instanceof ReferenceContent and
|
||||
node1.(IndexOutNode).getIndexExpr() = index and
|
||||
node2.asExpr() = index
|
||||
)
|
||||
or
|
||||
// Read from function return
|
||||
exists(DataFlowCall call |
|
||||
lambdaCall(call, _, node1) and
|
||||
@@ -616,13 +638,21 @@ module RustDataFlow implements InputSig<Location> {
|
||||
referenceExprToExpr(node2.(PostUpdateNode).getPreUpdateNode(),
|
||||
node1.(PostUpdateNode).getPreUpdateNode(), c)
|
||||
or
|
||||
// Step from receiver expression to receiver node, in case of an implicit
|
||||
// dereference.
|
||||
implicitDerefToReceiver(node1, node2, c)
|
||||
implicitDeref(node1, node2, c)
|
||||
or
|
||||
// A read step dual to the store step for implicit borrows.
|
||||
implicitBorrowToReceiver(node2.(PostUpdateNode).getPreUpdateNode(),
|
||||
node1.(PostUpdateNode).getPreUpdateNode(), c)
|
||||
exists(Node n | implicitBorrow(n, node1.(PostUpdateNode).getPreUpdateNode(), c) |
|
||||
node2.(PostUpdateNode).getPreUpdateNode() = n
|
||||
or
|
||||
// For compound assignments into variables like `x += y`, we do not want flow into
|
||||
// `[post] x`, as that would create spurious flow when `x` is a parameter. Instead,
|
||||
// we add the step directly into the SSA definition for `x` after the update.
|
||||
exists(CompoundAssignmentExpr cae, Expr lhs |
|
||||
lhs = cae.getLhs() and
|
||||
lhs = node2.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess() and
|
||||
n = TExprNode(lhs)
|
||||
)
|
||||
)
|
||||
or
|
||||
VariableCapture::readStep(node1, c, node2)
|
||||
}
|
||||
@@ -657,28 +687,46 @@ module RustDataFlow implements InputSig<Location> {
|
||||
exists(AssignmentExpr assignment, FieldExpr access |
|
||||
assignment.getLhs() = access and
|
||||
node1.asExpr() = assignment.getRhs() and
|
||||
node2.asExpr() = access.getContainer() and
|
||||
node2 = getFieldExprContainerNode(access) and
|
||||
access = c.getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate referenceAssignment(Node node1, Node node2, ReferenceContent c) {
|
||||
exists(AssignmentExpr assignment, PrefixExpr deref |
|
||||
assignment.getLhs() = deref and
|
||||
deref.getOperatorName() = "*" and
|
||||
private predicate referenceAssignment(
|
||||
Node node1, Node node2, Expr e, boolean clears, ReferenceContent c
|
||||
) {
|
||||
exists(AssignmentExpr assignment, Expr lhs |
|
||||
assignment.getLhs() = lhs and
|
||||
node1.asExpr() = assignment.getRhs() and
|
||||
node2.asExpr() = deref.getExpr() and
|
||||
exists(c)
|
||||
|
|
||||
lhs =
|
||||
any(DerefExpr de |
|
||||
de = node2.(DerefOutNode).getDerefExpr() and
|
||||
e = de.getExpr()
|
||||
) and
|
||||
clears = true
|
||||
or
|
||||
lhs =
|
||||
any(IndexExpr ie |
|
||||
ie = node2.(IndexOutNode).getIndexExpr() and
|
||||
e = ie.getBase() and
|
||||
clears = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
additional predicate storeContentStep(Node node1, Content c, Node node2) {
|
||||
exists(CallExpr call, int pos |
|
||||
node1.asExpr() = call.getArg(pragma[only_bind_into](pos)) and
|
||||
node2.asExpr() = call and
|
||||
c = TTupleFieldContent(call.getTupleField(pragma[only_bind_into](pos)))
|
||||
exists(CallExpr ce, TupleField tf, int pos |
|
||||
node1.asExpr() = ce.getSyntacticPositionalArgument(pos) and
|
||||
node2.asExpr() = ce and
|
||||
c = TTupleFieldContent(tf)
|
||||
|
|
||||
tf = ce.(TupleStructExpr).getTupleField(pos)
|
||||
or
|
||||
tf = ce.(TupleVariantExpr).getTupleField(pos)
|
||||
)
|
||||
or
|
||||
exists(StructExpr re, string field |
|
||||
@@ -709,14 +757,14 @@ module RustDataFlow implements InputSig<Location> {
|
||||
or
|
||||
fieldAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
|
||||
or
|
||||
referenceAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
|
||||
referenceAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), _, _, c)
|
||||
or
|
||||
exists(AssignmentExpr assignment, IndexExpr index |
|
||||
c instanceof ElementContent and
|
||||
assignment.getLhs() = index and
|
||||
node1.asExpr() = assignment.getRhs() and
|
||||
node2.(PostUpdateNode).getPreUpdateNode().asExpr() = index.getBase()
|
||||
)
|
||||
indexAssignment(any(AssignmentExpr ae), _, node1, node2, c)
|
||||
or
|
||||
// Compund assignment like `a[i] += rhs` are modeled as a store step from `rhs`
|
||||
// to `[post] a[i]`, followed by a taint step into `[post] a`.
|
||||
indexAssignment(any(CompoundAssignmentExpr cae),
|
||||
node2.(PostUpdateNode).getPreUpdateNode().asExpr(), node1, _, c)
|
||||
or
|
||||
referenceExprToExpr(node1, node2, c)
|
||||
or
|
||||
@@ -729,9 +777,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
or
|
||||
VariableCapture::storeStep(node1, c, node2)
|
||||
or
|
||||
// Step from receiver expression to receiver node, in case of an implicit
|
||||
// borrow.
|
||||
implicitBorrowToReceiver(node1, node2, c)
|
||||
implicitBorrow(node1, node2, c)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -755,7 +801,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
predicate clearsContent(Node n, ContentSet cs) {
|
||||
fieldAssignment(_, n, cs.(SingletonContentSet).getContent())
|
||||
or
|
||||
referenceAssignment(_, n, cs.(SingletonContentSet).getContent())
|
||||
referenceAssignment(_, _, n.asExpr(), true, cs.(SingletonContentSet).getContent())
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), cs)
|
||||
or
|
||||
@@ -835,11 +881,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
*/
|
||||
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
(
|
||||
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() |
|
||||
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
|
||||
)
|
||||
receiver.asExpr() = call.asCall().(CallExprImpl::DynamicCallExpr).getFunction()
|
||||
or
|
||||
call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode())
|
||||
) and
|
||||
@@ -1003,9 +1045,7 @@ private module Cached {
|
||||
newtype TDataFlowCall =
|
||||
TCall(Call call) {
|
||||
Stages::DataFlowStage::ref() and
|
||||
call.hasEnclosingCfgScope() and
|
||||
// TODO: Handle index expressions as calls in data flow.
|
||||
not call instanceof IndexExpr
|
||||
call.hasEnclosingCfgScope()
|
||||
} or
|
||||
TSummaryCall(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
|
||||
@@ -12,18 +12,17 @@ private import codeql.rust.dataflow.Ssa
|
||||
private import Content
|
||||
|
||||
module Input implements InputSig<Location, RustDataFlow> {
|
||||
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
|
||||
private import codeql.rust.frameworks.stdlib.Stdlib
|
||||
|
||||
class SummarizedCallableBase = Function;
|
||||
|
||||
abstract private class SourceSinkBase extends AstNode {
|
||||
/** Gets the associated call. */
|
||||
abstract CallExprBase getCall();
|
||||
abstract Call getCall();
|
||||
|
||||
/** Holds if the associated call resolves to `path`. */
|
||||
final predicate callResolvesTo(string path) {
|
||||
path = this.getCall().getStaticTarget().(Addressable).getCanonicalPath()
|
||||
path = this.getCall().getResolvedTarget().getCanonicalPath()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +35,7 @@ module Input implements InputSig<Location, RustDataFlow> {
|
||||
|
||||
CallExprFunction() { this = call.getFunction() }
|
||||
|
||||
override CallExpr getCall() { result = call }
|
||||
override Call getCall() { result = call }
|
||||
}
|
||||
|
||||
private class MethodCallExprNameRef extends SourceBase, SinkBase {
|
||||
@@ -51,11 +50,9 @@ module Input implements InputSig<Location, RustDataFlow> {
|
||||
|
||||
ReturnKind getStandardReturnValueKind() { result = TNormalReturnKind() }
|
||||
|
||||
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }
|
||||
string encodeParameterPosition(RustDataFlow::ParameterPosition pos) { result = pos.toString() }
|
||||
|
||||
string encodeArgumentPosition(RustDataFlow::ArgumentPosition pos) {
|
||||
result = encodeParameterPosition(pos)
|
||||
}
|
||||
string encodeArgumentPosition(RustDataFlow::ArgumentPosition pos) { result = pos.toString() }
|
||||
|
||||
string encodeContent(ContentSet cs, string arg) {
|
||||
exists(Content c | cs = TSingletonContentSet(c) |
|
||||
@@ -108,7 +105,9 @@ module Input implements InputSig<Location, RustDataFlow> {
|
||||
string encodeWithContent(ContentSet c, string arg) { result = "With" + encodeContent(c, arg) }
|
||||
|
||||
bindingset[token]
|
||||
ParameterPosition decodeUnknownParameterPosition(AccessPath::AccessPathTokenBase token) {
|
||||
RustDataFlow::ParameterPosition decodeUnknownParameterPosition(
|
||||
AccessPath::AccessPathTokenBase token
|
||||
) {
|
||||
// needed to support `Argument[x..y]` ranges
|
||||
token.getName() = "Argument" and
|
||||
result.getPosition() = AccessPath::parseInt(token.getAnArgument())
|
||||
@@ -135,7 +134,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
|
||||
/** Gets the argument of `source` described by `sc`, if any. */
|
||||
private Expr getSourceNodeArgument(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
|
||||
exists(ArgumentPosition pos |
|
||||
exists(RustDataFlow::ArgumentPosition pos |
|
||||
sc = Impl::Private::SummaryComponent::argument(pos) and
|
||||
result = pos.getArgument(source.getCall())
|
||||
)
|
||||
@@ -162,7 +161,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
s.head() = Impl::Private::SummaryComponent::return(_) and
|
||||
result.asExpr() = source.getCall()
|
||||
or
|
||||
exists(ArgumentPosition pos, Expr arg |
|
||||
exists(RustDataFlow::ArgumentPosition pos, Expr arg |
|
||||
s.head() = Impl::Private::SummaryComponent::parameter(pos) and
|
||||
arg = getSourceNodeArgument(source, s.tail().headOfSingleton()) and
|
||||
result.asParameter() = getCallable(arg).getParam(pos.getPosition())
|
||||
@@ -173,7 +172,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
}
|
||||
|
||||
RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {
|
||||
exists(CallExprBase call, Expr arg, ArgumentPosition pos |
|
||||
exists(InvocationExpr call, Expr arg, RustDataFlow::ArgumentPosition pos |
|
||||
result.asExpr() = arg and
|
||||
sc = Impl::Private::SummaryComponent::argument(pos) and
|
||||
call = sink.getCall() and
|
||||
|
||||
@@ -47,7 +47,6 @@ private import rust
|
||||
private import codeql.rust.dataflow.FlowSummary
|
||||
private import codeql.rust.dataflow.FlowSource
|
||||
private import codeql.rust.dataflow.FlowSink
|
||||
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
|
||||
|
||||
/**
|
||||
* Holds if in a call to the function with canonical path `path`, the value referred
|
||||
|
||||
@@ -14,6 +14,7 @@ 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 codeql.rust.internal.TypeInference as TypeInference
|
||||
private import Node as Node
|
||||
private import DataFlowImpl
|
||||
private import FlowSummaryImpl as FlowSummaryImpl
|
||||
@@ -166,7 +167,7 @@ final class NameNode extends AstNodeNode, TNameNode {
|
||||
*/
|
||||
abstract class ParameterNode extends Node {
|
||||
/** Holds if this node is a parameter of `c` at position `pos`. */
|
||||
abstract predicate isParameterOf(DataFlowCallable c, ParameterPosition pos);
|
||||
abstract predicate isParameterOf(DataFlowCallable c, RustDataFlow::ParameterPosition pos);
|
||||
}
|
||||
|
||||
final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParameterNode {
|
||||
@@ -174,12 +175,12 @@ final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParam
|
||||
|
||||
SourceParameterNode() { this = TSourceParameterNode(n) }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
override predicate isParameterOf(DataFlowCallable c, RustDataFlow::ParameterPosition pos) {
|
||||
n = pos.getParameterIn(c.asCfgScope().(Callable).getParamList())
|
||||
}
|
||||
|
||||
/** Get the parameter position of this parameter. */
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
RustDataFlow::ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
/** Gets the parameter in the CFG that this node corresponds to. */
|
||||
ParamBase getParameter() { result = n }
|
||||
@@ -187,13 +188,13 @@ final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParam
|
||||
|
||||
/** A parameter for a library callable with a flow summary. */
|
||||
final class SummaryParameterNode extends ParameterNode, FlowSummaryNode {
|
||||
private ParameterPosition pos_;
|
||||
private RustDataFlow::ParameterPosition pos_;
|
||||
|
||||
SummaryParameterNode() {
|
||||
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), pos_)
|
||||
}
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
override predicate isParameterOf(DataFlowCallable c, RustDataFlow::ParameterPosition pos) {
|
||||
this.getSummarizedCallable() = c.asSummarizedCallable() and pos = pos_
|
||||
}
|
||||
}
|
||||
@@ -209,7 +210,7 @@ final class ClosureParameterNode extends ParameterNode, TClosureSelfReferenceNod
|
||||
|
||||
final override CfgScope getCfgScope() { result = cfgScope }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
override predicate isParameterOf(DataFlowCallable c, RustDataFlow::ParameterPosition pos) {
|
||||
cfgScope = c.asCfgScope() and pos.isClosureSelf()
|
||||
}
|
||||
|
||||
@@ -226,7 +227,11 @@ final class ExprArgumentNode extends ArgumentNode, ExprNode {
|
||||
private Call call_;
|
||||
private RustDataFlow::ArgumentPosition pos_;
|
||||
|
||||
ExprArgumentNode() { isArgumentForCall(n, call_, pos_) }
|
||||
ExprArgumentNode() {
|
||||
isArgumentForCall(n, call_, pos_) and
|
||||
not TypeInference::implicitDeref(n) and
|
||||
not TypeInference::implicitBorrow(n)
|
||||
}
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call.asCall() = call_ and pos = pos_
|
||||
@@ -234,27 +239,41 @@ final class ExprArgumentNode extends ArgumentNode, ExprNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* The receiver of a method call _after_ any implicit borrow or dereferencing
|
||||
* has taken place.
|
||||
* A node that represents the value of an expression _after_ implicit dereferencing
|
||||
* or borrowing.
|
||||
*/
|
||||
final class ReceiverNode extends ArgumentNode, TReceiverNode {
|
||||
private Call n;
|
||||
class DerefBorrowNode extends Node, TDerefBorrowNode {
|
||||
AstNode n;
|
||||
boolean isBorrow;
|
||||
|
||||
ReceiverNode() { this = TReceiverNode(n, false) }
|
||||
DerefBorrowNode() { this = TDerefBorrowNode(n, isBorrow, false) }
|
||||
|
||||
Expr getReceiver() { result = n.getReceiver() }
|
||||
AstNode getNode() { result = n }
|
||||
|
||||
MethodCallExpr getMethodCall() { result = n }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call.asCall() = n and pos = TSelfParameterPosition()
|
||||
}
|
||||
predicate isBorrow() { isBorrow = true }
|
||||
|
||||
override CfgScope getCfgScope() { result = n.getEnclosingCfgScope() }
|
||||
|
||||
override Location getLocation() { result = this.getReceiver().getLocation() }
|
||||
override Location getLocation() { result = n.getLocation() }
|
||||
|
||||
override string toString() { result = "receiver for " + this.getReceiver() }
|
||||
override string toString() {
|
||||
if isBorrow = true then result = n + " [borrowed]" else result = n + " [dereferenced]"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that represents the value of an argument of a call _after_ implicit
|
||||
* dereferencing or borrowing.
|
||||
*/
|
||||
final class DerefBorrowArgNode extends DerefBorrowNode, ArgumentNode {
|
||||
private DataFlowCall call_;
|
||||
private RustDataFlow::ArgumentPosition pos_;
|
||||
|
||||
DerefBorrowArgNode() { isArgumentForCall(n, call_.asCall(), pos_) }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call = call_ and pos = pos_
|
||||
}
|
||||
}
|
||||
|
||||
final class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
|
||||
@@ -275,13 +294,12 @@ final class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
|
||||
* passed into the closure body at an invocation.
|
||||
*/
|
||||
final class ClosureArgumentNode extends ArgumentNode, ExprNode {
|
||||
private CallExpr call_;
|
||||
private Call call_;
|
||||
|
||||
ClosureArgumentNode() { lambdaCallExpr(call_, _, this.asExpr()) }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call.asCall() = call_ and
|
||||
pos.isClosureSelf()
|
||||
call.asCall() = call_ and pos.isClosureSelf()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,15 +347,73 @@ abstract class OutNode extends Node {
|
||||
}
|
||||
|
||||
final private class ExprOutNode extends ExprNode, OutNode {
|
||||
ExprOutNode() { this.asExpr() instanceof Call }
|
||||
ExprOutNode() {
|
||||
exists(Call call |
|
||||
call = this.asExpr() and
|
||||
not call instanceof DerefExpr and // Handled by `DerefOutNode`
|
||||
not call instanceof IndexExpr // Handled by `IndexOutNode`
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the underlying call CFG node that includes this out node. */
|
||||
/** Gets the underlying call node that includes this out node. */
|
||||
override DataFlowCall getCall(ReturnKind kind) {
|
||||
result.asCall() = n and
|
||||
kind = TNormalReturnKind()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that represents the value of a `*` expression _before_ implicit
|
||||
* dereferencing:
|
||||
*
|
||||
* `*v` equivalent to `*Deref::deref(&v)`, and this node represents the
|
||||
* `Deref::deref(&v)` part.
|
||||
*/
|
||||
class DerefOutNode extends OutNode, TDerefOutNode {
|
||||
DerefExpr de;
|
||||
|
||||
DerefOutNode() { this = TDerefOutNode(de, false) }
|
||||
|
||||
DerefExpr getDerefExpr() { result = de }
|
||||
|
||||
override CfgScope getCfgScope() { result = de.getEnclosingCfgScope() }
|
||||
|
||||
override DataFlowCall getCall(ReturnKind kind) {
|
||||
result.asCall() = de and
|
||||
kind = TNormalReturnKind()
|
||||
}
|
||||
|
||||
override Location getLocation() { result = de.getLocation() }
|
||||
|
||||
override string toString() { result = de.toString() + " [pre-dereferenced]" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that represents the value of a `x[y]` expression _before_ implicit
|
||||
* dereferencing:
|
||||
*
|
||||
* `x[y]` equivalent to `*x.index(y)`, and this node represents the
|
||||
* `x.index(y)` part.
|
||||
*/
|
||||
class IndexOutNode extends OutNode, TIndexOutNode {
|
||||
IndexExpr ie;
|
||||
|
||||
IndexOutNode() { this = TIndexOutNode(ie, false) }
|
||||
|
||||
IndexExpr getIndexExpr() { result = ie }
|
||||
|
||||
override CfgScope getCfgScope() { result = ie.getEnclosingCfgScope() }
|
||||
|
||||
override DataFlowCall getCall(ReturnKind kind) {
|
||||
result.asCall() = ie and
|
||||
kind = TNormalReturnKind()
|
||||
}
|
||||
|
||||
override Location getLocation() { result = ie.getLocation() }
|
||||
|
||||
override string toString() { result = ie.toString() + " [pre-dereferenced]" }
|
||||
}
|
||||
|
||||
final class SummaryOutNode extends FlowSummaryNode, OutNode {
|
||||
private DataFlowCall call;
|
||||
private ReturnKind kind_;
|
||||
@@ -402,16 +478,41 @@ final class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
|
||||
override Location getLocation() { result = e.getLocation() }
|
||||
}
|
||||
|
||||
final class ReceiverPostUpdateNode extends PostUpdateNode, TReceiverNode {
|
||||
private Call call;
|
||||
final class DerefBorrowPostUpdateNode extends PostUpdateNode, TDerefBorrowNode {
|
||||
private Expr arg;
|
||||
private boolean isBorrow;
|
||||
|
||||
ReceiverPostUpdateNode() { this = TReceiverNode(call, true) }
|
||||
DerefBorrowPostUpdateNode() { this = TDerefBorrowNode(arg, isBorrow, true) }
|
||||
|
||||
override Node getPreUpdateNode() { result = TReceiverNode(call, false) }
|
||||
override DerefBorrowNode getPreUpdateNode() { result = TDerefBorrowNode(arg, isBorrow, false) }
|
||||
|
||||
override CfgScope getCfgScope() { result = call.getEnclosingCfgScope() }
|
||||
override CfgScope getCfgScope() { result = arg.getEnclosingCfgScope() }
|
||||
|
||||
override Location getLocation() { result = call.getReceiver().getLocation() }
|
||||
override Location getLocation() { result = arg.getLocation() }
|
||||
}
|
||||
|
||||
class DerefOutPostUpdateNode extends PostUpdateNode, TDerefOutNode {
|
||||
DerefExpr de;
|
||||
|
||||
DerefOutPostUpdateNode() { this = TDerefOutNode(de, true) }
|
||||
|
||||
override DerefOutNode getPreUpdateNode() { result = TDerefOutNode(de, false) }
|
||||
|
||||
override CfgScope getCfgScope() { result = de.getEnclosingCfgScope() }
|
||||
|
||||
override Location getLocation() { result = de.getLocation() }
|
||||
}
|
||||
|
||||
class IndexOutPostUpdateNode extends PostUpdateNode, TIndexOutNode {
|
||||
IndexExpr ie;
|
||||
|
||||
IndexOutPostUpdateNode() { this = TIndexOutNode(ie, true) }
|
||||
|
||||
override IndexOutNode getPreUpdateNode() { result = TIndexOutNode(ie, false) }
|
||||
|
||||
override CfgScope getCfgScope() { result = ie.getEnclosingCfgScope() }
|
||||
|
||||
override Location getLocation() { result = ie.getLocation() }
|
||||
}
|
||||
|
||||
final class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode {
|
||||
@@ -452,7 +553,10 @@ newtype TNode =
|
||||
TExprPostUpdateNode(Expr e) {
|
||||
e.hasEnclosingCfgScope() and
|
||||
(
|
||||
isArgumentForCall(e, _, _)
|
||||
isArgumentForCall(e, _, _) and
|
||||
// For compound assignments into variables like `x += y`, we do not want flow into
|
||||
// `[post] x`, as that would create spurious flow when `x` is a parameter.
|
||||
not (e = any(CompoundAssignmentExpr cae).getLhs() and e instanceof VariableAccess)
|
||||
or
|
||||
lambdaCallExpr(_, _, e)
|
||||
or
|
||||
@@ -464,22 +568,22 @@ newtype TNode =
|
||||
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(Call call, Boolean isPost) {
|
||||
call.hasEnclosingCfgScope() and
|
||||
call.receiverImplicitlyBorrowed() and
|
||||
// TODO: Handle index expressions as calls in data flow.
|
||||
not call instanceof IndexExpr
|
||||
TDerefBorrowNode(AstNode n, boolean borrow, Boolean isPost) {
|
||||
TypeInference::implicitDeref(n) and
|
||||
borrow = false
|
||||
or
|
||||
TypeInference::implicitBorrow(n) and
|
||||
borrow = true
|
||||
} or
|
||||
TDerefOutNode(DerefExpr de, Boolean isPost) or
|
||||
TIndexOutNode(IndexExpr ie, Boolean isPost) or
|
||||
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
|
||||
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) {
|
||||
forall(AstNode n | n = sn.getSinkElement() or n = sn.getSourceElement() |
|
||||
|
||||
@@ -154,7 +154,7 @@ private predicate variableWriteInOuterScope(BasicBlock bb, int i, Variable v, Cf
|
||||
}
|
||||
|
||||
/** Holds if evaluating `e` jumps to the evaluation of a different CFG scope. */
|
||||
private predicate isControlFlowJump(Expr e) { e instanceof CallExprBase or e instanceof AwaitExpr }
|
||||
private predicate isControlFlowJump(Expr e) { e instanceof Call or e instanceof AwaitExpr }
|
||||
|
||||
/**
|
||||
* Holds if the call `call` at index `i` in basic block `bb` may reach
|
||||
@@ -325,10 +325,8 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
|
||||
|
||||
predicate ssaDefHasSource(WriteDefinition def) { none() } // handled in `DataFlowImpl.qll` instead
|
||||
|
||||
private predicate isArg(CallExprBase call, Expr e) {
|
||||
call.getAnArg() = e
|
||||
or
|
||||
call.(MethodCallExpr).getReceiver() = e
|
||||
private predicate isArg(Call call, Expr e) {
|
||||
call.getASyntacticArgument() = e
|
||||
or
|
||||
exists(Expr mid |
|
||||
isArg(call, mid) and
|
||||
|
||||
@@ -20,18 +20,6 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
|
||||
Stages::DataFlowStage::ref() and
|
||||
model = "" and
|
||||
(
|
||||
exists(BinaryExpr binary |
|
||||
binary.getOperatorName() = ["+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>"] and
|
||||
pred.asExpr() = [binary.getLhs(), binary.getRhs()] and
|
||||
succ.asExpr() = binary
|
||||
)
|
||||
or
|
||||
exists(PrefixExpr prefix |
|
||||
prefix.getOperatorName() = ["-", "!"] and
|
||||
pred.asExpr() = prefix.getExpr() and
|
||||
succ.asExpr() = prefix
|
||||
)
|
||||
or
|
||||
pred.asExpr() = succ.asExpr().(CastExpr).getExpr()
|
||||
or
|
||||
exists(IndexExpr index |
|
||||
@@ -65,6 +53,9 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
|
||||
or
|
||||
succ.(Node::PostUpdateNode).getPreUpdateNode().asExpr() =
|
||||
getPostUpdateReverseStep(pred.(Node::PostUpdateNode).getPreUpdateNode().asExpr(), false)
|
||||
or
|
||||
indexAssignment(any(CompoundAssignmentExpr cae),
|
||||
pred.(Node::PostUpdateNode).getPreUpdateNode().asExpr(), _, succ, _)
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(Node::FlowSummaryNode).getSummaryNode(),
|
||||
|
||||
1
rust/ql/lib/codeql/rust/elements.qll
generated
1
rust/ql/lib/codeql/rust/elements.qll
generated
@@ -38,7 +38,6 @@ import codeql.rust.elements.BlockExpr
|
||||
import codeql.rust.elements.BoxPat
|
||||
import codeql.rust.elements.BreakExpr
|
||||
import codeql.rust.elements.CallExpr
|
||||
import codeql.rust.elements.CallExprBase
|
||||
import codeql.rust.elements.Callable
|
||||
import codeql.rust.elements.CastExpr
|
||||
import codeql.rust.elements.ClosureExpr
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/**
|
||||
* This module provides the public class `Call`.
|
||||
* This module provides the public classes `Call` and `MethodCall`.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import internal.CallImpl
|
||||
|
||||
final class ArgumentPosition = Impl::ArgumentPosition;
|
||||
private import internal.CallExprImpl::Impl as CallExprImpl
|
||||
|
||||
final class Call = Impl::Call;
|
||||
|
||||
final class MethodCall = Impl::MethodCall;
|
||||
|
||||
10
rust/ql/lib/codeql/rust/elements/CallExpr.qll
generated
10
rust/ql/lib/codeql/rust/elements/CallExpr.qll
generated
@@ -4,16 +4,20 @@
|
||||
*/
|
||||
|
||||
private import internal.CallExprImpl
|
||||
import codeql.rust.elements.CallExprBase
|
||||
import codeql.rust.elements.ArgList
|
||||
import codeql.rust.elements.Attr
|
||||
import codeql.rust.elements.Expr
|
||||
|
||||
/**
|
||||
* A function call expression. For example:
|
||||
* NOTE: Consider using `Call` instead, as that excludes call expressions that are
|
||||
* instantiations of tuple structs and tuple variants.
|
||||
*
|
||||
* A call expression. For example:
|
||||
* ```rust
|
||||
* foo(42);
|
||||
* foo::<u32, u64>(42);
|
||||
* foo[0](42);
|
||||
* foo(1) = 4;
|
||||
* Option::Some(42); // tuple variant instantiation
|
||||
* ```
|
||||
*/
|
||||
final class CallExpr = Impl::CallExpr;
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
// generated by codegen, do not edit
|
||||
/**
|
||||
* This module provides the public class `CallExprBase`.
|
||||
*/
|
||||
|
||||
private import internal.CallExprBaseImpl
|
||||
import codeql.rust.elements.ArgList
|
||||
import codeql.rust.elements.Attr
|
||||
import codeql.rust.elements.Expr
|
||||
|
||||
/**
|
||||
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
|
||||
*/
|
||||
final class CallExprBase = Impl::CallExprBase;
|
||||
9
rust/ql/lib/codeql/rust/elements/InvocationExpr.qll
Normal file
9
rust/ql/lib/codeql/rust/elements/InvocationExpr.qll
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* This module provides the public classes `InvocationExpr` and `ArgumentPosition`.
|
||||
*/
|
||||
|
||||
private import internal.InvocationExprImpl
|
||||
|
||||
final class InvocationExpr = Impl::InvocationExpr;
|
||||
|
||||
final class ArgumentPosition = Impl::ArgumentPosition;
|
||||
22
rust/ql/lib/codeql/rust/elements/Method.qll
Normal file
22
rust/ql/lib/codeql/rust/elements/Method.qll
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* This module provides the public class `Method`.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
|
||||
/**
|
||||
* A method declaration. For example
|
||||
* ```rust
|
||||
* fn foo(self, x: u32) -> u64 { (x + 1).into() }
|
||||
* ```
|
||||
*
|
||||
* A method declaration within a trait might not have a body:
|
||||
* ```rust
|
||||
* trait Trait {
|
||||
* fn bar(self);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
final class Method extends Function {
|
||||
Method() { this.hasSelfParam() }
|
||||
}
|
||||
@@ -4,12 +4,17 @@
|
||||
*/
|
||||
|
||||
private import internal.MethodCallExprImpl
|
||||
import codeql.rust.elements.CallExprBase
|
||||
import codeql.rust.elements.ArgList
|
||||
import codeql.rust.elements.Attr
|
||||
import codeql.rust.elements.Expr
|
||||
import codeql.rust.elements.GenericArgList
|
||||
import codeql.rust.elements.NameRef
|
||||
|
||||
/**
|
||||
* NOTE: Consider using `MethodCall` instead, as that also includes calls to methods using
|
||||
* call syntax (such as `Foo::method(x)`), operation syntax (such as `x + y`), and
|
||||
* indexing syntax (such as `x[y]`).
|
||||
*
|
||||
* A method call expression. For example:
|
||||
* ```rust
|
||||
* x.foo(42);
|
||||
|
||||
2
rust/ql/lib/codeql/rust/elements/TupleField.qll
generated
2
rust/ql/lib/codeql/rust/elements/TupleField.qll
generated
@@ -10,7 +10,7 @@ import codeql.rust.elements.TypeRepr
|
||||
import codeql.rust.elements.Visibility
|
||||
|
||||
/**
|
||||
* A field in a tuple struct or tuple enum variant.
|
||||
* A field in a tuple struct or tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
|
||||
@@ -8,7 +8,7 @@ import codeql.rust.elements.FieldList
|
||||
import codeql.rust.elements.TupleField
|
||||
|
||||
/**
|
||||
* A list of fields in a tuple struct or tuple enum variant.
|
||||
* A list of fields in a tuple struct or tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
|
||||
7
rust/ql/lib/codeql/rust/elements/TupleStructExpr.qll
Normal file
7
rust/ql/lib/codeql/rust/elements/TupleStructExpr.qll
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This module provides the public class `TupleStructExpr`.
|
||||
*/
|
||||
|
||||
private import internal.CallExprImpl
|
||||
|
||||
final class TupleStructExpr = Impl::TupleStructExpr;
|
||||
7
rust/ql/lib/codeql/rust/elements/TupleVariantExpr.qll
Normal file
7
rust/ql/lib/codeql/rust/elements/TupleVariantExpr.qll
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This module provides the public class `TupleVariantExpr`.
|
||||
*/
|
||||
|
||||
private import internal.CallExprImpl
|
||||
|
||||
final class TupleVariantExpr = Impl::TupleVariantExpr;
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `CallExprBase`.
|
||||
*
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
private import codeql.rust.elements.internal.generated.CallExprBase
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the customizable definition of `CallExprBase` and should not
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
|
||||
*/
|
||||
class CallExprBase extends Generated::CallExprBase {
|
||||
/** Gets the static target (function or tuple struct/variant) of this call, if any. */
|
||||
final Addressable getStaticTarget() { result = TypeInference::resolveCallTarget(this) }
|
||||
|
||||
override Expr getArg(int index) { result = this.getArgList().getArg(index) }
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
private import codeql.rust.elements.internal.generated.CallExpr
|
||||
private import codeql.rust.elements.PathExpr
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the customizable definition of `CallExpr` and should not
|
||||
@@ -13,7 +12,10 @@ private import codeql.rust.elements.PathExpr
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.InvocationExprImpl::Impl as InvocationExprImpl
|
||||
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
|
||||
private import codeql.rust.internal.PathResolution as PathResolution
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
|
||||
pragma[nomagic]
|
||||
Path getFunctionPath(CallExpr ce) { result = ce.getFunction().(PathExpr).getPath() }
|
||||
@@ -23,9 +25,31 @@ module Impl {
|
||||
result = PathResolution::resolvePath(getFunctionPath(ce))
|
||||
}
|
||||
|
||||
private Expr getSyntacticArg(CallExpr ce, int i) { result = ce.getArgList().getArg(i) }
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A function call expression. For example:
|
||||
* NOTE: Consider using `Call` instead, as that excludes call expressions that are
|
||||
* instantiations of tuple structs and tuple variants.
|
||||
*
|
||||
* A call expression. For example:
|
||||
* ```rust
|
||||
* foo(42);
|
||||
* foo::<u32, u64>(42);
|
||||
* foo[0](42);
|
||||
* Option::Some(42); // tuple variant instantiation
|
||||
* ```
|
||||
*/
|
||||
class CallExpr extends Generated::CallExpr, InvocationExprImpl::InvocationExpr {
|
||||
override string toStringImpl() { result = this.getFunction().toAbbreviatedString() + "(...)" }
|
||||
|
||||
override Expr getSyntacticPositionalArgument(int i) { result = getSyntacticArg(this, i) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call expression that is _not_ an instantiation of a tuple struct or a tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
* foo(42);
|
||||
* foo::<u32, u64>(42);
|
||||
@@ -33,33 +57,102 @@ module Impl {
|
||||
* foo(1) = 4;
|
||||
* ```
|
||||
*/
|
||||
class CallExpr extends Generated::CallExpr {
|
||||
override string toStringImpl() { result = this.getFunction().toAbbreviatedString() + "(...)" }
|
||||
|
||||
/** Gets the struct that this call resolves to, if any. */
|
||||
Struct getStruct() { result = getResolvedFunction(this) }
|
||||
|
||||
/** Gets the variant that this call resolves to, if any. */
|
||||
Variant getVariant() { result = getResolvedFunction(this) }
|
||||
|
||||
pragma[nomagic]
|
||||
private PathResolution::ItemNode getResolvedFunctionAndPos(int pos) {
|
||||
result = getResolvedFunction(this) and
|
||||
exists(this.getArg(pos))
|
||||
class CallExprCall extends CallExpr, CallImpl::Call {
|
||||
CallExprCall() {
|
||||
not this instanceof TupleStructExpr and
|
||||
not this instanceof TupleVariantExpr
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tuple field that matches the `pos`th argument of this call, if any.
|
||||
*
|
||||
* For example, if this call is `Option::Some(42)`, then the tuple field matching
|
||||
* `42` is the first field of `Option::Some`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
TupleField getTupleField(int pos) {
|
||||
exists(PathResolution::ItemNode i | i = this.getResolvedFunctionAndPos(pos) |
|
||||
result.isStructField(i, pos) or
|
||||
result.isVariantField(i, pos)
|
||||
override Expr getPositionalArgument(int i) { result = getSyntacticArg(this, i) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call expression that targets a closure (or any value that implements
|
||||
* `Fn`, `FnMut`, or `FnOnce`).
|
||||
*
|
||||
* Dynamic calls never have a static target, and the set of potential
|
||||
* run-time targets is only available internally to the data flow library.
|
||||
*/
|
||||
class DynamicCallExpr extends CallExprCall {
|
||||
DynamicCallExpr() {
|
||||
exists(Expr f | f = this.getFunction() |
|
||||
// All calls to complex expressions and local variable accesses are lambda calls
|
||||
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call expression that is a _potential_ method call.
|
||||
*
|
||||
* Note: In order to prevent the AST layer from relying on the type inference
|
||||
* layer, we do not check that the resolved target is a method in the charpred,
|
||||
* instead we check this in `getPositionalArgument` and `getReceiver`.
|
||||
*/
|
||||
class CallExprMethodCall extends CallImpl::MethodCall, CallExprCall {
|
||||
CallExprMethodCall() { not this instanceof DynamicCallExpr }
|
||||
|
||||
private predicate isInFactMethodCall() { this.getResolvedTarget() instanceof Method }
|
||||
|
||||
override Expr getPositionalArgument(int i) {
|
||||
if this.isInFactMethodCall()
|
||||
then result = getSyntacticArg(this, i + 1)
|
||||
else result = getSyntacticArg(this, i)
|
||||
}
|
||||
|
||||
override Expr getReceiver() {
|
||||
this.isInFactMethodCall() and
|
||||
result = getSyntacticArg(this, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call expression that instantiates a tuple struct.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
* struct S(u32, u64);
|
||||
* let s = S(42, 84);
|
||||
* ```
|
||||
*/
|
||||
class TupleStructExpr extends CallExpr {
|
||||
private Struct struct;
|
||||
|
||||
TupleStructExpr() { struct = getResolvedFunction(this) }
|
||||
|
||||
/** Gets the struct that is instantiated. */
|
||||
Struct getStruct() { result = struct }
|
||||
|
||||
/** Gets the `i`th tuple field of the instantiated struct. */
|
||||
pragma[nomagic]
|
||||
TupleField getTupleField(int i) { result = this.getStruct().getTupleField(i) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TupleStructExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call expression that instantiates a tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
* enum E {
|
||||
* V(u32, u64),
|
||||
* }
|
||||
* let e = E::V(42, 84);
|
||||
* ```
|
||||
*/
|
||||
class TupleVariantExpr extends CallExpr {
|
||||
private Variant variant;
|
||||
|
||||
TupleVariantExpr() { variant = getResolvedFunction(this) }
|
||||
|
||||
/** Gets the variant that is instantiated. */
|
||||
Variant getVariant() { result = variant }
|
||||
|
||||
/** Gets the `i`th tuple field of the instantiated variant. */
|
||||
pragma[nomagic]
|
||||
TupleField getTupleField(int i) { result = this.getVariant().getTupleField(i) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TupleVariantExpr" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,209 +1,109 @@
|
||||
private import rust
|
||||
private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
|
||||
private import codeql.rust.elements.Operation
|
||||
|
||||
module Impl {
|
||||
newtype TArgumentPosition =
|
||||
TPositionalArgumentPosition(int i) {
|
||||
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1]
|
||||
} or
|
||||
TSelfArgumentPosition()
|
||||
|
||||
/** An argument position in a call. */
|
||||
class ArgumentPosition extends TArgumentPosition {
|
||||
/** Gets the index of the argument in the call, if this is a positional argument. */
|
||||
int asPosition() { this = TPositionalArgumentPosition(result) }
|
||||
|
||||
/** Holds if this call position is a self argument. */
|
||||
predicate isSelf() { this instanceof TSelfArgumentPosition }
|
||||
|
||||
/** Gets a string representation of this argument position. */
|
||||
string toString() {
|
||||
result = this.asPosition().toString()
|
||||
or
|
||||
this.isSelf() and result = "self"
|
||||
}
|
||||
}
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
|
||||
private import codeql.rust.elements.internal.InvocationExprImpl::Impl as InvocationExprImpl
|
||||
|
||||
/**
|
||||
* An expression that calls a function.
|
||||
* A call.
|
||||
*
|
||||
* This class abstracts over the different ways in which a function can be
|
||||
* called in Rust.
|
||||
* Either
|
||||
*
|
||||
* - a `CallExpr` that is _not_ an instantiation of a tuple struct or a tuple variant,
|
||||
* - a `MethodCallExpr`,
|
||||
* - an `Operation` that targets an overloadable operator, or
|
||||
* - an `IndexExpr`.
|
||||
*/
|
||||
abstract class Call extends ExprImpl::Expr {
|
||||
/** Holds if the receiver of this call is implicitly borrowed. */
|
||||
predicate receiverImplicitlyBorrowed() { this.implicitBorrowAt(TSelfArgumentPosition(), _) }
|
||||
abstract class Call extends InvocationExprImpl::InvocationExpr {
|
||||
/**
|
||||
* Gets the argument at position `pos` of this call.
|
||||
*
|
||||
* Examples:
|
||||
* ```rust
|
||||
* foo(42, "bar"); // `42` is argument 0 and `"bar"` is argument 1
|
||||
* foo.bar(42); // `foo` is receiver and `42` is argument 0
|
||||
* Foo::bar(foo, 42); // `foo` is receiver and `42` is argument 0
|
||||
* x + y; // `x` is receiver and `y` is argument 0
|
||||
* -x; // `x` is receiver
|
||||
* x[y]; // `x` is receiver and `y` is argument 0
|
||||
* ```
|
||||
*/
|
||||
final Expr getArgument(ArgumentPosition pos) {
|
||||
result = this.getPositionalArgument(pos.asPosition())
|
||||
or
|
||||
pos.isSelf() and
|
||||
result = this.(MethodCall).getReceiver()
|
||||
}
|
||||
|
||||
/** Gets the trait targeted by this call, if any. */
|
||||
abstract Trait getTrait();
|
||||
/** Gets an argument of this call. */
|
||||
Expr getAnArgument() { result = this.getArgument(_) }
|
||||
|
||||
/** Holds if this call targets a trait. */
|
||||
predicate hasTrait() { exists(this.getTrait()) }
|
||||
/**
|
||||
* Gets the `i`th positional argument of this call.
|
||||
*
|
||||
* Examples:
|
||||
* ```rust
|
||||
* foo(42, "bar"); // `42` is argument 0 and `"bar"` is argument 1
|
||||
* foo.bar(42); // `42` is argument 0
|
||||
* Foo::bar(foo, 42); // `42` is argument 0
|
||||
* x + y; // `y` is argument 0
|
||||
* -x; // no positional arguments
|
||||
* x[y]; // `y` is argument 0
|
||||
* ```
|
||||
*/
|
||||
Expr getPositionalArgument(int i) { none() }
|
||||
|
||||
/** Gets the name of the method called if this call is a method call. */
|
||||
abstract string getMethodName();
|
||||
/** Gets a positional argument of this expression. */
|
||||
Expr getAPositionalArgument() { result = this.getPositionalArgument(_) }
|
||||
|
||||
/** Gets the argument at the given position, if any. */
|
||||
abstract Expr getArgument(ArgumentPosition pos);
|
||||
/** Gets the number of positional arguments of this expression. */
|
||||
int getNumberOfPositionalArguments() {
|
||||
result = count(Expr arg | arg = this.getPositionalArgument(_))
|
||||
}
|
||||
|
||||
/** Holds if the argument at `pos` might be implicitly borrowed. */
|
||||
abstract predicate implicitBorrowAt(ArgumentPosition pos, boolean certain);
|
||||
/** Gets the resolved target of this call, if any. */
|
||||
Function getStaticTarget() { result = TypeInference::resolveCallTarget(this, _) }
|
||||
|
||||
/** Gets the number of arguments _excluding_ any `self` argument. */
|
||||
int getNumberOfArguments() { result = count(this.getArgument(TPositionalArgumentPosition(_))) }
|
||||
|
||||
/** Gets the `i`th argument of this call, if any. */
|
||||
Expr getPositionalArgument(int i) { result = this.getArgument(TPositionalArgumentPosition(i)) }
|
||||
|
||||
/** Gets the receiver of this call if it is a method call. */
|
||||
Expr getReceiver() { result = this.getArgument(TSelfArgumentPosition()) }
|
||||
|
||||
/** Gets the static target of this call, if any. */
|
||||
Function getStaticTarget() { result = TypeInference::resolveCallTarget(this) }
|
||||
/** Gets the name of the function called, if any. */
|
||||
string getTargetName() { result = this.getStaticTarget().getName().getText() }
|
||||
|
||||
/** Gets a runtime target of this call, if any. */
|
||||
pragma[nomagic]
|
||||
Function getARuntimeTarget() {
|
||||
result.hasImplementation() and
|
||||
(
|
||||
result = this.getStaticTarget()
|
||||
result = TypeInference::resolveCallTarget(this, _)
|
||||
or
|
||||
result.implements(this.getStaticTarget())
|
||||
result.implements(TypeInference::resolveCallTarget(this, true))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate callHasQualifier(CallExpr call, Path path, Path qualifier) {
|
||||
path = call.getFunction().(PathExpr).getPath() and
|
||||
qualifier = path.getQualifier()
|
||||
}
|
||||
|
||||
private predicate callHasTraitQualifier(CallExpr call, Trait qualifier) {
|
||||
exists(RelevantPath qualifierPath |
|
||||
callHasQualifier(call, _, qualifierPath) and
|
||||
qualifier = resolvePath(qualifierPath) and
|
||||
// When the qualifier is `Self` and resolves to a trait, it's inside a
|
||||
// trait method's default implementation. This is not a dispatch whose
|
||||
// target is inferred from the type of the receiver, but should always
|
||||
// resolve to the function in the trait block as path resolution does.
|
||||
not qualifierPath.isUnqualified("Self")
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the call expression dispatches to a method. */
|
||||
private predicate callIsMethodCall(
|
||||
CallExpr call, Path qualifier, string methodName, boolean selfIsRef
|
||||
) {
|
||||
exists(Path path, Function f |
|
||||
callHasQualifier(call, path, qualifier) and
|
||||
f = resolvePath(path) and
|
||||
path.getSegment().getIdentifier().getText() = methodName and
|
||||
exists(SelfParam self |
|
||||
self = f.getSelfParam() and
|
||||
if self.isRef() then selfIsRef = true else selfIsRef = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
class CallExprCall extends Call instanceof CallExpr {
|
||||
CallExprCall() { not callIsMethodCall(this, _, _, _) }
|
||||
|
||||
override string getMethodName() { none() }
|
||||
|
||||
override Trait getTrait() { callHasTraitQualifier(this, result) }
|
||||
|
||||
override predicate implicitBorrowAt(ArgumentPosition pos, boolean certain) { none() }
|
||||
|
||||
override Expr getArgument(ArgumentPosition pos) {
|
||||
result = super.getArgList().getArg(pos.asPosition())
|
||||
}
|
||||
}
|
||||
|
||||
class CallExprMethodCall extends Call instanceof CallExpr {
|
||||
string methodName;
|
||||
boolean selfIsRef;
|
||||
|
||||
CallExprMethodCall() { callIsMethodCall(this, _, methodName, selfIsRef) }
|
||||
|
||||
/**
|
||||
* A method call.
|
||||
*
|
||||
* Either
|
||||
*
|
||||
* - a `CallExpr` where we can resolve the target as a method,
|
||||
* - a `MethodCallExpr`,
|
||||
* - an `Operation` that targets an overloadable operator, or
|
||||
* - an `IndexExpr`.
|
||||
*/
|
||||
abstract class MethodCall extends Call {
|
||||
/**
|
||||
* Holds if this call must have an explicit borrow for the `self` argument,
|
||||
* because the corresponding parameter is `&self`. Explicit borrows are not
|
||||
* needed when using method call syntax.
|
||||
* Gets the receiver of this method call.
|
||||
*
|
||||
* Examples:
|
||||
* ```rust
|
||||
* foo(42, "bar"); // no receiver
|
||||
* foo.bar(42); // `foo` is receiver
|
||||
* Foo::bar(foo, 42); // `foo` is receiver
|
||||
* x + y; // `x` is receiver
|
||||
* -x; // `x` is receiver
|
||||
* x[y]; // `x` is receiver
|
||||
* ```
|
||||
*/
|
||||
predicate hasExplicitSelfBorrow() { selfIsRef = true }
|
||||
|
||||
override string getMethodName() { result = methodName }
|
||||
|
||||
override Trait getTrait() { callHasTraitQualifier(this, result) }
|
||||
|
||||
override predicate implicitBorrowAt(ArgumentPosition pos, boolean certain) { none() }
|
||||
|
||||
override Expr getArgument(ArgumentPosition pos) {
|
||||
pos.isSelf() and result = super.getArgList().getArg(0)
|
||||
or
|
||||
result = super.getArgList().getArg(pos.asPosition() + 1)
|
||||
}
|
||||
}
|
||||
|
||||
private class MethodCallExprCall extends Call instanceof MethodCallExpr {
|
||||
override string getMethodName() { result = super.getIdentifier().getText() }
|
||||
|
||||
override Trait getTrait() { none() }
|
||||
|
||||
override predicate implicitBorrowAt(ArgumentPosition pos, boolean certain) {
|
||||
pos.isSelf() and certain = false
|
||||
}
|
||||
|
||||
override Expr getArgument(ArgumentPosition pos) {
|
||||
pos.isSelf() and result = this.(MethodCallExpr).getReceiver()
|
||||
or
|
||||
result = super.getArgList().getArg(pos.asPosition())
|
||||
}
|
||||
}
|
||||
|
||||
private class OperatorCall extends Call instanceof Operation {
|
||||
Trait trait;
|
||||
string methodName;
|
||||
int borrows;
|
||||
|
||||
OperatorCall() { super.isOverloaded(trait, methodName, borrows) }
|
||||
|
||||
override string getMethodName() { result = methodName }
|
||||
|
||||
override Trait getTrait() { result = trait }
|
||||
|
||||
override predicate implicitBorrowAt(ArgumentPosition pos, boolean certain) {
|
||||
(
|
||||
pos.isSelf() and borrows >= 1
|
||||
or
|
||||
pos.asPosition() = 0 and borrows = 2
|
||||
) and
|
||||
certain = true
|
||||
}
|
||||
|
||||
override Expr getArgument(ArgumentPosition pos) {
|
||||
pos.isSelf() and result = super.getOperand(0)
|
||||
or
|
||||
pos.asPosition() = 0 and result = super.getOperand(1)
|
||||
}
|
||||
}
|
||||
|
||||
private class IndexCall extends Call instanceof IndexExpr {
|
||||
override string getMethodName() { result = "index" }
|
||||
|
||||
override Trait getTrait() { result.getCanonicalPath() = "core::ops::index::Index" }
|
||||
|
||||
override predicate implicitBorrowAt(ArgumentPosition pos, boolean certain) {
|
||||
pos.isSelf() and certain = true
|
||||
}
|
||||
|
||||
override Expr getArgument(ArgumentPosition pos) {
|
||||
pos.isSelf() and result = super.getBase()
|
||||
or
|
||||
pos.asPosition() = 0 and result = super.getIndex()
|
||||
}
|
||||
Expr getReceiver() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
*/
|
||||
|
||||
private import codeql.rust.elements.internal.generated.Const
|
||||
private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl
|
||||
private import codeql.rust.elements.internal.IdentPatImpl::Impl as IdentPatImpl
|
||||
private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl
|
||||
private import codeql.rust.internal.PathResolution
|
||||
|
||||
@@ -36,14 +38,30 @@ module Impl {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class ConstAccess extends PathExprImpl::PathExpr {
|
||||
private Const c;
|
||||
|
||||
ConstAccess() { c = resolvePath(this.getPath()) }
|
||||
|
||||
abstract class ConstAccess extends AstNodeImpl::AstNode {
|
||||
/** Gets the constant being accessed. */
|
||||
Const getConst() { result = c }
|
||||
abstract Const getConst();
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ConstAccess" }
|
||||
}
|
||||
|
||||
private class PathExprConstAccess extends ConstAccess, PathExprImpl::PathExpr {
|
||||
private Const c;
|
||||
|
||||
PathExprConstAccess() { c = resolvePath(this.getPath()) }
|
||||
|
||||
override Const getConst() { result = c }
|
||||
|
||||
override string getAPrimaryQlClass() { result = ConstAccess.super.getAPrimaryQlClass() }
|
||||
}
|
||||
|
||||
private class IdentPatConstAccess extends ConstAccess, IdentPatImpl::IdentPat {
|
||||
private Const c;
|
||||
|
||||
IdentPatConstAccess() { c = resolvePath(this) }
|
||||
|
||||
override Const getConst() { result = c }
|
||||
|
||||
override string getAPrimaryQlClass() { result = ConstAccess.super.getAPrimaryQlClass() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,5 +31,23 @@ module Impl {
|
||||
result = this.getVariantList().getAVariant() and
|
||||
result.getName().getText() = name
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a field-less enum, that is, an enum where no constructors contain fields.
|
||||
*
|
||||
* See: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.fieldless
|
||||
*/
|
||||
predicate isFieldless() {
|
||||
forall(Variant v | v = this.getVariantList().getAVariant() | v.getNumberOfFields() = 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a unit-only enum, that is, an enum where all constructors are unit variants.
|
||||
*
|
||||
* See: https://doc.rust-lang.org/reference/items/enumerations.html#r-items.enum.unit-only
|
||||
*/
|
||||
predicate isUnitOnly() {
|
||||
forall(Variant v | v = this.getVariantList().getAVariant() | v.isUnit())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@ module Impl {
|
||||
*/
|
||||
class FieldExpr extends Generated::FieldExpr {
|
||||
/** Gets the record field that this access references, if any. */
|
||||
StructField getStructField() { result = TypeInference::resolveStructFieldExpr(this) }
|
||||
StructField getStructField() { result = TypeInference::resolveStructFieldExpr(this, _) }
|
||||
|
||||
/** Gets the tuple field that this access references, if any. */
|
||||
TupleField getTupleField() { result = TypeInference::resolveTupleFieldExpr(this) }
|
||||
TupleField getTupleField() { result = TypeInference::resolveTupleFieldExpr(this, _) }
|
||||
|
||||
override string toStringImpl() {
|
||||
exists(string abbr, string name |
|
||||
|
||||
@@ -31,6 +31,8 @@ module Impl {
|
||||
|
||||
override string toStringImpl() { result = this.getName() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FormatTemplateVariableAccess" }
|
||||
|
||||
/** Gets the name of the variable */
|
||||
string getName() { result = argument.getName() }
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.generated.IndexExpr
|
||||
|
||||
/**
|
||||
@@ -11,6 +12,8 @@ private import codeql.rust.elements.internal.generated.IndexExpr
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* An index expression. For example:
|
||||
@@ -19,10 +22,20 @@ module Impl {
|
||||
* list[42] = 1;
|
||||
* ```
|
||||
*/
|
||||
class IndexExpr extends Generated::IndexExpr {
|
||||
class IndexExpr extends Generated::IndexExpr, CallImpl::MethodCall {
|
||||
override string toStringImpl() {
|
||||
result =
|
||||
this.getBase().toAbbreviatedString() + "[" + this.getIndex().toAbbreviatedString() + "]"
|
||||
}
|
||||
|
||||
override Expr getSyntacticPositionalArgument(int i) {
|
||||
i = 0 and result = this.getBase()
|
||||
or
|
||||
i = 1 and result = this.getIndex()
|
||||
}
|
||||
|
||||
override Expr getPositionalArgument(int i) { i = 0 and result = this.getIndex() }
|
||||
|
||||
override Expr getReceiver() { result = this.getBase() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
private import rust
|
||||
|
||||
module Impl {
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
|
||||
|
||||
private newtype TArgumentPosition =
|
||||
TPositionalArgumentPosition(int i) {
|
||||
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1]
|
||||
} or
|
||||
TSelfArgumentPosition()
|
||||
|
||||
/** An argument position in a call. */
|
||||
class ArgumentPosition extends TArgumentPosition {
|
||||
/** Gets the index of the argument in the call, if this is a positional argument. */
|
||||
int asPosition() { this = TPositionalArgumentPosition(result) }
|
||||
|
||||
/** Holds if this call position is a self argument. */
|
||||
predicate isSelf() { this instanceof TSelfArgumentPosition }
|
||||
|
||||
/** Gets a string representation of this argument position. */
|
||||
string toString() {
|
||||
result = this.asPosition().toString()
|
||||
or
|
||||
this.isSelf() and result = "self"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression with arguments.
|
||||
*
|
||||
* Either a `CallExpr`, a `MethodCallExpr`, an `Operation`, or an `IndexExpr`.
|
||||
*/
|
||||
abstract class InvocationExpr extends ExprImpl::Expr {
|
||||
/**
|
||||
* Gets the `i`th syntactical argument of this expression.
|
||||
*
|
||||
* Examples:
|
||||
* ```rust
|
||||
* foo(42, "bar"); // `42` is syntactic argument 0 and `"bar"` is syntactic argument 1
|
||||
* foo.bar(42); // `42` is syntactic argument 0
|
||||
* Foo::bar(foo, 42); // `foo` is syntactic argument 0 and `42` is syntactic argument 1
|
||||
* Option::Some(x); // `x` is syntactic argument 0
|
||||
* x + y; // `x` is syntactic argument 0 and `y` is syntactic argument 1
|
||||
* -x; // `x` is syntactic argument 0
|
||||
* x[y]; // `x` is syntactic argument 0 and `y` is syntactic argument 1
|
||||
* ```
|
||||
*/
|
||||
Expr getSyntacticPositionalArgument(int i) { none() }
|
||||
|
||||
/**
|
||||
* Gets the syntactic receiver of this expression, if any.
|
||||
*
|
||||
* Examples:
|
||||
* ```rust
|
||||
* foo(42, "bar"); // no syntactic receiver
|
||||
* foo.bar(42); // `foo` is syntactic receiver
|
||||
* Foo::bar(foo, 42); // no syntactic receiver
|
||||
* Option::Some(x); // no syntactic receiver
|
||||
* x + y; // no syntactic receiver
|
||||
* -x; // no syntactic receiver
|
||||
* x[y]; // no syntactic receiver
|
||||
* ```
|
||||
*/
|
||||
Expr getSyntacticReceiver() { none() }
|
||||
|
||||
/**
|
||||
* Gets the argument at syntactic position `pos` of this expression.
|
||||
*
|
||||
* Examples:
|
||||
* ```rust
|
||||
* foo(42, "bar"); // `42` is syntactic argument 0 and `"bar"` is syntactic argument 1
|
||||
* foo.bar(42); // `foo` is syntactic receiver and `42` is syntactic argument 0
|
||||
* Foo::bar(foo, 42); // `foo` is syntactic argument 0 and `42` is syntactic argument 1
|
||||
* Option::Some(x); // `x` is syntactic argument 0
|
||||
* x + y; // `x` is syntactic argument 0 and `y` is syntactic argument 1
|
||||
* -x; // `x` is syntactic argument 0
|
||||
* x[y]; // `x` is syntactic argument 0 and `y` is syntactic argument 1
|
||||
* ```
|
||||
*/
|
||||
final Expr getSyntacticArgument(ArgumentPosition pos) {
|
||||
result = this.getSyntacticPositionalArgument(pos.asPosition())
|
||||
or
|
||||
pos.isSelf() and
|
||||
result = this.getSyntacticReceiver()
|
||||
}
|
||||
|
||||
/** Gets a syntactic argument of this expression. */
|
||||
Expr getASyntacticArgument() { result = this.getSyntacticArgument(_) }
|
||||
|
||||
/** Gets the number of syntactic arguments of this expression. */
|
||||
int getNumberOfSyntacticArguments() {
|
||||
result = count(Expr arg | arg = this.getSyntacticArgument(_))
|
||||
}
|
||||
|
||||
/** Gets the resolved target (function or tuple struct/variant), if any. */
|
||||
Addressable getResolvedTarget() { result = TypeInference::resolveCallTarget(this, _) }
|
||||
}
|
||||
}
|
||||
@@ -12,15 +12,22 @@ private import codeql.rust.elements.internal.generated.MethodCallExpr
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
|
||||
private import codeql.rust.elements.internal.InvocationExprImpl::Impl as InvocationExprImpl
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* NOTE: Consider using `MethodCall` instead, as that also includes calls to methods using
|
||||
* call syntax (such as `Foo::method(x)`), operation syntax (such as `x + y`), and
|
||||
* indexing syntax (such as `x[y]`).
|
||||
*
|
||||
* A method call expression. For example:
|
||||
* ```rust
|
||||
* x.foo(42);
|
||||
* x.foo::<u32, u64>(42);
|
||||
* ```
|
||||
*/
|
||||
class MethodCallExpr extends Generated::MethodCallExpr {
|
||||
class MethodCallExpr extends Generated::MethodCallExpr, CallImpl::MethodCall {
|
||||
private string toStringPart(int index) {
|
||||
index = 0 and
|
||||
result = this.getReceiver().toAbbreviatedString()
|
||||
@@ -39,7 +46,12 @@ module Impl {
|
||||
result = strictconcat(int i | | this.toStringPart(i) order by i)
|
||||
}
|
||||
|
||||
/** Gets the static target of this method call, if any. */
|
||||
final Function getStaticTarget() { result = super.getStaticTarget() }
|
||||
override Expr getSyntacticPositionalArgument(int i) { result = this.getArgList().getArg(i) }
|
||||
|
||||
override Expr getSyntacticReceiver() { result = Generated::MethodCallExpr.super.getReceiver() }
|
||||
|
||||
override Expr getPositionalArgument(int i) { result = this.getArgList().getArg(i) }
|
||||
|
||||
override Expr getReceiver() { result = Generated::MethodCallExpr.super.getReceiver() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,100 +7,116 @@
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
|
||||
|
||||
/**
|
||||
* Holds if the operator `op` with arity `arity` is overloaded to a trait with
|
||||
* the canonical path `path` and the method name `method`, and if it borrows its
|
||||
* first `borrows` arguments.
|
||||
*/
|
||||
predicate isOverloaded(string op, int arity, string path, string method, int borrows) {
|
||||
arity = 1 and
|
||||
(
|
||||
// Negation
|
||||
op = "-" and path = "core::ops::arith::Neg" and method = "neg" and borrows = 0
|
||||
or
|
||||
// Not
|
||||
op = "!" and path = "core::ops::bit::Not" and method = "not" and borrows = 0
|
||||
or
|
||||
// Dereference
|
||||
op = "*" and path = "core::ops::deref::Deref" and method = "deref" and borrows = 1
|
||||
)
|
||||
or
|
||||
arity = 2 and
|
||||
(
|
||||
// Comparison operators
|
||||
op = "==" and path = "core::cmp::PartialEq" and method = "eq" and borrows = 2
|
||||
or
|
||||
op = "!=" and path = "core::cmp::PartialEq" and method = "ne" and borrows = 2
|
||||
or
|
||||
op = "<" and path = "core::cmp::PartialOrd" and method = "lt" and borrows = 2
|
||||
or
|
||||
op = "<=" and path = "core::cmp::PartialOrd" and method = "le" and borrows = 2
|
||||
or
|
||||
op = ">" and path = "core::cmp::PartialOrd" and method = "gt" and borrows = 2
|
||||
or
|
||||
op = ">=" and path = "core::cmp::PartialOrd" and method = "ge" and borrows = 2
|
||||
or
|
||||
// Arithmetic operators
|
||||
op = "+" and path = "core::ops::arith::Add" and method = "add" and borrows = 0
|
||||
or
|
||||
op = "-" and path = "core::ops::arith::Sub" and method = "sub" and borrows = 0
|
||||
or
|
||||
op = "*" and path = "core::ops::arith::Mul" and method = "mul" and borrows = 0
|
||||
or
|
||||
op = "/" and path = "core::ops::arith::Div" and method = "div" and borrows = 0
|
||||
or
|
||||
op = "%" and path = "core::ops::arith::Rem" and method = "rem" and borrows = 0
|
||||
or
|
||||
// Arithmetic assignment expressions
|
||||
op = "+=" and path = "core::ops::arith::AddAssign" and method = "add_assign" and borrows = 1
|
||||
or
|
||||
op = "-=" and path = "core::ops::arith::SubAssign" and method = "sub_assign" and borrows = 1
|
||||
or
|
||||
op = "*=" and path = "core::ops::arith::MulAssign" and method = "mul_assign" and borrows = 1
|
||||
or
|
||||
op = "/=" and path = "core::ops::arith::DivAssign" and method = "div_assign" and borrows = 1
|
||||
or
|
||||
op = "%=" and path = "core::ops::arith::RemAssign" and method = "rem_assign" and borrows = 1
|
||||
or
|
||||
// Bitwise operators
|
||||
op = "&" and path = "core::ops::bit::BitAnd" and method = "bitand" and borrows = 0
|
||||
or
|
||||
op = "|" and path = "core::ops::bit::BitOr" and method = "bitor" and borrows = 0
|
||||
or
|
||||
op = "^" and path = "core::ops::bit::BitXor" and method = "bitxor" and borrows = 0
|
||||
or
|
||||
op = "<<" and path = "core::ops::bit::Shl" and method = "shl" and borrows = 0
|
||||
or
|
||||
op = ">>" and path = "core::ops::bit::Shr" and method = "shr" and borrows = 0
|
||||
or
|
||||
// Bitwise assignment operators
|
||||
op = "&=" and path = "core::ops::bit::BitAndAssign" and method = "bitand_assign" and borrows = 1
|
||||
or
|
||||
op = "|=" and path = "core::ops::bit::BitOrAssign" and method = "bitor_assign" and borrows = 1
|
||||
or
|
||||
op = "^=" and path = "core::ops::bit::BitXorAssign" and method = "bitxor_assign" and borrows = 1
|
||||
or
|
||||
op = "<<=" and path = "core::ops::bit::ShlAssign" and method = "shl_assign" and borrows = 1
|
||||
or
|
||||
op = ">>=" and path = "core::ops::bit::ShrAssign" and method = "shr_assign" and borrows = 1
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the customizable definition of `Operation` and should not
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
|
||||
private import codeql.rust.elements.internal.InvocationExprImpl::Impl as InvocationExprImpl
|
||||
|
||||
/**
|
||||
* Holds if the operator `op` with arity `arity` is overloaded to a trait with
|
||||
* the canonical path `path` and the method name `method`, and if it borrows its
|
||||
* first `borrows` arguments.
|
||||
*/
|
||||
predicate isOverloaded(string op, int arity, string path, string method, int borrows) {
|
||||
arity = 1 and
|
||||
(
|
||||
// Negation
|
||||
op = "-" and path = "core::ops::arith::Neg" and method = "neg" and borrows = 0
|
||||
or
|
||||
// Not
|
||||
op = "!" and path = "core::ops::bit::Not" and method = "not" and borrows = 0
|
||||
or
|
||||
// Dereference
|
||||
op = "*" and path = "core::ops::deref::Deref" and method = "deref" and borrows = 1
|
||||
)
|
||||
or
|
||||
arity = 2 and
|
||||
(
|
||||
// Comparison operators
|
||||
op = "==" and path = "core::cmp::PartialEq" and method = "eq" and borrows = 2
|
||||
or
|
||||
op = "!=" and path = "core::cmp::PartialEq" and method = "ne" and borrows = 2
|
||||
or
|
||||
op = "<" and path = "core::cmp::PartialOrd" and method = "lt" and borrows = 2
|
||||
or
|
||||
op = "<=" and path = "core::cmp::PartialOrd" and method = "le" and borrows = 2
|
||||
or
|
||||
op = ">" and path = "core::cmp::PartialOrd" and method = "gt" and borrows = 2
|
||||
or
|
||||
op = ">=" and path = "core::cmp::PartialOrd" and method = "ge" and borrows = 2
|
||||
or
|
||||
// Arithmetic operators
|
||||
op = "+" and path = "core::ops::arith::Add" and method = "add" and borrows = 0
|
||||
or
|
||||
op = "-" and path = "core::ops::arith::Sub" and method = "sub" and borrows = 0
|
||||
or
|
||||
op = "*" and path = "core::ops::arith::Mul" and method = "mul" and borrows = 0
|
||||
or
|
||||
op = "/" and path = "core::ops::arith::Div" and method = "div" and borrows = 0
|
||||
or
|
||||
op = "%" and path = "core::ops::arith::Rem" and method = "rem" and borrows = 0
|
||||
or
|
||||
// Arithmetic assignment expressions
|
||||
op = "+=" and path = "core::ops::arith::AddAssign" and method = "add_assign" and borrows = 1
|
||||
or
|
||||
op = "-=" and path = "core::ops::arith::SubAssign" and method = "sub_assign" and borrows = 1
|
||||
or
|
||||
op = "*=" and path = "core::ops::arith::MulAssign" and method = "mul_assign" and borrows = 1
|
||||
or
|
||||
op = "/=" and path = "core::ops::arith::DivAssign" and method = "div_assign" and borrows = 1
|
||||
or
|
||||
op = "%=" and path = "core::ops::arith::RemAssign" and method = "rem_assign" and borrows = 1
|
||||
or
|
||||
// Bitwise operators
|
||||
op = "&" and path = "core::ops::bit::BitAnd" and method = "bitand" and borrows = 0
|
||||
or
|
||||
op = "|" and path = "core::ops::bit::BitOr" and method = "bitor" and borrows = 0
|
||||
or
|
||||
op = "^" and path = "core::ops::bit::BitXor" and method = "bitxor" and borrows = 0
|
||||
or
|
||||
op = "<<" and path = "core::ops::bit::Shl" and method = "shl" and borrows = 0
|
||||
or
|
||||
op = ">>" and path = "core::ops::bit::Shr" and method = "shr" and borrows = 0
|
||||
or
|
||||
// Bitwise assignment operators
|
||||
op = "&=" and
|
||||
path = "core::ops::bit::BitAndAssign" and
|
||||
method = "bitand_assign" and
|
||||
borrows = 1
|
||||
or
|
||||
op = "|=" and path = "core::ops::bit::BitOrAssign" and method = "bitor_assign" and borrows = 1
|
||||
or
|
||||
op = "^=" and
|
||||
path = "core::ops::bit::BitXorAssign" and
|
||||
method = "bitxor_assign" and
|
||||
borrows = 1
|
||||
or
|
||||
op = "<<=" and path = "core::ops::bit::ShlAssign" and method = "shl_assign" and borrows = 1
|
||||
or
|
||||
op = ">>=" and path = "core::ops::bit::ShrAssign" and method = "shr_assign" and borrows = 1
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An operation, for example `&&`, `+=`, `!` or `*`.
|
||||
*
|
||||
* Overloadable operations are syntatic sugar for method calls, where the
|
||||
* first operand is the receiver. For example, `x + y` is syntactic sugar
|
||||
* for `Add::add(x, y)`, and `x += y` is syntactic sugar for
|
||||
* `AddAssign::add_assign(&mut x, y)`.
|
||||
*/
|
||||
abstract class Operation extends ExprImpl::Expr {
|
||||
abstract class Operation extends InvocationExprImpl::InvocationExpr {
|
||||
/** Gets the operator name of this operation, if it exists. */
|
||||
abstract string getOperatorName();
|
||||
|
||||
/** Gets the `n`th operand of this operation, if any. */
|
||||
abstract Expr getOperand(int n);
|
||||
|
||||
override Expr getSyntacticPositionalArgument(int i) { result = this.getOperand(i) }
|
||||
|
||||
/**
|
||||
* Gets the number of operands of this operation.
|
||||
*
|
||||
@@ -115,9 +131,18 @@ module Impl {
|
||||
* Holds if this operation is overloaded to the method `methodName` of the
|
||||
* trait `trait`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate isOverloaded(Trait trait, string methodName, int borrows) {
|
||||
isOverloaded(this.getOperatorName(), this.getNumberOfOperands(), trait.getCanonicalPath(),
|
||||
methodName, borrows)
|
||||
}
|
||||
}
|
||||
|
||||
private class OperationMethodCall extends CallImpl::MethodCall instanceof Operation {
|
||||
OperationMethodCall() { super.isOverloaded(_, _, _) }
|
||||
|
||||
override Expr getPositionalArgument(int i) { result = super.getOperand(i + 1) and i >= 0 }
|
||||
|
||||
override Expr getReceiver() { result = super.getOperand(0) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.generated.PathExpr
|
||||
|
||||
/**
|
||||
@@ -25,5 +26,11 @@ module Impl {
|
||||
override string toStringImpl() { result = this.toAbbreviatedString() }
|
||||
|
||||
override string toAbbreviatedString() { result = this.getPath().toStringImpl() }
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
if this instanceof VariableAccess
|
||||
then result = "VariableAccess"
|
||||
else result = super.getAPrimaryQlClass()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,16 @@ module Impl {
|
||||
class StructExpr extends Generated::StructExpr {
|
||||
override string toStringImpl() { result = this.getPath().toStringImpl() + " {...}" }
|
||||
|
||||
private PathResolution::ItemNode getResolvedPath() {
|
||||
result = PathResolution::resolvePath(this.getPath())
|
||||
}
|
||||
|
||||
/** Gets the struct that is instantiated, if any. */
|
||||
Struct getStruct() { result = this.getResolvedPath() }
|
||||
|
||||
/** Gets the variant that is instantiated, if any. */
|
||||
Variant getVariant() { result = this.getResolvedPath() }
|
||||
|
||||
/** Gets the record expression for the field `name`. */
|
||||
pragma[nomagic]
|
||||
StructExprField getFieldExpr(string name) {
|
||||
@@ -34,19 +44,11 @@ module Impl {
|
||||
name = result.getFieldName()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathResolution::ItemNode getResolvedPath(string name) {
|
||||
result = PathResolution::resolvePath(this.getPath()) and
|
||||
exists(this.getFieldExpr(name))
|
||||
}
|
||||
|
||||
/** Gets the record field that matches the `name` field of this record expression. */
|
||||
pragma[nomagic]
|
||||
/** Gets the record field named `name` of the instantiated struct or variant. */
|
||||
StructField getStructField(string name) {
|
||||
exists(PathResolution::ItemNode i | i = this.getResolvedPath(name) |
|
||||
result.isStructField(i, name) or
|
||||
result.isVariantField(i, name)
|
||||
)
|
||||
result = this.getStruct().getStructField(name)
|
||||
or
|
||||
result = this.getVariant().getStructField(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +29,19 @@ module Impl {
|
||||
|
||||
/** Holds if this record field is named `name` and belongs to the struct `s`. */
|
||||
predicate isStructField(Struct s, string name) { this = s.getStructField(name) }
|
||||
|
||||
override string toStringImpl() {
|
||||
result = strictconcat(int i | | this.toStringPart(i) order by i)
|
||||
}
|
||||
|
||||
private string toStringPart(int index) {
|
||||
index = 0 and result = this.getVisibility().toAbbreviatedString() + " "
|
||||
or
|
||||
index = 1 and result = this.getName().getText()
|
||||
or
|
||||
index = 2 and result = ": "
|
||||
or
|
||||
index = 3 and result = this.getTypeRepr().toAbbreviatedString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,12 +46,11 @@ module Impl {
|
||||
pragma[nomagic]
|
||||
predicate isTuple() { this.getFieldList() instanceof TupleFieldList }
|
||||
|
||||
/**
|
||||
* Holds if this struct uses record fields.
|
||||
*
|
||||
* Empty structs are considered to use record fields.
|
||||
*/
|
||||
/** Holds if this struct uses struct fields. */
|
||||
pragma[nomagic]
|
||||
predicate isStruct() { not this.isTuple() }
|
||||
predicate isStruct() { this.getFieldList() instanceof StructFieldList }
|
||||
|
||||
/** Holds if this struct does not have a field list. */
|
||||
predicate isUnit() { not this.hasFieldList() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ module Impl {
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A field in a tuple struct or tuple enum variant.
|
||||
* A field in a tuple struct or tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
|
||||
@@ -13,7 +13,7 @@ private import codeql.rust.elements.internal.generated.TupleFieldList
|
||||
*/
|
||||
module Impl {
|
||||
/**
|
||||
* A list of fields in a tuple struct or tuple enum variant.
|
||||
* A list of fields in a tuple struct or tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
private import rust
|
||||
private import codeql.rust.controlflow.ControlFlowGraph
|
||||
private import codeql.rust.internal.PathResolution as PathResolution
|
||||
private import codeql.rust.elements.internal.generated.ParentChild as ParentChild
|
||||
private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl
|
||||
private import codeql.rust.elements.internal.PathImpl::Impl as PathImpl
|
||||
private import codeql.rust.elements.internal.PathExprBaseImpl::Impl as PathExprBaseImpl
|
||||
private import codeql.rust.elements.internal.FormatTemplateVariableAccessImpl::Impl as FormatTemplateVariableAccessImpl
|
||||
private import codeql.util.DenseRank
|
||||
|
||||
@@ -98,7 +99,7 @@ module Impl {
|
||||
* pattern.
|
||||
*/
|
||||
cached
|
||||
private predicate variableDecl(AstNode definingNode, Name name, string text) {
|
||||
predicate variableDecl(AstNode definingNode, Name name, string text) {
|
||||
Cached::ref() and
|
||||
exists(SelfParam sp |
|
||||
name = sp.getName() and
|
||||
@@ -117,11 +118,7 @@ module Impl {
|
||||
not exists(getOutermostEnclosingOrPat(pat)) and definingNode = name
|
||||
) and
|
||||
text = name.getText() and
|
||||
// exclude for now anything starting with an uppercase character, which may be a reference to
|
||||
// an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
|
||||
// which we don't appear to recognize yet anyway. This also assumes programmers follow the
|
||||
// naming guidelines, which they generally do, but they're not enforced.
|
||||
not text.charAt(0).isUppercase() and
|
||||
not PathResolution::identPatIsResolvable(pat) and
|
||||
// exclude parameters from functions without a body as these are trait method declarations
|
||||
// without implementations
|
||||
not exists(Function f | not f.hasBody() and f.getAParam().getPat() = pat) and
|
||||
@@ -666,7 +663,7 @@ module Impl {
|
||||
}
|
||||
|
||||
/** A variable access. */
|
||||
class VariableAccess extends PathExprBaseImpl::PathExprBase {
|
||||
class VariableAccess extends PathExprBase {
|
||||
private string name;
|
||||
private Variable v;
|
||||
|
||||
@@ -677,18 +674,14 @@ module Impl {
|
||||
|
||||
/** Holds if this access is a capture. */
|
||||
predicate isCapture() { this.getEnclosingCfgScope() != v.getEnclosingCfgScope() }
|
||||
|
||||
override string toStringImpl() { result = name }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "VariableAccess" }
|
||||
}
|
||||
|
||||
/** Holds if `e` occurs in the LHS of an assignment or compound assignment. */
|
||||
private predicate assignmentExprDescendant(AssignmentExpr ae, Expr e) {
|
||||
e = ae.getLhs()
|
||||
/** Holds if `e` occurs in the LHS of an assignment operation. */
|
||||
predicate assignmentOperationDescendant(AssignmentOperation ao, Expr e) {
|
||||
e = ao.getLhs()
|
||||
or
|
||||
exists(Expr mid |
|
||||
assignmentExprDescendant(ae, mid) and
|
||||
assignmentOperationDescendant(ao, mid) and
|
||||
getImmediateParentAdj(e) = mid and
|
||||
not mid instanceof DerefExpr and
|
||||
not mid instanceof FieldExpr and
|
||||
@@ -703,7 +696,7 @@ module Impl {
|
||||
cached
|
||||
VariableWriteAccess() {
|
||||
Cached::ref() and
|
||||
assignmentExprDescendant(ae, this)
|
||||
assignmentOperationDescendant(ae, this)
|
||||
}
|
||||
|
||||
/** Gets the assignment expression that has this write access in the left-hand side. */
|
||||
@@ -722,7 +715,7 @@ module Impl {
|
||||
}
|
||||
|
||||
/** A nested function access. */
|
||||
class NestedFunctionAccess extends PathExprBaseImpl::PathExprBase {
|
||||
class NestedFunctionAccess extends PathExprBase {
|
||||
private Function f;
|
||||
|
||||
NestedFunctionAccess() { nestedFunctionAccess(_, f, this) }
|
||||
|
||||
@@ -36,17 +36,27 @@ module Impl {
|
||||
pragma[nomagic]
|
||||
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }
|
||||
|
||||
/** Gets the number of fields of this variant. */
|
||||
int getNumberOfFields() {
|
||||
not this.hasFieldList() and
|
||||
result = 0
|
||||
or
|
||||
result = this.getFieldList().(StructFieldList).getNumberOfFields()
|
||||
or
|
||||
result = this.getFieldList().(TupleFieldList).getNumberOfFields()
|
||||
}
|
||||
|
||||
/** Holds if this variant uses tuple fields. */
|
||||
pragma[nomagic]
|
||||
predicate isTuple() { this.getFieldList() instanceof TupleFieldList }
|
||||
|
||||
/**
|
||||
* Holds if this variant uses struct fields.
|
||||
*
|
||||
* Empty variants are considered to use struct fields.
|
||||
*/
|
||||
/** Holds if this variant uses struct fields. */
|
||||
pragma[nomagic]
|
||||
predicate isStruct() { not this.isTuple() }
|
||||
predicate isStruct() { this.getFieldList() instanceof StructFieldList }
|
||||
|
||||
/** Holds if this variant does not have a field list. */
|
||||
pragma[nomagic]
|
||||
predicate isUnit() { not this.hasFieldList() }
|
||||
|
||||
/** Gets the enum that this variant belongs to. */
|
||||
Enum getEnum() { this = result.getVariantList().getAVariant() }
|
||||
|
||||
@@ -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 `Visibility`.
|
||||
*
|
||||
@@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.Visibility
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A visibility modifier.
|
||||
*
|
||||
@@ -21,5 +21,13 @@ module Impl {
|
||||
* //^^^
|
||||
* ```
|
||||
*/
|
||||
class Visibility extends Generated::Visibility { }
|
||||
class Visibility extends Generated::Visibility {
|
||||
override string toStringImpl() { result = this.toAbbreviatedString() }
|
||||
|
||||
override string toAbbreviatedString() {
|
||||
result = "pub(" + this.getPath().toAbbreviatedString() + ")"
|
||||
or
|
||||
not this.hasPath() and result = "pub"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
|
||||
private import codeql.rust.elements.internal.generated.Synth
|
||||
private import codeql.rust.elements.internal.generated.Raw
|
||||
import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
|
||||
import codeql.rust.elements.ArgList
|
||||
import codeql.rust.elements.Attr
|
||||
import codeql.rust.elements.Expr
|
||||
import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the fully generated definition of `CallExpr` and should not
|
||||
@@ -15,19 +17,53 @@ import codeql.rust.elements.Expr
|
||||
*/
|
||||
module Generated {
|
||||
/**
|
||||
* A function call expression. For example:
|
||||
* NOTE: Consider using `Call` instead, as that excludes call expressions that are
|
||||
* instantiations of tuple structs and tuple variants.
|
||||
*
|
||||
* A call expression. For example:
|
||||
* ```rust
|
||||
* foo(42);
|
||||
* foo::<u32, u64>(42);
|
||||
* foo[0](42);
|
||||
* foo(1) = 4;
|
||||
* Option::Some(42); // tuple variant instantiation
|
||||
* ```
|
||||
* INTERNAL: Do not reference the `Generated::CallExpr` class directly.
|
||||
* Use the subclass `CallExpr`, where the following predicates are available.
|
||||
*/
|
||||
class CallExpr extends Synth::TCallExpr, CallExprBaseImpl::CallExprBase {
|
||||
class CallExpr extends Synth::TCallExpr, ExprImpl::Expr {
|
||||
override string getAPrimaryQlClass() { result = "CallExpr" }
|
||||
|
||||
/**
|
||||
* Gets the argument list of this call expression, if it exists.
|
||||
*/
|
||||
ArgList getArgList() {
|
||||
result =
|
||||
Synth::convertArgListFromRaw(Synth::convertCallExprToRaw(this).(Raw::CallExpr).getArgList())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `getArgList()` exists.
|
||||
*/
|
||||
final predicate hasArgList() { exists(this.getArgList()) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th attr of this call expression (0-based).
|
||||
*/
|
||||
Attr getAttr(int index) {
|
||||
result =
|
||||
Synth::convertAttrFromRaw(Synth::convertCallExprToRaw(this).(Raw::CallExpr).getAttr(index))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any of the attrs of this call expression.
|
||||
*/
|
||||
final Attr getAnAttr() { result = this.getAttr(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of attrs of this call expression.
|
||||
*/
|
||||
final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) }
|
||||
|
||||
/**
|
||||
* Gets the function of this call expression, if it exists.
|
||||
*/
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
// generated by codegen, do not edit
|
||||
/**
|
||||
* This module provides the generated definition of `CallExprBase`.
|
||||
* INTERNAL: Do not import directly.
|
||||
*/
|
||||
|
||||
private import codeql.rust.elements.internal.generated.Synth
|
||||
private import codeql.rust.elements.internal.generated.Raw
|
||||
import codeql.rust.elements.ArgList
|
||||
import codeql.rust.elements.Attr
|
||||
import codeql.rust.elements.Expr
|
||||
import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the fully generated definition of `CallExprBase` and should not
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Generated {
|
||||
/**
|
||||
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
|
||||
* INTERNAL: Do not reference the `Generated::CallExprBase` class directly.
|
||||
* Use the subclass `CallExprBase`, where the following predicates are available.
|
||||
*/
|
||||
class CallExprBase extends Synth::TCallExprBase, ExprImpl::Expr {
|
||||
/**
|
||||
* Gets the argument list of this call expression base, if it exists.
|
||||
*/
|
||||
ArgList getArgList() {
|
||||
result =
|
||||
Synth::convertArgListFromRaw(Synth::convertCallExprBaseToRaw(this)
|
||||
.(Raw::CallExprBase)
|
||||
.getArgList())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `getArgList()` exists.
|
||||
*/
|
||||
final predicate hasArgList() { exists(this.getArgList()) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th attr of this call expression base (0-based).
|
||||
*/
|
||||
Attr getAttr(int index) {
|
||||
result =
|
||||
Synth::convertAttrFromRaw(Synth::convertCallExprBaseToRaw(this)
|
||||
.(Raw::CallExprBase)
|
||||
.getAttr(index))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any of the attrs of this call expression base.
|
||||
*/
|
||||
final Attr getAnAttr() { result = this.getAttr(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of attrs of this call expression base.
|
||||
*/
|
||||
final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th argument of this call expression base (0-based).
|
||||
*/
|
||||
Expr getArg(int index) { none() }
|
||||
|
||||
/**
|
||||
* Gets any of the arguments of this call expression base.
|
||||
*/
|
||||
final Expr getAnArg() { result = this.getArg(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of arguments of this call expression base.
|
||||
*/
|
||||
final int getNumberOfArgs() { result = count(int i | exists(this.getArg(i))) }
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,10 @@
|
||||
|
||||
private import codeql.rust.elements.internal.generated.Synth
|
||||
private import codeql.rust.elements.internal.generated.Raw
|
||||
import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
|
||||
import codeql.rust.elements.ArgList
|
||||
import codeql.rust.elements.Attr
|
||||
import codeql.rust.elements.Expr
|
||||
import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
|
||||
import codeql.rust.elements.GenericArgList
|
||||
import codeql.rust.elements.NameRef
|
||||
|
||||
@@ -17,6 +19,10 @@ import codeql.rust.elements.NameRef
|
||||
*/
|
||||
module Generated {
|
||||
/**
|
||||
* NOTE: Consider using `MethodCall` instead, as that also includes calls to methods using
|
||||
* call syntax (such as `Foo::method(x)`), operation syntax (such as `x + y`), and
|
||||
* indexing syntax (such as `x[y]`).
|
||||
*
|
||||
* A method call expression. For example:
|
||||
* ```rust
|
||||
* x.foo(42);
|
||||
@@ -25,9 +31,44 @@ module Generated {
|
||||
* INTERNAL: Do not reference the `Generated::MethodCallExpr` class directly.
|
||||
* Use the subclass `MethodCallExpr`, where the following predicates are available.
|
||||
*/
|
||||
class MethodCallExpr extends Synth::TMethodCallExpr, CallExprBaseImpl::CallExprBase {
|
||||
class MethodCallExpr extends Synth::TMethodCallExpr, ExprImpl::Expr {
|
||||
override string getAPrimaryQlClass() { result = "MethodCallExpr" }
|
||||
|
||||
/**
|
||||
* Gets the argument list of this method call expression, if it exists.
|
||||
*/
|
||||
ArgList getArgList() {
|
||||
result =
|
||||
Synth::convertArgListFromRaw(Synth::convertMethodCallExprToRaw(this)
|
||||
.(Raw::MethodCallExpr)
|
||||
.getArgList())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `getArgList()` exists.
|
||||
*/
|
||||
final predicate hasArgList() { exists(this.getArgList()) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th attr of this method call expression (0-based).
|
||||
*/
|
||||
Attr getAttr(int index) {
|
||||
result =
|
||||
Synth::convertAttrFromRaw(Synth::convertMethodCallExprToRaw(this)
|
||||
.(Raw::MethodCallExpr)
|
||||
.getAttr(index))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any of the attrs of this method call expression.
|
||||
*/
|
||||
final Attr getAnAttr() { result = this.getAttr(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of attrs of this method call expression.
|
||||
*/
|
||||
final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) }
|
||||
|
||||
/**
|
||||
* Gets the generic argument list of this method call expression, if it exists.
|
||||
*/
|
||||
|
||||
@@ -1070,6 +1070,25 @@ private module Impl {
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfCallExpr(CallExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nArgList, int nAttr, int nFunction |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nFunction = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
index = n and result = e.getArgList() and partialPredicateCall = "ArgList()"
|
||||
or
|
||||
result = e.getAttr(index - nArgList) and
|
||||
partialPredicateCall = "Attr(" + (index - nArgList).toString() + ")"
|
||||
or
|
||||
index = nAttr and result = e.getFunction() and partialPredicateCall = "Function()"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfCastExpr(CastExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nAttr, int nExpr, int nTypeRepr |
|
||||
n = 0 and
|
||||
@@ -1563,6 +1582,37 @@ private module Impl {
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfMethodCallExpr(
|
||||
MethodCallExpr e, int index, string partialPredicateCall
|
||||
) {
|
||||
exists(int n, int nArgList, int nAttr, int nGenericArgList, int nIdentifier, int nReceiver |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nGenericArgList = nAttr + 1 and
|
||||
nIdentifier = nGenericArgList + 1 and
|
||||
nReceiver = nIdentifier + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
index = n and result = e.getArgList() and partialPredicateCall = "ArgList()"
|
||||
or
|
||||
result = e.getAttr(index - nArgList) and
|
||||
partialPredicateCall = "Attr(" + (index - nArgList).toString() + ")"
|
||||
or
|
||||
index = nAttr and
|
||||
result = e.getGenericArgList() and
|
||||
partialPredicateCall = "GenericArgList()"
|
||||
or
|
||||
index = nGenericArgList and
|
||||
result = e.getIdentifier() and
|
||||
partialPredicateCall = "Identifier()"
|
||||
or
|
||||
index = nIdentifier and result = e.getReceiver() and partialPredicateCall = "Receiver()"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfNameRef(NameRef e, int index, string partialPredicateCall) {
|
||||
none()
|
||||
}
|
||||
@@ -2228,25 +2278,6 @@ private module Impl {
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfCallExpr(CallExpr e, int index, string partialPredicateCall) {
|
||||
exists(int n, int nArgList, int nAttr, int nFunction |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nFunction = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
index = n and result = e.getArgList() and partialPredicateCall = "ArgList()"
|
||||
or
|
||||
result = e.getAttr(index - nArgList) and
|
||||
partialPredicateCall = "Attr(" + (index - nArgList).toString() + ")"
|
||||
or
|
||||
index = nAttr and result = e.getFunction() and partialPredicateCall = "Function()"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfExternBlock(
|
||||
ExternBlock e, int index, string partialPredicateCall
|
||||
) {
|
||||
@@ -2421,37 +2452,6 @@ private module Impl {
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfMethodCallExpr(
|
||||
MethodCallExpr e, int index, string partialPredicateCall
|
||||
) {
|
||||
exists(int n, int nArgList, int nAttr, int nGenericArgList, int nIdentifier, int nReceiver |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nGenericArgList = nAttr + 1 and
|
||||
nIdentifier = nGenericArgList + 1 and
|
||||
nReceiver = nIdentifier + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
index = n and result = e.getArgList() and partialPredicateCall = "ArgList()"
|
||||
or
|
||||
result = e.getAttr(index - nArgList) and
|
||||
partialPredicateCall = "Attr(" + (index - nArgList).toString() + ")"
|
||||
or
|
||||
index = nAttr and
|
||||
result = e.getGenericArgList() and
|
||||
partialPredicateCall = "GenericArgList()"
|
||||
or
|
||||
index = nGenericArgList and
|
||||
result = e.getIdentifier() and
|
||||
partialPredicateCall = "Identifier()"
|
||||
or
|
||||
index = nIdentifier and result = e.getReceiver() and partialPredicateCall = "Receiver()"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfModule(Module e, int index, string partialPredicateCall) {
|
||||
exists(
|
||||
int n, int nAttributeMacroExpansion, int nAttr, int nItemList, int nName, int nVisibility
|
||||
@@ -3167,6 +3167,8 @@ private module Impl {
|
||||
or
|
||||
result = getImmediateChildOfBreakExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfCallExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfCastExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfClosureExpr(e, index, partialAccessor)
|
||||
@@ -3227,6 +3229,8 @@ private module Impl {
|
||||
or
|
||||
result = getImmediateChildOfMatchExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfMethodCallExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfNameRef(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfNeverTypeRepr(e, index, partialAccessor)
|
||||
@@ -3311,8 +3315,6 @@ private module Impl {
|
||||
or
|
||||
result = getImmediateChildOfBlockExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfCallExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfExternBlock(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfExternCrate(e, index, partialAccessor)
|
||||
@@ -3325,8 +3327,6 @@ private module Impl {
|
||||
or
|
||||
result = getImmediateChildOfMacroRules(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfMethodCallExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfModule(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfPathExpr(e, index, partialAccessor)
|
||||
|
||||
@@ -1808,7 +1808,7 @@ module Raw {
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* A field in a tuple struct or tuple enum variant.
|
||||
* A field in a tuple struct or tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
@@ -2942,23 +2942,57 @@ module Raw {
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
|
||||
* NOTE: Consider using `Call` instead, as that excludes call expressions that are
|
||||
* instantiations of tuple structs and tuple variants.
|
||||
*
|
||||
* A call expression. For example:
|
||||
* ```rust
|
||||
* foo(42);
|
||||
* foo::<u32, u64>(42);
|
||||
* foo[0](42);
|
||||
* Option::Some(42); // tuple variant instantiation
|
||||
* ```
|
||||
*/
|
||||
class CallExprBase extends @call_expr_base, Expr {
|
||||
/**
|
||||
* Gets the argument list of this call expression base, if it exists.
|
||||
*/
|
||||
ArgList getArgList() { call_expr_base_arg_lists(this, result) }
|
||||
class CallExpr extends @call_expr, Expr {
|
||||
override string toString() { result = "CallExpr" }
|
||||
|
||||
/**
|
||||
* Gets the `index`th attr of this call expression base (0-based).
|
||||
* Gets the argument list of this call expression, if it exists.
|
||||
*/
|
||||
Attr getAttr(int index) { call_expr_base_attrs(this, index, result) }
|
||||
ArgList getArgList() { call_expr_arg_lists(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the number of attrs of this call expression base.
|
||||
* Gets the `index`th attr of this call expression (0-based).
|
||||
*/
|
||||
int getNumberOfAttrs() { result = count(int i | call_expr_base_attrs(this, i, _)) }
|
||||
Attr getAttr(int index) { call_expr_attrs(this, index, result) }
|
||||
|
||||
/**
|
||||
* Gets the number of attrs of this call expression.
|
||||
*/
|
||||
int getNumberOfAttrs() { result = count(int i | call_expr_attrs(this, i, _)) }
|
||||
|
||||
/**
|
||||
* Gets the function of this call expression, if it exists.
|
||||
*/
|
||||
Expr getFunction() { call_expr_functions(this, result) }
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfCallExpr(CallExpr e, int index) {
|
||||
exists(int n, int nArgList, int nAttr, int nFunction |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nFunction = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
index = n and result = e.getArgList()
|
||||
or
|
||||
result = e.getAttr(index - nArgList)
|
||||
or
|
||||
index = nAttr and result = e.getFunction()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4345,6 +4379,76 @@ module Raw {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* NOTE: Consider using `MethodCall` instead, as that also includes calls to methods using
|
||||
* call syntax (such as `Foo::method(x)`), operation syntax (such as `x + y`), and
|
||||
* indexing syntax (such as `x[y]`).
|
||||
*
|
||||
* A method call expression. For example:
|
||||
* ```rust
|
||||
* x.foo(42);
|
||||
* x.foo::<u32, u64>(42);
|
||||
* ```
|
||||
*/
|
||||
class MethodCallExpr extends @method_call_expr, Expr {
|
||||
override string toString() { result = "MethodCallExpr" }
|
||||
|
||||
/**
|
||||
* Gets the argument list of this method call expression, if it exists.
|
||||
*/
|
||||
ArgList getArgList() { method_call_expr_arg_lists(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th attr of this method call expression (0-based).
|
||||
*/
|
||||
Attr getAttr(int index) { method_call_expr_attrs(this, index, result) }
|
||||
|
||||
/**
|
||||
* Gets the number of attrs of this method call expression.
|
||||
*/
|
||||
int getNumberOfAttrs() { result = count(int i | method_call_expr_attrs(this, i, _)) }
|
||||
|
||||
/**
|
||||
* Gets the generic argument list of this method call expression, if it exists.
|
||||
*/
|
||||
GenericArgList getGenericArgList() { method_call_expr_generic_arg_lists(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the identifier of this method call expression, if it exists.
|
||||
*/
|
||||
NameRef getIdentifier() { method_call_expr_identifiers(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the receiver of this method call expression, if it exists.
|
||||
*/
|
||||
Expr getReceiver() { method_call_expr_receivers(this, result) }
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfMethodCallExpr(MethodCallExpr e, int index) {
|
||||
exists(int n, int nArgList, int nAttr, int nGenericArgList, int nIdentifier, int nReceiver |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nGenericArgList = nAttr + 1 and
|
||||
nIdentifier = nGenericArgList + 1 and
|
||||
nReceiver = nIdentifier + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
index = n and result = e.getArgList()
|
||||
or
|
||||
result = e.getAttr(index - nArgList)
|
||||
or
|
||||
index = nAttr and result = e.getGenericArgList()
|
||||
or
|
||||
index = nGenericArgList and result = e.getIdentifier()
|
||||
or
|
||||
index = nIdentifier and result = e.getReceiver()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* A reference to a name.
|
||||
@@ -5418,7 +5522,7 @@ module Raw {
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* A list of fields in a tuple struct or tuple enum variant.
|
||||
* A list of fields in a tuple struct or tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
@@ -6033,43 +6137,6 @@ module Raw {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* A function call expression. For example:
|
||||
* ```rust
|
||||
* foo(42);
|
||||
* foo::<u32, u64>(42);
|
||||
* foo[0](42);
|
||||
* foo(1) = 4;
|
||||
* ```
|
||||
*/
|
||||
class CallExpr extends @call_expr, CallExprBase {
|
||||
override string toString() { result = "CallExpr" }
|
||||
|
||||
/**
|
||||
* Gets the function of this call expression, if it exists.
|
||||
*/
|
||||
Expr getFunction() { call_expr_functions(this, result) }
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfCallExpr(CallExpr e, int index) {
|
||||
exists(int n, int nArgList, int nAttr, int nFunction |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nFunction = nAttr + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
index = n and result = e.getArgList()
|
||||
or
|
||||
result = e.getAttr(index - nArgList)
|
||||
or
|
||||
index = nAttr and result = e.getFunction()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* An extern block containing foreign function declarations.
|
||||
@@ -6467,57 +6534,6 @@ module Raw {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* A method call expression. For example:
|
||||
* ```rust
|
||||
* x.foo(42);
|
||||
* x.foo::<u32, u64>(42);
|
||||
* ```
|
||||
*/
|
||||
class MethodCallExpr extends @method_call_expr, CallExprBase {
|
||||
override string toString() { result = "MethodCallExpr" }
|
||||
|
||||
/**
|
||||
* Gets the generic argument list of this method call expression, if it exists.
|
||||
*/
|
||||
GenericArgList getGenericArgList() { method_call_expr_generic_arg_lists(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the identifier of this method call expression, if it exists.
|
||||
*/
|
||||
NameRef getIdentifier() { method_call_expr_identifiers(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the receiver of this method call expression, if it exists.
|
||||
*/
|
||||
Expr getReceiver() { method_call_expr_receivers(this, result) }
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfMethodCallExpr(MethodCallExpr e, int index) {
|
||||
exists(int n, int nArgList, int nAttr, int nGenericArgList, int nIdentifier, int nReceiver |
|
||||
n = 0 and
|
||||
nArgList = n + 1 and
|
||||
nAttr = nArgList + e.getNumberOfAttrs() and
|
||||
nGenericArgList = nAttr + 1 and
|
||||
nIdentifier = nGenericArgList + 1 and
|
||||
nReceiver = nIdentifier + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
index = n and result = e.getArgList()
|
||||
or
|
||||
result = e.getAttr(index - nArgList)
|
||||
or
|
||||
index = nAttr and result = e.getGenericArgList()
|
||||
or
|
||||
index = nGenericArgList and result = e.getIdentifier()
|
||||
or
|
||||
index = nIdentifier and result = e.getReceiver()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* A module declaration. For example:
|
||||
@@ -7907,6 +7923,8 @@ module Raw {
|
||||
or
|
||||
result = getImmediateChildOfBreakExpr(e, index)
|
||||
or
|
||||
result = getImmediateChildOfCallExpr(e, index)
|
||||
or
|
||||
result = getImmediateChildOfCastExpr(e, index)
|
||||
or
|
||||
result = getImmediateChildOfClosureExpr(e, index)
|
||||
@@ -7967,6 +7985,8 @@ module Raw {
|
||||
or
|
||||
result = getImmediateChildOfMatchExpr(e, index)
|
||||
or
|
||||
result = getImmediateChildOfMethodCallExpr(e, index)
|
||||
or
|
||||
result = getImmediateChildOfNameRef(e, index)
|
||||
or
|
||||
result = getImmediateChildOfNeverTypeRepr(e, index)
|
||||
@@ -8047,8 +8067,6 @@ module Raw {
|
||||
or
|
||||
result = getImmediateChildOfBlockExpr(e, index)
|
||||
or
|
||||
result = getImmediateChildOfCallExpr(e, index)
|
||||
or
|
||||
result = getImmediateChildOfExternBlock(e, index)
|
||||
or
|
||||
result = getImmediateChildOfExternCrate(e, index)
|
||||
@@ -8059,8 +8077,6 @@ module Raw {
|
||||
or
|
||||
result = getImmediateChildOfMacroRules(e, index)
|
||||
or
|
||||
result = getImmediateChildOfMethodCallExpr(e, index)
|
||||
or
|
||||
result = getImmediateChildOfModule(e, index)
|
||||
or
|
||||
result = getImmediateChildOfPathExpr(e, index)
|
||||
|
||||
@@ -729,11 +729,6 @@ module Synth {
|
||||
TTypeBoundList or TTypeRepr or TUseBoundGenericArg or TUseBoundGenericArgs or TUseTree or
|
||||
TUseTreeList or TVariantList or TVisibility or TWhereClause or TWherePred;
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
class TCallExprBase = TCallExpr or TMethodCallExpr;
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
@@ -744,11 +739,11 @@ module Synth {
|
||||
*/
|
||||
class TExpr =
|
||||
TArrayExpr or TArrayExprInternal or TAsmExpr or TAwaitExpr or TBecomeExpr or TBinaryExpr or
|
||||
TBreakExpr or TCallExprBase or TCastExpr or TClosureExpr or TContinueExpr or TFieldExpr or
|
||||
TBreakExpr or TCallExpr or TCastExpr or TClosureExpr or TContinueExpr or TFieldExpr or
|
||||
TFormatArgsExpr or TIfExpr or TIndexExpr or TLabelableExpr or TLetExpr or TLiteralExpr or
|
||||
TMacroBlockExpr or TMacroExpr or TMatchExpr or TOffsetOfExpr or TParenExpr or
|
||||
TPathExprBase or TPrefixExpr or TRangeExpr or TRefExpr or TReturnExpr or TStructExpr or
|
||||
TTryExpr or TTupleExpr or TUnderscoreExpr or TYeetExpr or TYieldExpr;
|
||||
TMacroBlockExpr or TMacroExpr or TMatchExpr or TMethodCallExpr or TOffsetOfExpr or
|
||||
TParenExpr or TPathExprBase or TPrefixExpr or TRangeExpr or TRefExpr or TReturnExpr or
|
||||
TStructExpr or TTryExpr or TTupleExpr or TUnderscoreExpr or TYeetExpr or TYieldExpr;
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
@@ -2229,16 +2224,6 @@ module Synth {
|
||||
result = convertWherePredFromRaw(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a raw DB element to a synthesized `TCallExprBase`, if possible.
|
||||
*/
|
||||
TCallExprBase convertCallExprBaseFromRaw(Raw::Element e) {
|
||||
result = convertCallExprFromRaw(e)
|
||||
or
|
||||
result = convertMethodCallExprFromRaw(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a raw DB element to a synthesized `TCallable`, if possible.
|
||||
@@ -2282,7 +2267,7 @@ module Synth {
|
||||
or
|
||||
result = convertBreakExprFromRaw(e)
|
||||
or
|
||||
result = convertCallExprBaseFromRaw(e)
|
||||
result = convertCallExprFromRaw(e)
|
||||
or
|
||||
result = convertCastExprFromRaw(e)
|
||||
or
|
||||
@@ -2310,6 +2295,8 @@ module Synth {
|
||||
or
|
||||
result = convertMatchExprFromRaw(e)
|
||||
or
|
||||
result = convertMethodCallExprFromRaw(e)
|
||||
or
|
||||
result = convertOffsetOfExprFromRaw(e)
|
||||
or
|
||||
result = convertParenExprFromRaw(e)
|
||||
@@ -3805,16 +3792,6 @@ module Synth {
|
||||
result = convertWherePredToRaw(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a synthesized `TCallExprBase` to a raw DB element, if possible.
|
||||
*/
|
||||
Raw::Element convertCallExprBaseToRaw(TCallExprBase e) {
|
||||
result = convertCallExprToRaw(e)
|
||||
or
|
||||
result = convertMethodCallExprToRaw(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a synthesized `TCallable` to a raw DB element, if possible.
|
||||
@@ -3858,7 +3835,7 @@ module Synth {
|
||||
or
|
||||
result = convertBreakExprToRaw(e)
|
||||
or
|
||||
result = convertCallExprBaseToRaw(e)
|
||||
result = convertCallExprToRaw(e)
|
||||
or
|
||||
result = convertCastExprToRaw(e)
|
||||
or
|
||||
@@ -3886,6 +3863,8 @@ module Synth {
|
||||
or
|
||||
result = convertMatchExprToRaw(e)
|
||||
or
|
||||
result = convertMethodCallExprToRaw(e)
|
||||
or
|
||||
result = convertOffsetOfExprToRaw(e)
|
||||
or
|
||||
result = convertParenExprToRaw(e)
|
||||
|
||||
@@ -17,7 +17,7 @@ import codeql.rust.elements.Visibility
|
||||
*/
|
||||
module Generated {
|
||||
/**
|
||||
* A field in a tuple struct or tuple enum variant.
|
||||
* A field in a tuple struct or tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
|
||||
@@ -15,7 +15,7 @@ import codeql.rust.elements.TupleField
|
||||
*/
|
||||
module Generated {
|
||||
/**
|
||||
* A list of fields in a tuple struct or tuple enum variant.
|
||||
* A list of fields in a tuple struct or tuple variant.
|
||||
*
|
||||
* For example:
|
||||
* ```rust
|
||||
|
||||
@@ -6,6 +6,11 @@ extensions:
|
||||
- ["<actix_web::route::Route>::to", "Argument[0].Parameter[0..7]", "remote", "manual"]
|
||||
# Actix attributes such as `get` expand to this `to` call on the handler.
|
||||
- ["<actix_web::resource::Resource>::to", "Argument[0].Parameter[0..7]", "remote", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["<actix_web::types::html::Html>::new", "Argument[0]", "html-injection", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: summaryModel
|
||||
|
||||
@@ -7,13 +7,10 @@ extensions:
|
||||
- ["<futures_util::io::buf_reader::BufReader>::new", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncReadExt>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncReadExt>::read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncReadExt>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncReadExt>::read_to_end", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncBufReadExt>::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncBufReadExt>::read_line", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncBufReadExt>::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncBufReadExt>::read_until", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncBufReadExt>::fill_buf", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncBufReadExt>::fill_buf", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as futures_util::io::AsyncBufReadExt>::lines", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as futures_io::if_std::AsyncBufRead>::poll_fill_buf", "Argument[self].Reference", "ReturnValue.Field[core::task::poll::Poll::Ready(0)].Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as futures_io::if_std::AsyncRead>::poll_read", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"]
|
||||
|
||||
9
rust/ql/lib/codeql/rust/frameworks/native-tls.model.yml
Normal file
9
rust/ql/lib/codeql/rust/frameworks/native-tls.model.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["<native_tls::TlsConnectorBuilder>::danger_accept_invalid_certs", "Argument[0]", "disable-certificate", "manual"]
|
||||
- ["<native_tls::TlsConnectorBuilder>::danger_accept_invalid_hostnames", "Argument[0]", "disable-certificate", "manual"]
|
||||
- ["<async_native_tls::connect::TlsConnector>::danger_accept_invalid_certs", "Argument[0]", "disable-certificate", "manual"]
|
||||
- ["<async_native_tls::connect::TlsConnector>::danger_accept_invalid_hostnames", "Argument[0]", "disable-certificate", "manual"]
|
||||
@@ -11,6 +11,10 @@ extensions:
|
||||
data:
|
||||
- ["<reqwest::async_impl::client::Client>::request", "Argument[1]", "request-url", "manual"]
|
||||
- ["<reqwest::blocking::client::Client>::request", "Argument[1]", "request-url", "manual"]
|
||||
- ["<reqwest::async_impl::client::ClientBuilder>::danger_accept_invalid_certs", "Argument[0]", "disable-certificate", "manual"]
|
||||
- ["<reqwest::async_impl::client::ClientBuilder>::danger_accept_invalid_hostnames", "Argument[0]", "disable-certificate", "manual"]
|
||||
- ["<reqwest::blocking::client::ClientBuilder>::danger_accept_invalid_certs", "Argument[0]", "disable-certificate", "manual"]
|
||||
- ["<reqwest::blocking::client::ClientBuilder>::danger_accept_invalid_hostnames", "Argument[0]", "disable-certificate", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: summaryModel
|
||||
@@ -18,10 +22,10 @@ extensions:
|
||||
- ["<reqwest::response::Response>::text", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<reqwest::response::Response>::text_with_charset", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<reqwest::response::Response>::bytes", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<reqwest::response::Response>::chunk", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"]
|
||||
- ["<reqwest::response::Response>::chunk", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"]
|
||||
- ["<reqwest::blocking::response::Response>::text", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<reqwest::blocking::response::Response>::text_with_charset", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<reqwest::blocking::response::Response>::bytes", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<reqwest::async_impl::response::Response>::text", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<reqwest::async_impl::response::Response>::bytes", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<reqwest::async_impl::response::Response>::chunk", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"]
|
||||
- ["<reqwest::async_impl::response::Response>::chunk", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"]
|
||||
|
||||
@@ -24,13 +24,12 @@ class StreamCipherInit extends Cryptography::CryptographicOperation::Range {
|
||||
StreamCipherInit() {
|
||||
// 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() and
|
||||
ce.getStaticTarget().(Function).getName().getText() =
|
||||
["new", "new_from_slice", "new_with_eff_key_len", "new_from_slices"] and
|
||||
exists(Call call, string rawAlgorithmName |
|
||||
call = this.asExpr() and
|
||||
call.getTargetName() = ["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.
|
||||
exists(Type t, TypePath tp |
|
||||
t = inferType([ce, ce.(MethodCallExpr).getReceiver()], tp) and
|
||||
t = inferType([call, call.(MethodCall).getReceiver()], tp) and
|
||||
rawAlgorithmName = t.(StructType).getStruct().(Addressable).getCanonicalPath().splitAt("::")
|
||||
) and
|
||||
algorithmName = simplifyAlgorithmName(rawAlgorithmName) and
|
||||
|
||||
@@ -27,8 +27,19 @@ private class BuiltinsTypesFile extends File {
|
||||
class BuiltinType extends Struct {
|
||||
BuiltinType() { this.getFile() instanceof BuiltinsTypesFile }
|
||||
|
||||
/** Gets the name of this type. */
|
||||
/**
|
||||
* Gets the name of this type.
|
||||
*
|
||||
* This is the name used internally to represent the type, for example `Ref`.
|
||||
*/
|
||||
string getName() { result = super.getName().getText() }
|
||||
|
||||
/**
|
||||
* Gets a display name for this type.
|
||||
*
|
||||
* This is the name used in code, for example `&`.
|
||||
*/
|
||||
string getDisplayName() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,21 +151,48 @@ class F64 extends FloatingPointTypeImpl {
|
||||
/** The builtin slice type `[T]`. */
|
||||
class SliceType extends BuiltinType {
|
||||
SliceType() { this.getName() = "Slice" }
|
||||
|
||||
override string getDisplayName() { result = "[]" }
|
||||
}
|
||||
|
||||
/** The builtin array type `[T; N]`. */
|
||||
class ArrayType extends BuiltinType {
|
||||
ArrayType() { this.getName() = "Array" }
|
||||
|
||||
override string getDisplayName() { result = "[;]" }
|
||||
}
|
||||
|
||||
/** The builtin reference type `&T` or `&mut T`. */
|
||||
/** The builtin reference type `&T`. */
|
||||
class RefType extends BuiltinType {
|
||||
RefType() { this.getName() = "Ref" }
|
||||
|
||||
override string getDisplayName() { result = "&" }
|
||||
}
|
||||
|
||||
/** The builtin pointer type `*const T` or `*mut T`. */
|
||||
class PtrType extends BuiltinType {
|
||||
PtrType() { this.getName() = "Ptr" }
|
||||
/** The builtin reference type `&mut T`. */
|
||||
class RefMutType extends BuiltinType {
|
||||
RefMutType() { this.getName() = "RefMut" }
|
||||
|
||||
override string getDisplayName() { result = "&mut" }
|
||||
}
|
||||
|
||||
/** A builtin raw pointer type `*const T` or `*mut T`. */
|
||||
abstract private class PtrTypeImpl extends BuiltinType { }
|
||||
|
||||
final class PtrType = PtrTypeImpl;
|
||||
|
||||
/** The builtin raw pointer type `*const T`. */
|
||||
class PtrConstType extends PtrTypeImpl {
|
||||
PtrConstType() { this.getName() = "PtrConst" }
|
||||
|
||||
override string getDisplayName() { result = "*const" }
|
||||
}
|
||||
|
||||
/** The builtin raw pointer type `*mut T`. */
|
||||
class PtrMutType extends PtrTypeImpl {
|
||||
PtrMutType() { this.getName() = "PtrMut" }
|
||||
|
||||
override string getDisplayName() { result = "*mut" }
|
||||
}
|
||||
|
||||
/** A builtin tuple type `(T1, T2, ...)`. */
|
||||
@@ -168,4 +206,13 @@ class TupleType extends BuiltinType {
|
||||
or
|
||||
result = this.getGenericParamList().getNumberOfGenericParams()
|
||||
}
|
||||
|
||||
override string getDisplayName() {
|
||||
// Note: This produces "(,,)" for a 2-tuple, "(,,,)" for a 3-tuple, etc.
|
||||
// This is in order to distinguish the unit type `()` from the 1-tuple `(,)`.
|
||||
exists(string commas |
|
||||
commas = concat(int i | i = [0 .. this.getArity() - 1] | ",") and
|
||||
result = "(" + commas + ")"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ private import codeql.rust.internal.PathResolution
|
||||
/**
|
||||
* A call to the `starts_with` method on a `Path`.
|
||||
*/
|
||||
private class StartswithCall extends Path::SafeAccessCheck::Range, MethodCallExpr {
|
||||
private class StartswithCall extends Path::SafeAccessCheck::Range, MethodCall {
|
||||
StartswithCall() { this.getStaticTarget().getCanonicalPath() = "<std::path::Path>::starts_with" }
|
||||
|
||||
override predicate checks(Expr e, boolean branch) {
|
||||
|
||||
@@ -24,30 +24,31 @@ extensions:
|
||||
extensible: summaryModel
|
||||
data:
|
||||
# Box
|
||||
- ["<alloc::boxed::Box>::pin", "Argument[0]", "ReturnValue.Reference", "value", "manual"]
|
||||
- ["<alloc::boxed::Box>::new", "Argument[0]", "ReturnValue.Reference", "value", "manual"]
|
||||
- ["<alloc::boxed::Box>::into_pin", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["<alloc::boxed::Box as core::ops::deref::Deref>::deref", "Argument[self].Reference.Field[alloc::boxed::Box(0)]", "ReturnValue.Reference", "value", "manual"]
|
||||
- ["<alloc::boxed::Box>::pin", "Argument[0]", "ReturnValue.Field[core::pin::Pin::pointer].Field[alloc::boxed::Box(0)]", "value", "manual"]
|
||||
- ["<alloc::boxed::Box>::new", "Argument[0]", "ReturnValue.Field[alloc::boxed::Box(0)]", "value", "manual"]
|
||||
- ["<alloc::boxed::Box>::into_pin", "Argument[0]", "ReturnValue.Field[core::pin::Pin::pointer]", "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[self].Reference", "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[self].Reference", "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[self].Reference", "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[self].Reference", "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"]
|
||||
- ["<core::alloc::layout::Layout>::align_to", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::align_to", "Argument[self].Reference.Element", "ReturnValue.Field[0,1,2].Reference.Element", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::pad_to_align", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<core::alloc::layout::Layout>::size", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
# String
|
||||
- ["<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"]
|
||||
- ["<_ as alloc::string::ToString>::to_string", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
# Vec
|
||||
- ["alloc::vec::from_elem", "Argument[0]", "ReturnValue.Element", "value", "manual"]
|
||||
|
||||
@@ -3,10 +3,76 @@ extensions:
|
||||
pack: codeql/rust-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
# Arithmetic
|
||||
# Builtin deref
|
||||
- ["<& as core::ops::deref::Deref>::deref", "Argument[self].Reference", "ReturnValue", "value", "manual"]
|
||||
- ["<&mut as core::ops::deref::Deref>::deref", "Argument[self].Reference", "ReturnValue", "value", "manual"]
|
||||
# Index
|
||||
- ["<_ as core::ops::index::Index>::index", "Argument[self].Reference.Element", "ReturnValue.Reference", "value", "manual"]
|
||||
- ["<_ as core::ops::index::IndexMut>::index_mut", "Argument[self].Reference.Element", "ReturnValue.Reference", "value", "manual"]
|
||||
# Unary operators
|
||||
- ["<_ as core::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
# Arithmetic operators
|
||||
- ["<_ 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"]
|
||||
- ["<_ as core::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Sub>::sub", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Mul>::mul", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Div>::div", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::Rem>::rem", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
# Arithmetic assignment expressions
|
||||
- ["<_ as core::ops::arith::AddAssign>::add_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::AddAssign>::add_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::AddAssign>::add_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::SubAssign>::sub_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::SubAssign>::sub_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::SubAssign>::sub_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::MulAssign>::mul_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::MulAssign>::mul_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::MulAssign>::mul_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::DivAssign>::div_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::DivAssign>::div_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::DivAssign>::div_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::RemAssign>::rem_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::RemAssign>::rem_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::arith::RemAssign>::rem_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
# Bitwise operators
|
||||
- ["<_ as core::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitAnd>::bitand", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitOr>::bitor", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitXor>::bitxor", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
# Bitwise assignment operators
|
||||
- ["<_ as core::ops::bit::BitAndAssign>::bitand_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitAndAssign>::bitand_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitOrAssign>::bitor_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitOrAssign>::bitor_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitXorAssign>::bitxor_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::BitXorAssign>::bitxor_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
# Shift operators
|
||||
- ["<_ as core::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::Shl>::shl", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::Shr>::shr", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
|
||||
# Shift assignment operators
|
||||
- ["<_ as core::ops::bit::ShlAssign>::shl_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::ShlAssign>::shl_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::ShrAssign>::shr_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
|
||||
- ["<_ as core::ops::bit::ShrAssign>::shr_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
|
||||
# Clone
|
||||
- ["<_ as core::clone::Clone>::clone", "Argument[self].Reference", "ReturnValue", "value", "manual"]
|
||||
# Conversions
|
||||
@@ -20,9 +86,8 @@ extensions:
|
||||
- ["<core::result::Result>::iter_mut", "Argument[self].Element", "ReturnValue.Element", "value", "manual"]
|
||||
- ["<core::result::Result>::into_iter", "Argument[self].Element", "ReturnValue.Element", "value", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::nth", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::next", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::next", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)].Field[core::result::Result::Ok(0)]", "value", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::nth", "Argument[self].Reference.Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"]
|
||||
- ["<_ as core::iter::traits::iterator::Iterator>::next", "Argument[self].Reference.Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"]
|
||||
- ["<_ 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"]
|
||||
@@ -30,12 +95,11 @@ extensions:
|
||||
- ["<_ 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"]
|
||||
- ["<core::pin::Pin>::new_unchecked", "Argument[0].Reference", "ReturnValue", "value", "manual"]
|
||||
- ["<core::pin::Pin>::into_inner", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["<core::pin::Pin>::into_inner_unchecked", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["<core::pin::Pin>::set", "Argument[0]", "Argument[self]", "value", "manual"]
|
||||
- ["<core::pin::Pin>::new", "Argument[0]", "ReturnValue.Field[core::pin::Pin::pointer]", "value", "manual"]
|
||||
- ["<core::pin::Pin>::new_unchecked", "Argument[0]", "ReturnValue.Field[core::pin::Pin::pointer]", "value", "manual"]
|
||||
- ["<core::pin::Pin>::into_inner", "Argument[0].Field[core::pin::Pin::pointer]", "ReturnValue", "value", "manual"]
|
||||
- ["<core::pin::Pin>::into_inner_unchecked", "Argument[0].Field[core::pin::Pin::pointer]", "ReturnValue", "value", "manual"]
|
||||
- ["<core::pin::Pin>::set", "Argument[0]", "Argument[self].Reference.Field[core::pin::Pin::pointer]", "value", "manual"]
|
||||
# Ptr
|
||||
- ["core::ptr::read", "Argument[0].Reference", "ReturnValue", "value", "manual"]
|
||||
- ["core::ptr::read_unaligned", "Argument[0].Reference", "ReturnValue", "value", "manual"]
|
||||
@@ -43,6 +107,9 @@ extensions:
|
||||
- ["core::ptr::write", "Argument[1]", "Argument[0].Reference", "value", "manual"]
|
||||
- ["core::ptr::write_unaligned", "Argument[1]", "Argument[0].Reference", "value", "manual"]
|
||||
- ["core::ptr::write_volatile", "Argument[1]", "Argument[0].Reference", "value", "manual"]
|
||||
# https://doc.rust-lang.org/std/pin/struct.Pin.html#impl-Deref-for-Pin%3CPtr%3E, but limited to `Ptr = &` and `Ptr = Box`
|
||||
- ["<core::pin::Pin as core::ops::deref::Deref>::deref", "Argument[self].Reference.Field[core::pin::Pin::pointer].Reference", "ReturnValue.Reference", "value", "manual"]
|
||||
- ["<core::pin::Pin as core::ops::deref::Deref>::deref", "Argument[self].Reference.Field[core::pin::Pin::pointer].Field[alloc::boxed::Box(0)]", "ReturnValue.Reference", "value", "manual"]
|
||||
# Str
|
||||
- ["<core::str>::as_str", "Argument[self]", "ReturnValue", "value", "manual"]
|
||||
- ["<core::str>::as_bytes", "Argument[self]", "ReturnValue", "value", "manual"]
|
||||
@@ -60,6 +127,7 @@ extensions:
|
||||
- ["core::ptr::dangling", "ReturnValue", "pointer-invalidate", "manual"]
|
||||
- ["core::ptr::dangling_mut", "ReturnValue", "pointer-invalidate", "manual"]
|
||||
- ["core::ptr::null", "ReturnValue", "pointer-invalidate", "manual"]
|
||||
- ["core::ptr::null_mut", "ReturnValue", "pointer-invalidate", "manual"]
|
||||
- ["v8::primitives::null", "ReturnValue", "pointer-invalidate", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
|
||||
@@ -3,14 +3,27 @@ extensions:
|
||||
pack: codeql/rust-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- ["std::fs::exists", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["std::fs::read", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["std::fs::read_dir", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["std::fs::read_to_string", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["std::fs::read_link", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["std::fs::metadata", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["std::fs::symlink_metadata", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["<std::fs::DirEntry>::path", "ReturnValue", "file", "manual"]
|
||||
- ["<std::fs::DirEntry>::file_name", "ReturnValue", "file", "manual"]
|
||||
- ["<std::fs::File>::open", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["<std::fs::File>::open_buffered", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["<std::fs::OpenOptions>::open", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["<std::path::Path>::exists", "ReturnValue", "file", "manual"]
|
||||
- ["<std::path::Path>::try_exists", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["<std::path::Path>::is_file", "ReturnValue", "file", "manual"]
|
||||
- ["<std::path::Path>::is_dir", "ReturnValue", "file", "manual"]
|
||||
- ["<std::path::Path>::is_symlink", "ReturnValue", "file", "manual"]
|
||||
- ["<std::path::Path>::metadata", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["<std::path::Path>::symlink_metadata", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["<std::path::Path>::read_dir", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- ["<std::path::Path>::read_link", "ReturnValue.Field[core::result::Result::Ok(0)]", "file", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sinkModel
|
||||
@@ -68,3 +81,12 @@ extensions:
|
||||
- ["<std::path::Path>::with_extension", "Argument[Self].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::path::Path>::with_file_name", "Argument[Self].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::path::Path>::with_file_name", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::fs::Metadata>::accessed", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<std::fs::Metadata>::created", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<std::fs::Metadata>::file_type", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::fs::Metadata>::is_file", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::fs::Metadata>::is_dir", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::fs::Metadata>::is_symlink", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::fs::Metadata>::len", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::fs::Metadata>::modified", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<std::fs::Metadata>::permissions", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
|
||||
@@ -9,18 +9,19 @@ extensions:
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["<std::io::buffered::bufreader::BufReader>::new", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as std::io::BufRead>::fill_buf", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<std::io::buffered::bufreader::BufReader>::buffer", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::BufRead>::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::BufRead>::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::BufRead>::fill_buf", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<std::io::buffered::bufreader::BufReader>::buffer", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::read_to_string", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::read_to_end", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::read_exact", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::BufRead>::read_line", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::BufRead>::read_until", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"]
|
||||
- ["<_ as std::io::BufRead>::split", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as std::io::BufRead>::lines", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::bytes", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::chain", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::chain", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as std::io::Read>::take", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::io::stdio::Stdin>::lock", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::io::stdio::Stdin>::lock", "Argument[self].Reference", "ReturnValue", "taint", "manual"]
|
||||
- ["<std::io::Split as core::iter::traits::iterator::Iterator>::next", "Argument[self].Reference.Element", "ReturnValue.Field[core::option::Option::Some(0)].Field[core::result::Result::Ok(0)]", "value", "manual"]
|
||||
|
||||
@@ -9,40 +9,40 @@ extensions:
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["<tokio::io::util::buf_reader::BufReader>::new", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::fill_buf", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<tokio::io::util::buf_reader::BufReader>::buffer", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::fill_buf", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<tokio::io::util::buf_reader::BufReader>::buffer", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_to_string", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_to_end", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_exact", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::read_line", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::read_until", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::split", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<tokio::io::util::split::Split>::next_segment", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"]
|
||||
- ["<tokio::io::util::split::Split>::next_segment", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::lines", "Argument[self]", "ReturnValue", "taint", "manual"]
|
||||
- ["<tokio::io::util::lines::Lines>::next_line", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_buf", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u8", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u8_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u16", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u16_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u32", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u32_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u64", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u64_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u128", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u128_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i8", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i8_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i16", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i16_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i32", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i32_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i64", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i64_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i128", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i128_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_f32", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ 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"]
|
||||
- ["<tokio::io::util::lines::Lines>::next_line", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_buf", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u8", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u8_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u16", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u16_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u32", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u32_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u64", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u64_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u128", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u128_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i8", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i8_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i16", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i16_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i32", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i32_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i64", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i64_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i128", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i128_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_f32", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>:::read_f32_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_f64", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_f64_le", "Argument[self].Reference", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]
|
||||
|
||||
@@ -8,7 +8,6 @@ extensions:
|
||||
pack: codeql/rust-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["<tokio::net::tcp::stream::TcpStream>::peek", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<tokio::net::tcp::stream::TcpStream>::try_read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<tokio::net::tcp::stream::TcpStream>::try_read_buf", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<tokio::net::tcp::stream::TcpStream>::peek", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<tokio::net::tcp::stream::TcpStream>::try_read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
- ["<tokio::net::tcp::stream::TcpStream>::try_read_buf", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"]
|
||||
|
||||
@@ -5,4 +5,9 @@ extensions:
|
||||
data:
|
||||
- ["<_ as warp::filter::Filter>::then", "Argument[0].Parameter[0..7]", "remote", "manual"]
|
||||
- ["<_ as warp::filter::Filter>::map", "Argument[0].Parameter[0..7]", "remote", "manual"]
|
||||
- ["<_ as warp::filter::Filter>::and_then", "Argument[0].Parameter[0..7]", "remote", "manual"]
|
||||
- ["<_ as warp::filter::Filter>::and_then", "Argument[0].Parameter[0..7]", "remote", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["warp::reply::html", "Argument[0]", "html-injection", "manual"]
|
||||
@@ -115,13 +115,11 @@ module Stages {
|
||||
predicate backref() {
|
||||
1 = 1
|
||||
or
|
||||
exists(resolvePath(_))
|
||||
exists(resolvePathIgnoreVariableShadowing(_))
|
||||
or
|
||||
exists(any(ItemNode i).getASuccessor(_, _, _))
|
||||
or
|
||||
exists(any(ImplOrTraitItemNode i).getASelfPath())
|
||||
or
|
||||
any(TypeParamItemNode i).hasTraitBound()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ private module Cached {
|
||||
TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() } or
|
||||
TItemNode(ItemNode i)
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isMacroCallLocation(Location loc) { loc = any(MacroCall m).getLocation() }
|
||||
|
||||
/**
|
||||
* Gets an element, of kind `kind`, that element `use` uses, if any.
|
||||
*/
|
||||
@@ -44,7 +47,7 @@ private module Cached {
|
||||
Definition definitionOf(Use use, string kind) {
|
||||
result = use.getDefinition() and
|
||||
kind = use.getUseType() and
|
||||
not result.getLocation() = any(MacroCall m).getLocation()
|
||||
not isMacroCallLocation(result.getLocation())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +147,7 @@ private class PathUse extends Use instanceof NameRef {
|
||||
|
||||
override Definition getDefinition() {
|
||||
// Our call resolution logic may disambiguate some calls, so only use those
|
||||
result.asItemNode() = this.getCall().getStaticTarget()
|
||||
result.asItemNode() = this.getCall().getResolvedTarget()
|
||||
or
|
||||
not exists(this.getCall()) and
|
||||
result.asItemNode() = resolvePath(path)
|
||||
|
||||
@@ -1,9 +1,49 @@
|
||||
/**
|
||||
* Provides functionality for resolving paths, using the predicate `resolvePath`.
|
||||
*
|
||||
* Path resolution needs to happen before variable resolution, because otherwise
|
||||
* we cannot know whether an identifier pattern binds a new variable or whether it
|
||||
* refers to a constructor or constant:
|
||||
*
|
||||
* ```rust
|
||||
* let x = ...; // `x` is only a variable if it does not resolve to a constructor/constant
|
||||
* ```
|
||||
*
|
||||
* Even though variable names typically start with a lowercase letter and constructors
|
||||
* with an uppercase letter, this is not enforced by the Rust language.
|
||||
*
|
||||
* Variables may shadow declarations, so variable resolution also needs to affect
|
||||
* path resolution:
|
||||
*
|
||||
* ```rust
|
||||
* fn foo() {} // (1)
|
||||
*
|
||||
* fn bar() {
|
||||
* let f = foo; // `foo` here refers to (1) via path resolution
|
||||
* let foo = f(); // (2)
|
||||
* foo // `foo` here refers to (2) via variable resolution
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* So it may seem that path resolution and variable resolution must happen in mutual
|
||||
* recursion, but we would like to keep the inherently global path resolution logic
|
||||
* separate from the inherently local variable resolution logic. We achieve this by
|
||||
*
|
||||
* - First computing global path resolution, where variable shadowing is ignored,
|
||||
* exposed as the internal predicate `resolvePathIgnoreVariableShadowing`.
|
||||
* - `resolvePathIgnoreVariableShadowing` is sufficient to determine whether an
|
||||
* identifier pattern resolves to a constructor/constant, since if it does, it cannot
|
||||
* be shadowed by a variable. We expose this as the predicate `identPatIsResolvable`.
|
||||
* - Variable resolution can then be computed as a local property, using only the
|
||||
* global information from `identPatIsResolvable`.
|
||||
* - Finally, path resolution can be computed by restricting
|
||||
* `resolvePathIgnoreVariableShadowing` to paths that are not resolvable via
|
||||
* variable resolution.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.generated.ParentChild
|
||||
private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl
|
||||
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
|
||||
private import codeql.rust.internal.CachedStages
|
||||
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
|
||||
@@ -184,7 +224,7 @@ abstract class ItemNode extends Locatable {
|
||||
pragma[nomagic]
|
||||
final Attr getAttr(string name) {
|
||||
result = this.getAnAttr() and
|
||||
result.getMeta().getPath().(RelevantPath).isUnqualified(name)
|
||||
result.getMeta().getPath().(PathExt).isUnqualified(name)
|
||||
}
|
||||
|
||||
final predicate hasAttr(string name) { exists(this.getAttr(name)) }
|
||||
@@ -224,6 +264,9 @@ abstract class ItemNode extends Locatable {
|
||||
pragma[nomagic]
|
||||
ItemNode getImmediateParent() { this = result.getADescendant() }
|
||||
|
||||
/** Gets a child item of this item, if any. */
|
||||
ItemNode getAChild() { this = result.getImmediateParent() }
|
||||
|
||||
/** Gets the immediately enclosing module (or source file) of this item. */
|
||||
pragma[nomagic]
|
||||
ModuleLikeNode getImmediateParentModule() {
|
||||
@@ -299,10 +342,13 @@ abstract class ItemNode extends Locatable {
|
||||
typeImplEdge(this, _, name, kind, result, useOpt)
|
||||
or
|
||||
// trait items with default implementations made available in an implementation
|
||||
exists(ImplItemNodeImpl impl, ItemNode trait |
|
||||
exists(ImplItemNodeImpl impl, TraitItemNode trait |
|
||||
this = impl and
|
||||
trait = impl.resolveTraitTyCand() and
|
||||
result = trait.getASuccessor(name, kind, useOpt) and
|
||||
// do not inherit default implementations from super traits; those are inherited by
|
||||
// their `impl` blocks
|
||||
result = trait.getAssocItem(name) and
|
||||
result.(AssocItemNode).hasImplementation() and
|
||||
kind.isExternalOrBoth() and
|
||||
not impl.hasAssocItem(name)
|
||||
@@ -362,8 +408,14 @@ abstract class ItemNode extends Locatable {
|
||||
this instanceof SourceFile and
|
||||
builtin(name, result)
|
||||
or
|
||||
name = "Self" and
|
||||
this = result.(ImplOrTraitItemNode).getAnItemInSelfScope()
|
||||
exists(ImplOrTraitItemNode i |
|
||||
name = "Self" and
|
||||
this = i.getAnItemInSelfScope()
|
||||
|
|
||||
result = i.(Trait)
|
||||
or
|
||||
result = i.(ImplItemNodeImpl).resolveSelfTyCand()
|
||||
)
|
||||
or
|
||||
name = "crate" and
|
||||
this = result.(CrateItemNode).getASourceFile()
|
||||
@@ -619,7 +671,7 @@ private class VariantItemNode extends ParameterizableItemNode instanceof Variant
|
||||
override string getName() { result = Variant.super.getName().getText() }
|
||||
|
||||
override Namespace getNamespace() {
|
||||
if super.getFieldList() instanceof StructFieldList then result.isType() else result.isValue()
|
||||
if super.isStruct() then result.isType() else result.isValue()
|
||||
}
|
||||
|
||||
override TypeParam getTypeParam(int i) {
|
||||
@@ -694,7 +746,7 @@ abstract class ImplOrTraitItemNode extends ItemNode {
|
||||
Path getASelfPath() {
|
||||
Stages::PathResolutionStage::ref() and
|
||||
isUnqualifiedSelfPath(result) and
|
||||
this = unqualifiedPathLookup(result, _, _)
|
||||
result = this.getAnItemInSelfScope().getADescendant()
|
||||
}
|
||||
|
||||
/** Gets an associated item belonging to this trait or `impl` block. */
|
||||
@@ -722,8 +774,11 @@ private TypeItemNode resolveBuiltin(TypeRepr tr) {
|
||||
tr instanceof RefTypeRepr and
|
||||
result instanceof Builtins::RefType
|
||||
or
|
||||
tr instanceof PtrTypeRepr and
|
||||
result instanceof Builtins::PtrType
|
||||
tr.(PtrTypeRepr).isConst() and
|
||||
result instanceof Builtins::PtrConstType
|
||||
or
|
||||
tr.(PtrTypeRepr).isMut() and
|
||||
result instanceof Builtins::PtrMutType
|
||||
or
|
||||
result.(Builtins::TupleType).getArity() = tr.(TupleTypeRepr).getNumberOfFields()
|
||||
}
|
||||
@@ -920,7 +975,7 @@ private class ImplItemNodeImpl extends ImplItemNode {
|
||||
result = this.resolveSelfTyBuiltin()
|
||||
}
|
||||
|
||||
TraitItemNode resolveTraitTyCand() { result = resolvePathCand(this.getTraitPath()) }
|
||||
TraitItemNodeImpl resolveTraitTyCand() { result = resolvePathCand(this.getTraitPath()) }
|
||||
}
|
||||
|
||||
private class StructItemNode extends TypeItemNode, ParameterizableItemNode instanceof Struct {
|
||||
@@ -929,7 +984,7 @@ private class StructItemNode extends TypeItemNode, ParameterizableItemNode insta
|
||||
override Namespace getNamespace() {
|
||||
result.isType() // the struct itself
|
||||
or
|
||||
not super.getFieldList() instanceof StructFieldList and
|
||||
not super.isStruct() and
|
||||
result.isValue() // the constructor
|
||||
}
|
||||
|
||||
@@ -958,7 +1013,16 @@ private class StructItemNode extends TypeItemNode, ParameterizableItemNode insta
|
||||
language[monotonicAggregates]
|
||||
override string getCanonicalPath(Crate c) {
|
||||
this.hasCanonicalPath(c) and
|
||||
result = strictconcat(int i | i in [0 .. 2] | this.getCanonicalPathPart(c, i) order by i)
|
||||
(
|
||||
this =
|
||||
any(Builtins::BuiltinType t |
|
||||
not t.hasVisibility() and
|
||||
result = t.getDisplayName()
|
||||
)
|
||||
or
|
||||
not this = any(Builtins::BuiltinType t | not t.hasVisibility()) and
|
||||
result = strictconcat(int i | i in [0 .. 2] | this.getCanonicalPathPart(c, i) order by i)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1159,34 +1223,6 @@ final class TypeParamItemNode extends TypeItemNode instanceof TypeParam {
|
||||
|
||||
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
|
||||
|
||||
/**
|
||||
* Holds if this type parameter has a trait bound. Examples:
|
||||
*
|
||||
* ```rust
|
||||
* impl<T> Foo<T> { ... } // has no trait bound
|
||||
*
|
||||
* impl<T: Trait> Foo<T> { ... } // has trait bound
|
||||
*
|
||||
* impl<T> Foo<T> where T: Trait { ... } // has trait bound
|
||||
* ```
|
||||
*/
|
||||
cached
|
||||
predicate hasTraitBound() { Stages::PathResolutionStage::ref() and exists(this.getABoundPath()) }
|
||||
|
||||
/**
|
||||
* Holds if this type parameter has no trait bound. Examples:
|
||||
*
|
||||
* ```rust
|
||||
* impl<T> Foo<T> { ... } // has no trait bound
|
||||
*
|
||||
* impl<T: Trait> Foo<T> { ... } // has trait bound
|
||||
*
|
||||
* impl<T> Foo<T> where T: Trait { ... } // has trait bound
|
||||
* ```
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate hasNoTraitBound() { not this.hasTraitBound() }
|
||||
|
||||
override string getName() { result = TypeParam.super.getName().getText() }
|
||||
|
||||
override Namespace getNamespace() { result.isType() }
|
||||
@@ -1525,20 +1561,22 @@ private predicate declares(ItemNode item, Namespace ns, string name) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A path that does not access a local variable. */
|
||||
class RelevantPath extends Path {
|
||||
RelevantPath() { not this = any(VariableAccess va).(PathExpr).getPath() }
|
||||
/**
|
||||
* A `Path` or an `IdentPat`.
|
||||
*
|
||||
* `IdentPat`s are included in order to resolve unqualified references to
|
||||
* constructors in patterns.
|
||||
*/
|
||||
abstract class PathExt extends AstNode {
|
||||
abstract string getText();
|
||||
|
||||
/** Holds if this is an unqualified path with the textual value `name`. */
|
||||
pragma[nomagic]
|
||||
predicate isUnqualified(string name) {
|
||||
not exists(this.getQualifier()) and
|
||||
not exists(UseTree tree |
|
||||
tree.hasPath() and
|
||||
this = getAUseTreeUseTree(tree).getPath().getQualifier*()
|
||||
) and
|
||||
name = this.getText()
|
||||
}
|
||||
abstract predicate isUnqualified(string name);
|
||||
|
||||
abstract Path getQualifier();
|
||||
|
||||
abstract string toStringDebug();
|
||||
|
||||
/**
|
||||
* Holds if this is an unqualified path with the textual value `name` and
|
||||
@@ -1560,6 +1598,33 @@ class RelevantPath extends Path {
|
||||
predicate isDollarCrate() { this.isUnqualified("$crate", _) }
|
||||
}
|
||||
|
||||
private class PathExtPath extends PathExt instanceof Path {
|
||||
override string getText() { result = Path.super.getText() }
|
||||
|
||||
override predicate isUnqualified(string name) {
|
||||
not exists(Path.super.getQualifier()) and
|
||||
not exists(UseTree tree |
|
||||
tree.hasPath() and
|
||||
this = getAUseTreeUseTree(tree).getPath().getQualifier*()
|
||||
) and
|
||||
name = Path.super.getText()
|
||||
}
|
||||
|
||||
override Path getQualifier() { result = Path.super.getQualifier() }
|
||||
|
||||
override string toStringDebug() { result = Path.super.toStringDebug() }
|
||||
}
|
||||
|
||||
private class PathExtIdentPat extends PathExt, IdentPat {
|
||||
override string getText() { result = this.getName().getText() }
|
||||
|
||||
override predicate isUnqualified(string name) { name = this.getText() }
|
||||
|
||||
override Path getQualifier() { none() }
|
||||
|
||||
override string toStringDebug() { result = this.getText() }
|
||||
}
|
||||
|
||||
private predicate isModule(ItemNode m) { m instanceof Module }
|
||||
|
||||
/** Holds if source file `source` contains the module `m`. */
|
||||
@@ -1583,7 +1648,7 @@ private ItemNode getOuterScope(ItemNode i) {
|
||||
pragma[nomagic]
|
||||
private predicate unqualifiedPathLookup(ItemNode ancestor, string name, Namespace ns, ItemNode encl) {
|
||||
// lookup in the immediately enclosing item
|
||||
exists(RelevantPath path |
|
||||
exists(PathExt path |
|
||||
path.isUnqualified(name, encl) and
|
||||
ancestor = encl and
|
||||
not name = ["crate", "$crate", "super", "self"]
|
||||
@@ -1619,7 +1684,7 @@ private ItemNode getASuccessor(
|
||||
|
||||
private predicate isSourceFile(ItemNode source) { source instanceof SourceFileItemNode }
|
||||
|
||||
private predicate hasCratePath(ItemNode i) { any(RelevantPath path).isCratePath(_, i) }
|
||||
private predicate hasCratePath(ItemNode i) { any(PathExt path).isCratePath(_, i) }
|
||||
|
||||
private predicate hasChild(ItemNode parent, ItemNode child) { child.getImmediateParent() = parent }
|
||||
|
||||
@@ -1631,7 +1696,7 @@ private predicate sourceFileHasCratePathTc(ItemNode i1, ItemNode i2) =
|
||||
* `name` may be looked up inside `ancestor`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate keywordLookup(ItemNode ancestor, string name, RelevantPath p) {
|
||||
private predicate keywordLookup(ItemNode ancestor, string name, PathExt p) {
|
||||
// For `crate`, jump directly to the root module
|
||||
exists(ItemNode i | p.isCratePath(name, i) |
|
||||
ancestor instanceof SourceFile and
|
||||
@@ -1645,7 +1710,7 @@ private predicate keywordLookup(ItemNode ancestor, string name, RelevantPath p)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKind kind) {
|
||||
private ItemNode unqualifiedPathLookup(PathExt p, Namespace ns, SuccessorKind kind) {
|
||||
exists(ItemNode ancestor, string name |
|
||||
result = getASuccessor(ancestor, pragma[only_bind_into](name), ns, kind, _) and
|
||||
kind.isInternalOrBoth()
|
||||
@@ -1660,7 +1725,7 @@ private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKi
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isUnqualifiedSelfPath(RelevantPath path) { path.isUnqualified("Self") }
|
||||
private predicate isUnqualifiedSelfPath(PathExt path) { path.isUnqualified("Self") }
|
||||
|
||||
/** Provides the input to `TraitIsVisible`. */
|
||||
signature predicate relevantTraitVisibleSig(Element element, Trait trait);
|
||||
@@ -1743,14 +1808,14 @@ private module DollarCrateResolution {
|
||||
isDollarCrateSupportedMacroExpansion(_, expansion)
|
||||
}
|
||||
|
||||
private predicate isDollarCratePath(RelevantPath p) { p.isDollarCrate() }
|
||||
private predicate isDollarCratePath(PathExt p) { p.isDollarCrate() }
|
||||
|
||||
private predicate isInDollarCrateMacroExpansion(RelevantPath p, AstNode expansion) =
|
||||
private predicate isInDollarCrateMacroExpansion(PathExt p, AstNode expansion) =
|
||||
doublyBoundedFastTC(hasParent/2, isDollarCratePath/1, isDollarCrateSupportedMacroExpansion/1)(p,
|
||||
expansion)
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isInDollarCrateMacroExpansionFromFile(File macroDefFile, RelevantPath p) {
|
||||
private predicate isInDollarCrateMacroExpansionFromFile(File macroDefFile, PathExt p) {
|
||||
exists(Path macroDefPath, AstNode expansion |
|
||||
isDollarCrateSupportedMacroExpansion(macroDefPath, expansion) and
|
||||
isInDollarCrateMacroExpansion(p, expansion) and
|
||||
@@ -1765,22 +1830,14 @@ private module DollarCrateResolution {
|
||||
* calls.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate resolveDollarCrate(RelevantPath p, CrateItemNode crate) {
|
||||
predicate resolveDollarCrate(PathExt p, CrateItemNode crate) {
|
||||
isInDollarCrateMacroExpansionFromFile(crate.getASourceFile().getFile(), p)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) {
|
||||
exists(ItemNode res |
|
||||
res = unqualifiedPathLookup(path, ns, _) and
|
||||
if
|
||||
not any(RelevantPath parent).getQualifier() = path and
|
||||
isUnqualifiedSelfPath(path) and
|
||||
res instanceof ImplItemNode
|
||||
then result = res.(ImplItemNodeImpl).resolveSelfTyCand()
|
||||
else result = res
|
||||
)
|
||||
private ItemNode resolvePathCand0(PathExt path, Namespace ns) {
|
||||
result = unqualifiedPathLookup(path, ns, _)
|
||||
or
|
||||
DollarCrateResolution::resolveDollarCrate(path, result) and
|
||||
ns = result.getNamespace()
|
||||
@@ -1790,13 +1847,16 @@ private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) {
|
||||
result = resolveUseTreeListItem(_, _, path, _) and
|
||||
ns = result.getNamespace()
|
||||
or
|
||||
result = resolveBuiltin(path.getSegment().getTypeRepr()) and
|
||||
not path.getSegment().hasTraitTypeRepr() and
|
||||
ns.isType()
|
||||
exists(PathSegment seg |
|
||||
seg = path.(Path).getSegment() and
|
||||
result = resolveBuiltin(seg.getTypeRepr()) and
|
||||
not seg.hasTraitTypeRepr() and
|
||||
ns.isType()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ItemNode resolvePathCandQualifier(RelevantPath qualifier, RelevantPath path, string name) {
|
||||
private ItemNode resolvePathCandQualifier(PathExt qualifier, PathExt path, string name) {
|
||||
qualifier = path.getQualifier() and
|
||||
result = resolvePathCand(qualifier) and
|
||||
name = path.getText()
|
||||
@@ -1839,14 +1899,35 @@ private predicate checkQualifiedVisibility(
|
||||
not i instanceof TypeParam
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isImplSelfQualifiedPath(
|
||||
ImplItemNode impl, PathExt qualifier, PathExt path, string name
|
||||
) {
|
||||
qualifier = impl.getASelfPath() and
|
||||
qualifier = path.getQualifier() and
|
||||
name = path.getText()
|
||||
}
|
||||
|
||||
private ItemNode resolveImplSelfQualified(PathExt qualifier, PathExt path, Namespace ns) {
|
||||
exists(ImplItemNode impl, string name |
|
||||
isImplSelfQualifiedPath(impl, qualifier, path, name) and
|
||||
result = impl.getAssocItem(name) and
|
||||
ns = result.getNamespace()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item that `path` resolves to in `ns` when `qualifier` is the
|
||||
* qualifier of `path` and `qualifier` resolves to `q`, if any.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private ItemNode resolvePathCandQualified(
|
||||
RelevantPath qualifier, ItemNode q, RelevantPath path, Namespace ns
|
||||
) {
|
||||
private ItemNode resolvePathCandQualified(PathExt qualifier, ItemNode q, PathExt path, Namespace ns) {
|
||||
// Special case for `Self::Assoc`; this always refers to the associated
|
||||
// item in the enclosing `impl` block, if available.
|
||||
q = resolvePathCandQualifier(qualifier, path, _) and
|
||||
result = resolveImplSelfQualified(qualifier, path, ns)
|
||||
or
|
||||
not exists(resolveImplSelfQualified(qualifier, path, ns)) and
|
||||
exists(string name, SuccessorKind kind, UseOption useOpt |
|
||||
q = resolvePathCandQualifier(qualifier, path, name) and
|
||||
result = getASuccessor(q, name, ns, kind, useOpt) and
|
||||
@@ -1855,12 +1936,14 @@ private ItemNode resolvePathCandQualified(
|
||||
}
|
||||
|
||||
/** Holds if path `p` must be looked up in namespace `n`. */
|
||||
private predicate pathUsesNamespace(Path p, Namespace n) {
|
||||
private predicate pathUsesNamespace(PathExt p, Namespace n) {
|
||||
n.isValue() and
|
||||
(
|
||||
p = any(PathExpr pe).getPath()
|
||||
or
|
||||
p = any(TupleStructPat tsp).getPath()
|
||||
or
|
||||
p instanceof PathExtIdentPat
|
||||
)
|
||||
or
|
||||
n.isType() and
|
||||
@@ -1936,7 +2019,7 @@ private predicate macroUseEdge(
|
||||
* result in non-monotonic recursion.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private ItemNode resolvePathCand(RelevantPath path) {
|
||||
private ItemNode resolvePathCand(PathExt path) {
|
||||
exists(Namespace ns |
|
||||
result = resolvePathCand0(path, ns) and
|
||||
if path = any(ImplItemNode i).getSelfPath()
|
||||
@@ -1949,7 +2032,13 @@ private ItemNode resolvePathCand(RelevantPath path) {
|
||||
else
|
||||
if path = any(PathTypeRepr p).getPath()
|
||||
then result instanceof TypeItemNode
|
||||
else any()
|
||||
else
|
||||
if path instanceof IdentPat
|
||||
then
|
||||
result instanceof VariantItemNode or
|
||||
result instanceof StructItemNode or
|
||||
result instanceof ConstItemNode
|
||||
else any()
|
||||
|
|
||||
pathUsesNamespace(path, ns)
|
||||
or
|
||||
@@ -1960,13 +2049,13 @@ private ItemNode resolvePathCand(RelevantPath path) {
|
||||
or
|
||||
exists(CallExpr ce |
|
||||
path = CallExprImpl::getFunctionPath(ce) and
|
||||
result.(ParameterizableItemNode).getArity() = ce.getNumberOfArgs()
|
||||
result.(ParameterizableItemNode).getArity() = ce.getArgList().getNumberOfArgs()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Get a trait that should be visible when `path` resolves to `node`, if any. */
|
||||
private Trait getResolvePathTraitUsed(RelevantPath path, AssocItemNode node) {
|
||||
private Trait getResolvePathTraitUsed(PathExt path, AssocItemNode node) {
|
||||
exists(TypeItemNode type, ImplItemNodeImpl impl |
|
||||
node = resolvePathCandQualified(_, type, path, _) and
|
||||
typeImplEdge(type, impl, _, _, node, _) and
|
||||
@@ -1978,9 +2067,9 @@ private predicate pathTraitUsed(Element path, Trait trait) {
|
||||
trait = getResolvePathTraitUsed(path, _)
|
||||
}
|
||||
|
||||
/** Gets the item that `path` resolves to, if any. */
|
||||
/** INTERNAL: Do not use; use `resolvePath` instead. */
|
||||
cached
|
||||
ItemNode resolvePath(RelevantPath path) {
|
||||
ItemNode resolvePathIgnoreVariableShadowing(PathExt path) {
|
||||
result = resolvePathCand(path) and
|
||||
not path = any(Path parent | exists(resolvePathCand(parent))).getQualifier() and
|
||||
(
|
||||
@@ -1993,29 +2082,43 @@ ItemNode resolvePath(RelevantPath path) {
|
||||
or
|
||||
// if `path` is the qualifier of a resolvable `parent`, then we should
|
||||
// resolve `path` to something consistent with what `parent` resolves to
|
||||
exists(RelevantPath parent |
|
||||
resolvePathCandQualified(path, result, parent, _) = resolvePath(parent)
|
||||
exists(PathExt parent |
|
||||
resolvePathCandQualified(path, result, parent, _) = resolvePathIgnoreVariableShadowing(parent)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isUseTreeSubPath(UseTree tree, RelevantPath path) {
|
||||
/**
|
||||
* Holds if `ip` resolves to some constructor or constant.
|
||||
*/
|
||||
// use `forceLocal` once we implement overlay support
|
||||
pragma[nomagic]
|
||||
predicate identPatIsResolvable(IdentPat ip) { exists(resolvePathIgnoreVariableShadowing(ip)) }
|
||||
|
||||
/** Gets the item that `path` resolves to, if any. */
|
||||
pragma[nomagic]
|
||||
ItemNode resolvePath(PathExt path) {
|
||||
result = resolvePathIgnoreVariableShadowing(path) and
|
||||
not path = any(VariableAccess va).(PathExpr).getPath()
|
||||
}
|
||||
|
||||
private predicate isUseTreeSubPath(UseTree tree, PathExt path) {
|
||||
path = tree.getPath()
|
||||
or
|
||||
exists(RelevantPath mid |
|
||||
exists(PathExt mid |
|
||||
isUseTreeSubPath(tree, mid) and
|
||||
path = mid.getQualifier()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isUseTreeSubPathUnqualified(UseTree tree, RelevantPath path, string name) {
|
||||
private predicate isUseTreeSubPathUnqualified(UseTree tree, PathExt path, string name) {
|
||||
isUseTreeSubPath(tree, path) and
|
||||
not exists(path.getQualifier()) and
|
||||
name = path.getText()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) {
|
||||
private ItemNode resolveUseTreeListItem(Use use, UseTree tree, PathExt path, SuccessorKind kind) {
|
||||
exists(UseOption useOpt | checkQualifiedVisibility(use, result, kind, useOpt) |
|
||||
exists(UseTree midTree, ItemNode mid, string name |
|
||||
mid = resolveUseTreeListItem(use, midTree) and
|
||||
@@ -2032,9 +2135,7 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ItemNode resolveUseTreeListItemQualifier(
|
||||
Use use, UseTree tree, RelevantPath path, string name
|
||||
) {
|
||||
private ItemNode resolveUseTreeListItemQualifier(Use use, UseTree tree, PathExt path, string name) {
|
||||
result = resolveUseTreeListItem(use, tree, path.getQualifier(), _) and
|
||||
name = path.getText()
|
||||
}
|
||||
@@ -2189,7 +2290,7 @@ private module Debug {
|
||||
}
|
||||
|
||||
predicate debugUnqualifiedPathLookup(
|
||||
RelevantPath p, string name, Namespace ns, ItemNode ancestor, string path
|
||||
PathExt p, string name, Namespace ns, ItemNode ancestor, string path
|
||||
) {
|
||||
p = getRelevantLocatable() and
|
||||
exists(ItemNode encl |
|
||||
@@ -2199,14 +2300,19 @@ private module Debug {
|
||||
path = p.toStringDebug()
|
||||
}
|
||||
|
||||
ItemNode debugUnqualifiedPathLookup(PathExt p, Namespace ns, SuccessorKind kind) {
|
||||
p = getRelevantLocatable() and
|
||||
result = unqualifiedPathLookup(p, ns, kind)
|
||||
}
|
||||
|
||||
predicate debugItemNode(ItemNode item) { item = getRelevantLocatable() }
|
||||
|
||||
ItemNode debugResolvePath(RelevantPath path) {
|
||||
ItemNode debugResolvePath(PathExt path) {
|
||||
path = getRelevantLocatable() and
|
||||
result = resolvePath(path)
|
||||
}
|
||||
|
||||
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) {
|
||||
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree, PathExt path, SuccessorKind kind) {
|
||||
use = getRelevantLocatable() and
|
||||
result = resolveUseTreeListItem(use, tree, path, kind)
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ query predicate multiplePathResolutions(Path p, ItemNode i) {
|
||||
strictcount(ItemNode i0 | i0 = resolvePath(p) and not i0 instanceof Crate) > 1
|
||||
}
|
||||
|
||||
/** Holds if `call` has multiple static call targets including `target`. */
|
||||
query predicate multipleCallTargets(CallExprBase call, Callable target) {
|
||||
target = call.getStaticTarget() and
|
||||
strictcount(call.getStaticTarget()) > 1
|
||||
/** Holds if `ie` has multiple resolved targets including `target`. */
|
||||
query predicate multipleResolvedTargets(InvocationExpr ie, Addressable target) {
|
||||
target = ie.getResolvedTarget() and
|
||||
strictcount(ie.getResolvedTarget()) > 1
|
||||
}
|
||||
|
||||
/** Holds if `fe` resolves to multiple record fields including `field`. */
|
||||
@@ -55,8 +55,8 @@ int getPathResolutionInconsistencyCounts(string type) {
|
||||
type = "Multiple path resolutions" and
|
||||
result = count(Path p | multiplePathResolutions(p, _) | p)
|
||||
or
|
||||
type = "Multiple static call targets" and
|
||||
result = count(CallExprBase call | multipleCallTargets(call, _) | call)
|
||||
type = "Multiple resolved targets" and
|
||||
result = count(InvocationExpr ie | multipleResolvedTargets(ie, _) | ie)
|
||||
or
|
||||
type = "Multiple record fields" and
|
||||
result = count(FieldExpr fe | multipleStructFields(fe, _) | fe)
|
||||
|
||||
@@ -140,6 +140,9 @@ class EnumType extends Type, TEnum {
|
||||
|
||||
EnumType() { this = TEnum(enum) }
|
||||
|
||||
/** Gets the enum that this enum type represents. */
|
||||
Enum getEnum() { result = enum }
|
||||
|
||||
override TypeParameter getPositionalTypeParameter(int i) {
|
||||
result = TTypeParamTypeParameter(enum.getGenericParamList().getTypeParam(i))
|
||||
}
|
||||
@@ -336,12 +339,23 @@ class NeverType extends Type, TNeverType {
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
class PtrType extends StructType {
|
||||
PtrType() { this.getStruct() instanceof Builtins::PtrType }
|
||||
abstract class PtrType extends StructType { }
|
||||
|
||||
override string toString() { result = "*" }
|
||||
pragma[nomagic]
|
||||
TypeParamTypeParameter getPtrTypeParameter() {
|
||||
result = any(PtrType t).getPositionalTypeParameter(0)
|
||||
}
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
class PtrMutType extends PtrType {
|
||||
PtrMutType() { this.getStruct() instanceof Builtins::PtrMutType }
|
||||
|
||||
override string toString() { result = "*mut" }
|
||||
}
|
||||
|
||||
class PtrConstType extends PtrType {
|
||||
PtrConstType() { this.getStruct() instanceof Builtins::PtrConstType }
|
||||
|
||||
override string toString() { result = "*const" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,14 +388,11 @@ class UnknownType extends Type, TUnknownType {
|
||||
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() }
|
||||
|
||||
abstract ItemNode getDeclaringItem();
|
||||
}
|
||||
|
||||
private class RawTypeParameter = @type_param or @trait or @type_alias or @impl_trait_type_repr;
|
||||
@@ -400,6 +411,8 @@ class TypeParamTypeParameter extends TypeParameter, TTypeParamTypeParameter {
|
||||
|
||||
TypeParam getTypeParam() { result = typeParam }
|
||||
|
||||
override ItemNode getDeclaringItem() { result.getTypeParam(_) = typeParam }
|
||||
|
||||
override string toString() { result = typeParam.toString() }
|
||||
|
||||
override Location getLocation() { result = typeParam.getLocation() }
|
||||
@@ -433,6 +446,8 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara
|
||||
/** Gets the trait that contains this associated type declaration. */
|
||||
TraitItemNode getTrait() { result.getAnAssocItem() = typeAlias }
|
||||
|
||||
override ItemNode getDeclaringItem() { result = this.getTrait() }
|
||||
|
||||
override string toString() { result = typeAlias.getName().getText() }
|
||||
|
||||
override Location getLocation() { result = typeAlias.getLocation() }
|
||||
@@ -465,6 +480,8 @@ class DynTraitTypeParameter extends TypeParameter, TDynTraitTypeParameter {
|
||||
result = [this.getTypeParam().toString(), this.getTypeAlias().getName().toString()]
|
||||
}
|
||||
|
||||
override ItemNode getDeclaringItem() { none() }
|
||||
|
||||
override string toString() { result = "dyn(" + this.toStringInner() + ")" }
|
||||
|
||||
override Location getLocation() { result = n.getLocation() }
|
||||
@@ -480,6 +497,8 @@ class ImplTraitTypeParameter extends TypeParameter, TImplTraitTypeParameter {
|
||||
|
||||
ImplTraitTypeRepr getImplTraitTypeRepr() { result = implTrait }
|
||||
|
||||
override ItemNode getDeclaringItem() { none() }
|
||||
|
||||
override string toString() { result = "impl(" + typeParam.toString() + ")" }
|
||||
|
||||
override Location getLocation() { result = typeParam.getLocation() }
|
||||
@@ -499,6 +518,8 @@ class SelfTypeParameter extends TypeParameter, TSelfTypeParameter {
|
||||
|
||||
Trait getTrait() { result = trait }
|
||||
|
||||
override ItemNode getDeclaringItem() { result = trait }
|
||||
|
||||
override string toString() { result = "Self [" + trait.toString() + "]" }
|
||||
|
||||
override Location getLocation() { result = trait.getLocation() }
|
||||
@@ -526,6 +547,8 @@ class ImplTraitTypeTypeParameter extends ImplTraitType, TypeParameter {
|
||||
|
||||
ImplTraitTypeTypeParameter() { impl = function.getAParam().getTypeRepr() }
|
||||
|
||||
override ItemNode getDeclaringItem() { none() }
|
||||
|
||||
override Function getFunction() { result = function }
|
||||
|
||||
override TypeParameter getPositionalTypeParameter(int i) { none() }
|
||||
|
||||
@@ -9,12 +9,11 @@ private import TypeMention
|
||||
private import typeinference.FunctionType
|
||||
private import typeinference.FunctionOverloading as FunctionOverloading
|
||||
private import typeinference.BlanketImplementation as BlanketImplementation
|
||||
private import codeql.rust.elements.internal.VariableImpl::Impl as VariableImpl
|
||||
private import codeql.rust.internal.CachedStages
|
||||
private import codeql.typeinference.internal.TypeInference
|
||||
private import codeql.rust.frameworks.stdlib.Stdlib
|
||||
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
|
||||
private import codeql.rust.elements.Call
|
||||
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
|
||||
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
|
||||
|
||||
class Type = T::Type;
|
||||
@@ -230,11 +229,6 @@ module Consistency {
|
||||
}
|
||||
}
|
||||
|
||||
/** A method, that is, a function with a `self` parameter. */
|
||||
private class Method extends Function {
|
||||
Method() { this.hasSelfParam() }
|
||||
}
|
||||
|
||||
/** A function without a `self` parameter. */
|
||||
private class NonMethodFunction extends Function {
|
||||
NonMethodFunction() { not this.hasSelfParam() }
|
||||
@@ -431,7 +425,10 @@ module CertainTypeInference {
|
||||
or
|
||||
result = inferLiteralType(n, path, true)
|
||||
or
|
||||
result = inferRefNodeType(n) and
|
||||
result = inferRefPatType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferRefExprType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferLogicalOperationType(n, path)
|
||||
@@ -606,10 +603,14 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
|
||||
strictcount(Expr e | bodyReturns(n1, e)) = 1
|
||||
)
|
||||
or
|
||||
(
|
||||
n1 = n2.(RefExpr).getExpr() or
|
||||
n1 = n2.(RefPat).getPat()
|
||||
) and
|
||||
n2 =
|
||||
any(RefExpr re |
|
||||
n1 = re.getExpr() and
|
||||
prefix1.isEmpty() and
|
||||
prefix2 = TypePath::singleton(inferRefExprType(re).getPositionalTypeParameter(0))
|
||||
)
|
||||
or
|
||||
n1 = n2.(RefPat).getPat() and
|
||||
prefix1.isEmpty() and
|
||||
prefix2 = TypePath::singleton(getRefTypeParameter())
|
||||
or
|
||||
@@ -629,7 +630,7 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
|
||||
n2 = be.getStmtList().getTailExpr() and
|
||||
if be.isAsync()
|
||||
then
|
||||
prefix1 = TypePath::singleton(getFutureOutputTypeParameter()) and
|
||||
prefix1 = TypePath::singleton(getDynFutureOutputTypeParameter()) and
|
||||
prefix2.isEmpty()
|
||||
else (
|
||||
prefix1.isEmpty() and
|
||||
@@ -672,7 +673,7 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
|
||||
|
||||
/**
|
||||
* Holds if `child` is a child of `parent`, and the Rust compiler applies [least
|
||||
* upper bound (LUB) coercion](1) to infer the type of `parent` from the type of
|
||||
* upper bound (LUB) coercion][1] to infer the type of `parent` from the type of
|
||||
* `child`.
|
||||
*
|
||||
* In this case, we want type information to only flow from `child` to `parent`,
|
||||
@@ -709,9 +710,7 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) {
|
||||
* of `n2` at `prefix2`, but type information should only propagate from `n1` to
|
||||
* `n2`.
|
||||
*/
|
||||
private predicate typeEqualityNonSymmetric(
|
||||
AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2
|
||||
) {
|
||||
private predicate typeEqualityAsymmetric(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) {
|
||||
lubCoercion(n2, n1, prefix2) and
|
||||
prefix1.isEmpty()
|
||||
or
|
||||
@@ -723,6 +722,13 @@ private predicate typeEqualityNonSymmetric(
|
||||
not lubCoercion(mid, n1, _) and
|
||||
prefix1 = prefixMid.append(suffix)
|
||||
)
|
||||
or
|
||||
// When `n2` is `*n1` propagate type information from a raw pointer type
|
||||
// parameter at `n1`. The other direction is handled in
|
||||
// `inferDereferencedExprPtrType`.
|
||||
n1 = n2.(DerefExpr).getExpr() and
|
||||
prefix1 = TypePath::singleton(getPtrTypeParameter()) and
|
||||
prefix2.isEmpty()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -735,7 +741,7 @@ private Type inferTypeEquality(AstNode n, TypePath path) {
|
||||
or
|
||||
typeEquality(n2, prefix2, n, prefix1)
|
||||
or
|
||||
typeEqualityNonSymmetric(n2, prefix2, n, prefix1)
|
||||
typeEqualityAsymmetric(n2, prefix2, n, prefix1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -787,7 +793,7 @@ private module StructExprMatchingInput implements MatchingInputSig {
|
||||
}
|
||||
|
||||
private class StructDecl extends Declaration, Struct {
|
||||
StructDecl() { this.isStruct() }
|
||||
StructDecl() { this.isStruct() or this.isUnit() }
|
||||
|
||||
override TypeParam getATypeParam() { result = this.getGenericParamList().getATypeParam() }
|
||||
|
||||
@@ -804,7 +810,7 @@ private module StructExprMatchingInput implements MatchingInputSig {
|
||||
}
|
||||
|
||||
private class StructVariantDecl extends Declaration, Variant {
|
||||
StructVariantDecl() { this.isStruct() }
|
||||
StructVariantDecl() { this.isStruct() or this.isUnit() }
|
||||
|
||||
Enum getEnum() { result.getVariantList().getAVariant() = this }
|
||||
|
||||
@@ -961,6 +967,24 @@ private Type getCallExprTypeQualifier(CallExpr ce, TypePath path) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the trait qualifier of function call `ce`, if any.
|
||||
*
|
||||
* For example, the trait qualifier of `Default::<i32>::default()` is `Default`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private Trait getCallExprTraitQualifier(CallExpr ce) {
|
||||
exists(PathExt qualifierPath |
|
||||
qualifierPath = getCallExprPathQualifier(ce) and
|
||||
result = resolvePath(qualifierPath) and
|
||||
// When the qualifier is `Self` and resolves to a trait, it's inside a
|
||||
// trait method's default implementation. This is not a dispatch whose
|
||||
// target is inferred from the type of the receiver, but should always
|
||||
// resolve to the function in the trait block as path resolution does.
|
||||
not qualifierPath.isUnqualified("Self")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides functionality related to context-based typing of calls.
|
||||
*/
|
||||
@@ -1244,14 +1268,17 @@ private module MethodResolution {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate methodCallTraitCandidate(Element mc, Trait trait) {
|
||||
exists(string name, int arity |
|
||||
mc.(MethodCall).hasNameAndArity(name, arity) and
|
||||
methodTraitInfo(name, arity, trait)
|
||||
|
|
||||
not mc.(Call).hasTrait()
|
||||
or
|
||||
trait = mc.(Call).getTrait()
|
||||
)
|
||||
mc =
|
||||
any(MethodCall mc0 |
|
||||
exists(string name, int arity |
|
||||
mc0.hasNameAndArity(name, arity) and
|
||||
methodTraitInfo(name, arity, trait)
|
||||
|
|
||||
not mc0.hasTrait()
|
||||
or
|
||||
trait = mc0.getTrait()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private module MethodTraitIsVisible = TraitIsVisible<methodCallTraitCandidate/2>;
|
||||
@@ -1296,7 +1323,7 @@ private module MethodResolution {
|
||||
or
|
||||
methodCallVisibleTraitCandidate(mc, i)
|
||||
or
|
||||
i.(ImplItemNode).resolveTraitTy() = mc.(Call).getTrait()
|
||||
i.(ImplItemNode).resolveTraitTy() = mc.getTrait()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1323,7 +1350,7 @@ private module MethodResolution {
|
||||
|
|
||||
methodCallVisibleImplTraitCandidate(mc, impl)
|
||||
or
|
||||
impl.resolveTraitTy() = mc.(Call).getTrait()
|
||||
impl.resolveTraitTy() = mc.getTrait()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1350,18 +1377,24 @@ private module MethodResolution {
|
||||
abstract class MethodCall extends Expr {
|
||||
abstract predicate hasNameAndArity(string name, int arity);
|
||||
|
||||
abstract Expr getArgument(ArgumentPosition pos);
|
||||
abstract Expr getArg(ArgumentPosition pos);
|
||||
|
||||
abstract predicate supportsAutoDerefAndBorrow();
|
||||
|
||||
/** Gets the trait targeted by this call, if any. */
|
||||
abstract Trait getTrait();
|
||||
|
||||
/** Holds if this call targets a trait. */
|
||||
predicate hasTrait() { exists(this.getTrait()) }
|
||||
|
||||
AstNode getNodeAt(FunctionPosition apos) {
|
||||
result = this.getArgument(apos.asArgumentPosition())
|
||||
result = this.getArg(apos.asArgumentPosition())
|
||||
or
|
||||
result = this and apos.isReturn()
|
||||
}
|
||||
|
||||
Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) {
|
||||
result = inferType(this.getArgument(pos), path)
|
||||
result = inferType(this.getArg(pos), path)
|
||||
}
|
||||
|
||||
private Type getReceiverTypeAt(TypePath path) {
|
||||
@@ -1587,12 +1620,12 @@ private module MethodResolution {
|
||||
|
||||
predicate receiverHasImplicitDeref(AstNode receiver) {
|
||||
exists(this.resolveCallTarget(_, ".ref", false)) and
|
||||
receiver = this.getArgument(CallImpl::TSelfArgumentPosition())
|
||||
receiver = this.getArg(any(ArgumentPosition pos | pos.isSelf()))
|
||||
}
|
||||
|
||||
predicate receiverHasImplicitBorrow(AstNode receiver) {
|
||||
predicate argumentHasImplicitBorrow(AstNode arg) {
|
||||
exists(this.resolveCallTarget(_, "", true)) and
|
||||
receiver = this.getArgument(CallImpl::TSelfArgumentPosition())
|
||||
arg = this.getArg(any(ArgumentPosition pos | pos.isSelf()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1603,35 +1636,45 @@ private module MethodResolution {
|
||||
arity = super.getArgList().getNumberOfArgs()
|
||||
}
|
||||
|
||||
override Expr getArgument(ArgumentPosition pos) {
|
||||
pos.isSelf() and
|
||||
result = MethodCallExpr.super.getReceiver()
|
||||
or
|
||||
result = super.getArgList().getArg(pos.asPosition())
|
||||
override Expr getArg(ArgumentPosition pos) {
|
||||
result = MethodCallExpr.super.getSyntacticArgument(pos)
|
||||
}
|
||||
|
||||
override predicate supportsAutoDerefAndBorrow() { any() }
|
||||
|
||||
override Trait getTrait() { none() }
|
||||
}
|
||||
|
||||
private class MethodCallIndexExpr extends MethodCall, IndexExpr {
|
||||
private class MethodCallIndexExpr extends MethodCall instanceof IndexExpr {
|
||||
private predicate isInMutableContext() {
|
||||
// todo: does not handle all cases yet
|
||||
VariableImpl::assignmentOperationDescendant(_, this)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
override predicate hasNameAndArity(string name, int arity) {
|
||||
name = "index" and
|
||||
(if this.isInMutableContext() then name = "index_mut" else name = "index") and
|
||||
arity = 1
|
||||
}
|
||||
|
||||
override Expr getArgument(ArgumentPosition pos) {
|
||||
override Expr getArg(ArgumentPosition pos) {
|
||||
pos.isSelf() and
|
||||
result = this.getBase()
|
||||
result = super.getBase()
|
||||
or
|
||||
pos.asPosition() = 0 and
|
||||
result = this.getIndex()
|
||||
result = super.getIndex()
|
||||
}
|
||||
|
||||
override predicate supportsAutoDerefAndBorrow() { any() }
|
||||
|
||||
override Trait getTrait() {
|
||||
if this.isInMutableContext()
|
||||
then result.getCanonicalPath() = "core::ops::index::IndexMut"
|
||||
else result.getCanonicalPath() = "core::ops::index::Index"
|
||||
}
|
||||
}
|
||||
|
||||
private class MethodCallCallExpr extends MethodCall, CallExpr {
|
||||
private class MethodCallCallExpr extends MethodCall instanceof CallExpr {
|
||||
MethodCallCallExpr() {
|
||||
exists(getCallExprPathQualifier(this)) and
|
||||
// even if a method cannot be resolved by path resolution, it may still
|
||||
@@ -1656,14 +1699,14 @@ private module MethodResolution {
|
||||
pragma[nomagic]
|
||||
override predicate hasNameAndArity(string name, int arity) {
|
||||
name = CallExprImpl::getFunctionPath(this).getText() and
|
||||
arity = this.getArgList().getNumberOfArgs() - 1
|
||||
arity = super.getArgList().getNumberOfArgs() - 1
|
||||
}
|
||||
|
||||
override Expr getArgument(ArgumentPosition pos) {
|
||||
override Expr getArg(ArgumentPosition pos) {
|
||||
pos.isSelf() and
|
||||
result = this.getArg(0)
|
||||
result = super.getSyntacticPositionalArgument(0)
|
||||
or
|
||||
result = this.getArgList().getArg(pos.asPosition() + 1)
|
||||
result = super.getSyntacticPositionalArgument(pos.asPosition() + 1)
|
||||
}
|
||||
|
||||
// needed for `TypeQualifierIsInstantiationOfImplSelfInput`
|
||||
@@ -1672,38 +1715,55 @@ private module MethodResolution {
|
||||
}
|
||||
|
||||
override predicate supportsAutoDerefAndBorrow() { none() }
|
||||
|
||||
override Trait getTrait() { result = getCallExprTraitQualifier(this) }
|
||||
}
|
||||
|
||||
final class MethodCallOperation extends MethodCall, Operation {
|
||||
final class MethodCallOperation extends MethodCall instanceof Operation {
|
||||
pragma[nomagic]
|
||||
override predicate hasNameAndArity(string name, int arity) {
|
||||
name = this.(Call).getMethodName() and
|
||||
arity = this.getNumberOfOperands() - 1
|
||||
super.isOverloaded(_, name, _) and
|
||||
arity = super.getNumberOfOperands() - 1
|
||||
}
|
||||
|
||||
override Expr getArgument(ArgumentPosition pos) { result = this.(Call).getArgument(pos) }
|
||||
override Expr getArg(ArgumentPosition pos) {
|
||||
pos.isSelf() and
|
||||
result = super.getOperand(0)
|
||||
or
|
||||
result = super.getOperand(pos.asPosition() + 1)
|
||||
}
|
||||
|
||||
private predicate implicitBorrowAt(ArgumentPosition pos) {
|
||||
exists(int borrows | super.isOverloaded(_, _, borrows) |
|
||||
pos.isSelf() and borrows >= 1
|
||||
or
|
||||
pos.asPosition() = 0 and borrows = 2
|
||||
)
|
||||
}
|
||||
|
||||
override Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) {
|
||||
if this.(Call).implicitBorrowAt(pos, true)
|
||||
if this.implicitBorrowAt(pos)
|
||||
then
|
||||
result instanceof RefType and
|
||||
path.isEmpty()
|
||||
or
|
||||
exists(TypePath path0 |
|
||||
result = inferType(this.getArgument(pos), path0) and
|
||||
result = inferType(this.getArg(pos), path0) and
|
||||
path = TypePath::cons(getRefTypeParameter(), path0)
|
||||
)
|
||||
else result = inferType(this.getArgument(pos), path)
|
||||
else result = inferType(this.getArg(pos), path)
|
||||
}
|
||||
|
||||
override predicate receiverHasImplicitBorrow(AstNode receiver) {
|
||||
override predicate argumentHasImplicitBorrow(AstNode arg) {
|
||||
exists(ArgumentPosition pos |
|
||||
this.(Call).implicitBorrowAt(pos, true) and
|
||||
receiver = this.getArgument(pos)
|
||||
this.implicitBorrowAt(pos) and
|
||||
arg = this.getArg(pos)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate supportsAutoDerefAndBorrow() { none() }
|
||||
|
||||
override Trait getTrait() { super.isOverloaded(result, _, _) }
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -2053,7 +2113,7 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
|
||||
or
|
||||
exists(TypePath suffix |
|
||||
result = this.resolveRetType(suffix) and
|
||||
path = TypePath::cons(getFutureOutputTypeParameter(), suffix)
|
||||
path = TypePath::cons(getDynFutureOutputTypeParameter(), suffix)
|
||||
)
|
||||
else result = this.resolveRetType(path)
|
||||
}
|
||||
@@ -2274,14 +2334,17 @@ private module NonMethodResolution {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate blanketLikeCallTraitCandidate(Element fc, Trait trait) {
|
||||
exists(string name, int arity |
|
||||
fc.(NonMethodCall).hasNameAndArity(name, arity) and
|
||||
functionInfoBlanketLikeRelevantPos(_, name, arity, _, trait, _, _, _, _)
|
||||
|
|
||||
not fc.(Call).hasTrait()
|
||||
or
|
||||
trait = fc.(Call).getTrait()
|
||||
)
|
||||
fc =
|
||||
any(NonMethodCall nmc |
|
||||
exists(string name, int arity |
|
||||
nmc.hasNameAndArity(name, arity) and
|
||||
functionInfoBlanketLikeRelevantPos(_, name, arity, _, trait, _, _, _, _)
|
||||
|
|
||||
not nmc.hasTrait()
|
||||
or
|
||||
trait = nmc.getTrait()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private module BlanketTraitIsVisible = TraitIsVisible<blanketLikeCallTraitCandidate/2>;
|
||||
@@ -2323,9 +2386,15 @@ private module NonMethodResolution {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the trait targeted by this call, if any. */
|
||||
Trait getTrait() { result = getCallExprTraitQualifier(this) }
|
||||
|
||||
/** Holds if this call targets a trait. */
|
||||
predicate hasTrait() { exists(this.getTrait()) }
|
||||
|
||||
pragma[nomagic]
|
||||
NonMethodFunction resolveAssocCallTargetCand(ImplItemNode i) {
|
||||
not this.(Call).hasTrait() and
|
||||
not this.hasTrait() and
|
||||
result = this.getPathResolutionResolved() and
|
||||
result = i.getASuccessor(_)
|
||||
or
|
||||
@@ -2333,7 +2402,7 @@ private module NonMethodResolution {
|
||||
}
|
||||
|
||||
AstNode getNodeAt(FunctionPosition pos) {
|
||||
result = this.getArg(pos.asPosition())
|
||||
result = this.getSyntacticArgument(pos.asArgumentPosition())
|
||||
or
|
||||
result = this and pos.isReturn()
|
||||
}
|
||||
@@ -2358,7 +2427,7 @@ private module NonMethodResolution {
|
||||
pragma[nomagic]
|
||||
predicate hasTraitResolved(TraitItemNode trait, NonMethodFunction resolved) {
|
||||
resolved = this.getPathResolutionResolved() and
|
||||
trait = this.(Call).getTrait()
|
||||
trait = this.getTrait()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2366,7 +2435,7 @@ private module NonMethodResolution {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
ItemNode resolveCallTargetViaPathResolution() {
|
||||
not this.(Call).hasTrait() and
|
||||
not this.hasTrait() and
|
||||
result = this.getPathResolutionResolved() and
|
||||
not FunctionOverloading::functionResolutionDependsOnArgument(_, result, _, _, _)
|
||||
}
|
||||
@@ -2391,7 +2460,7 @@ private module NonMethodResolution {
|
||||
|
||||
pragma[nomagic]
|
||||
NonMethodFunction resolveTraitFunctionViaPathResolution(TraitItemNode trait) {
|
||||
this.(Call).hasTrait() and
|
||||
this.hasTrait() and
|
||||
result = this.getPathResolutionResolved() and
|
||||
result = trait.getASuccessor(_)
|
||||
}
|
||||
@@ -2703,7 +2772,7 @@ private predicate inferNonMethodCallType =
|
||||
* A matching configuration for resolving types of operations like `a + b`.
|
||||
*/
|
||||
private module OperationMatchingInput implements MatchingInputSig {
|
||||
private import codeql.rust.elements.internal.OperationImpl as OperationImpl
|
||||
private import codeql.rust.elements.internal.OperationImpl::Impl as OperationImpl
|
||||
import FunctionPositionMatchingInput
|
||||
|
||||
class Declaration extends MethodCallMatchingInput::Declaration {
|
||||
@@ -2783,18 +2852,19 @@ private predicate inferOperationType =
|
||||
ContextTyping::CheckContextTyping<inferOperationType0/3>::check/2;
|
||||
|
||||
pragma[nomagic]
|
||||
private Type getFieldExprLookupType(FieldExpr fe, string name) {
|
||||
private Type getFieldExprLookupType(FieldExpr fe, string name, boolean isDereferenced) {
|
||||
exists(TypePath path |
|
||||
result = inferType(fe.getContainer(), path) and
|
||||
name = fe.getIdentifier().getText() and
|
||||
isComplexRootStripped(path, result)
|
||||
isComplexRootStripped(path, result) and
|
||||
if path.isEmpty() then isDereferenced = false else isDereferenced = true
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Type getTupleFieldExprLookupType(FieldExpr fe, int pos) {
|
||||
private Type getTupleFieldExprLookupType(FieldExpr fe, int pos, boolean isDereferenced) {
|
||||
exists(string name |
|
||||
result = getFieldExprLookupType(fe, name) and
|
||||
result = getFieldExprLookupType(fe, name, isDereferenced) and
|
||||
pos = name.toInt()
|
||||
)
|
||||
}
|
||||
@@ -2911,8 +2981,8 @@ private module FieldExprMatchingInput implements MatchingInputSig {
|
||||
// mutual recursion; resolving fields requires resolving types and vice versa
|
||||
result =
|
||||
[
|
||||
TStructFieldDecl(resolveStructFieldExpr(this)).(TDeclaration),
|
||||
TTupleFieldDecl(resolveTupleFieldExpr(this))
|
||||
TStructFieldDecl(resolveStructFieldExpr(this, _)).(TDeclaration),
|
||||
TTupleFieldDecl(resolveTupleFieldExpr(this, _))
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -2951,16 +3021,21 @@ private Type inferFieldExprType(AstNode n, TypePath path) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the root type of the reference expression `ref`. */
|
||||
pragma[nomagic]
|
||||
private Type inferRefExprType(RefExpr ref) {
|
||||
if ref.isRaw()
|
||||
then
|
||||
ref.isMut() and result instanceof PtrMutType
|
||||
or
|
||||
ref.isConst() and result instanceof PtrConstType
|
||||
else result instanceof RefType
|
||||
}
|
||||
|
||||
/** Gets the root type of the reference node `ref`. */
|
||||
pragma[nomagic]
|
||||
private Type inferRefNodeType(AstNode ref) {
|
||||
(
|
||||
ref = any(IdentPat ip | ip.isRef()).getName()
|
||||
or
|
||||
ref instanceof RefExpr
|
||||
or
|
||||
ref instanceof RefPat
|
||||
) and
|
||||
private Type inferRefPatType(AstNode ref) {
|
||||
(ref = any(IdentPat ip | ip.isRef()).getName() or ref instanceof RefPat) and
|
||||
result instanceof RefType
|
||||
}
|
||||
|
||||
@@ -3024,13 +3099,18 @@ private Type inferLiteralType(LiteralExpr le, TypePath path, boolean certain) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private TraitType getFutureTraitType() { result.getTrait() instanceof FutureTrait }
|
||||
private DynTraitType getFutureTraitType() { result.getTrait() instanceof FutureTrait }
|
||||
|
||||
pragma[nomagic]
|
||||
private AssociatedTypeTypeParameter getFutureOutputTypeParameter() {
|
||||
result.getTypeAlias() = any(FutureTrait ft).getOutputType()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private DynTraitTypeParameter getDynFutureOutputTypeParameter() {
|
||||
result = TDynTraitTypeParameter(any(FutureTrait ft).getOutputType())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate isUnitBlockExpr(BlockExpr be) {
|
||||
not be.getStmtList().hasTailExpr() and
|
||||
@@ -3047,7 +3127,7 @@ private Type inferBlockExprType(BlockExpr be, TypePath path) {
|
||||
result = getFutureTraitType()
|
||||
or
|
||||
isUnitBlockExpr(be) and
|
||||
path = TypePath::singleton(getFutureOutputTypeParameter()) and
|
||||
path = TypePath::singleton(getDynFutureOutputTypeParameter()) and
|
||||
result instanceof UnitType
|
||||
) else (
|
||||
isUnitBlockExpr(be) and
|
||||
@@ -3072,6 +3152,7 @@ final private class AwaitTarget extends Expr {
|
||||
}
|
||||
|
||||
private module AwaitSatisfiesConstraintInput implements SatisfiesConstraintInputSig<AwaitTarget> {
|
||||
pragma[nomagic]
|
||||
predicate relevantConstraint(AwaitTarget term, Type constraint) {
|
||||
exists(term) and
|
||||
constraint.(TraitType).getTrait() instanceof FutureTrait
|
||||
@@ -3138,6 +3219,27 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Type getInferredDerefType(DerefExpr de, TypePath path) { result = inferType(de, path) }
|
||||
|
||||
pragma[nomagic]
|
||||
private PtrType getInferredDerefExprPtrType(DerefExpr de) { result = inferType(de.getExpr()) }
|
||||
|
||||
/**
|
||||
* Gets the inferred type of `n` at `path` when `n` occurs in a dereference
|
||||
* expression `*n` and when `n` is known to have a raw pointer type.
|
||||
*
|
||||
* The other direction is handled in `typeEqualityAsymmetric`.
|
||||
*/
|
||||
private Type inferDereferencedExprPtrType(AstNode n, TypePath path) {
|
||||
exists(DerefExpr de, PtrType type, TypePath suffix |
|
||||
de.getExpr() = n and
|
||||
type = getInferredDerefExprPtrType(de) and
|
||||
result = getInferredDerefType(de, suffix) and
|
||||
path = TypePath::cons(type.getPositionalTypeParameter(0), suffix)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A matching configuration for resolving types of struct patterns
|
||||
* like `let Foo { bar } = ...`.
|
||||
@@ -3358,8 +3460,9 @@ private Type inferDynamicCallExprType(Expr n, TypePath path) {
|
||||
or
|
||||
// Propagate the function's parameter type to the arguments
|
||||
exists(int index |
|
||||
n = ce.getCall().getArgList().getArg(index) and
|
||||
path = path0.stripPrefix(fnParameterPath(ce.getCall().getNumberOfArgs(), index))
|
||||
n = ce.getCall().getSyntacticPositionalArgument(index) and
|
||||
path =
|
||||
path0.stripPrefix(fnParameterPath(ce.getCall().getArgList().getNumberOfArgs(), index))
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -3369,16 +3472,17 @@ private Type inferDynamicCallExprType(Expr n, TypePath path) {
|
||||
ce.getTypeAt(TypePath::nil()).(DynTraitType).getTrait() instanceof FnOnceTrait
|
||||
|
|
||||
// Propagate the type of arguments to the parameter types of closure
|
||||
exists(int index |
|
||||
exists(int index, ArgList args |
|
||||
n = ce and
|
||||
arity = ce.getCall().getNumberOfArgs() and
|
||||
result = inferType(ce.getCall().getArg(index), path0) and
|
||||
args = ce.getCall().getArgList() and
|
||||
arity = args.getNumberOfArgs() and
|
||||
result = inferType(args.getArg(index), path0) and
|
||||
path = closureParameterPath(arity, index).append(path0)
|
||||
)
|
||||
or
|
||||
// Propagate the type of the call expression to the return type of the closure
|
||||
n = ce and
|
||||
arity = ce.getCall().getNumberOfArgs() and
|
||||
arity = ce.getCall().getArgList().getNumberOfArgs() and
|
||||
result = inferType(ce.getCall(), path0) and
|
||||
path = closureReturnPath().append(path0)
|
||||
)
|
||||
@@ -3390,7 +3494,7 @@ private Type inferClosureExprType(AstNode n, TypePath path) {
|
||||
exists(ClosureExpr ce |
|
||||
n = ce and
|
||||
path.isEmpty() and
|
||||
result = TDynTraitType(any(FnOnceTrait t))
|
||||
result = TDynTraitType(any(FnOnceTrait t)) // always exists because of the mention in `builtins/mentions.rs`
|
||||
or
|
||||
n = ce and
|
||||
path = TypePath::singleton(TDynTraitTypeParameter(any(FnOnceTrait t).getTypeParam())) and
|
||||
@@ -3409,32 +3513,56 @@ private Type inferCastExprType(CastExpr ce, TypePath path) {
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/** Holds if `receiver` is the receiver of a method call with an implicit dereference. */
|
||||
/** Holds if `n` is implicitly dereferenced. */
|
||||
cached
|
||||
predicate receiverHasImplicitDeref(AstNode receiver) {
|
||||
any(MethodResolution::MethodCall mc).receiverHasImplicitDeref(receiver)
|
||||
}
|
||||
|
||||
/** Holds if `receiver` is the receiver of a method call with an implicit borrow. */
|
||||
cached
|
||||
predicate receiverHasImplicitBorrow(AstNode receiver) {
|
||||
any(MethodResolution::MethodCall mc).receiverHasImplicitBorrow(receiver)
|
||||
}
|
||||
|
||||
/** Gets an item (function or tuple struct/variant) that `call` resolves to, if any. */
|
||||
cached
|
||||
Addressable resolveCallTarget(Call call) {
|
||||
result = call.(MethodResolution::MethodCall).resolveCallTarget(_, _, _)
|
||||
predicate implicitDeref(AstNode n) {
|
||||
any(MethodResolution::MethodCall mc).receiverHasImplicitDeref(n)
|
||||
or
|
||||
result = call.(NonMethodResolution::NonMethodCall).resolveCallTarget()
|
||||
n =
|
||||
any(FieldExpr fe |
|
||||
exists(resolveStructFieldExpr(fe, true))
|
||||
or
|
||||
exists(resolveTupleFieldExpr(fe, true))
|
||||
).getContainer()
|
||||
}
|
||||
|
||||
/** Holds if `n` is implicitly borrowed. */
|
||||
cached
|
||||
predicate implicitBorrow(AstNode n) {
|
||||
any(MethodResolution::MethodCall mc).argumentHasImplicitBorrow(n)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an item (function or tuple struct/variant) that `call` resolves to, if
|
||||
* any.
|
||||
*
|
||||
* The parameter `dispatch` is `true` if and only if the resolved target is a
|
||||
* trait item because a precise target could not be determined from the
|
||||
* types (for instance in the presence of generics or `dyn` types)
|
||||
*/
|
||||
cached
|
||||
Addressable resolveCallTarget(InvocationExpr call, boolean dispatch) {
|
||||
dispatch = false and
|
||||
result = call.(NonMethodResolution::NonMethodCall).resolveCallTargetViaPathResolution()
|
||||
or
|
||||
exists(ImplOrTraitItemNode i |
|
||||
i instanceof TraitItemNode and dispatch = true
|
||||
or
|
||||
i instanceof ImplItemNode and dispatch = false
|
||||
|
|
||||
result = call.(MethodResolution::MethodCall).resolveCallTarget(i, _, _) or
|
||||
result = call.(NonMethodResolution::NonMethodCall).resolveCallTargetViaTypeInference(i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the struct field that the field expression `fe` resolves to, if any.
|
||||
*/
|
||||
cached
|
||||
StructField resolveStructFieldExpr(FieldExpr fe) {
|
||||
exists(string name, Type ty | ty = getFieldExprLookupType(fe, pragma[only_bind_into](name)) |
|
||||
StructField resolveStructFieldExpr(FieldExpr fe, boolean isDereferenced) {
|
||||
exists(string name, Type ty |
|
||||
ty = getFieldExprLookupType(fe, pragma[only_bind_into](name), isDereferenced)
|
||||
|
|
||||
result = ty.(StructType).getStruct().getStructField(pragma[only_bind_into](name)) or
|
||||
result = ty.(UnionType).getUnion().getStructField(pragma[only_bind_into](name))
|
||||
)
|
||||
@@ -3444,10 +3572,10 @@ private module Cached {
|
||||
* Gets the tuple field that the field expression `fe` resolves to, if any.
|
||||
*/
|
||||
cached
|
||||
TupleField resolveTupleFieldExpr(FieldExpr fe) {
|
||||
TupleField resolveTupleFieldExpr(FieldExpr fe, boolean isDereferenced) {
|
||||
exists(int i |
|
||||
result =
|
||||
getTupleFieldExprLookupType(fe, pragma[only_bind_into](i))
|
||||
getTupleFieldExprLookupType(fe, pragma[only_bind_into](i), isDereferenced)
|
||||
.(StructType)
|
||||
.getStruct()
|
||||
.getTupleField(pragma[only_bind_into](i))
|
||||
@@ -3528,6 +3656,8 @@ private module Cached {
|
||||
or
|
||||
result = inferIndexExprType(n, path)
|
||||
or
|
||||
result = inferDereferencedExprPtrType(n, path)
|
||||
or
|
||||
result = inferForLoopExprType(n, path)
|
||||
or
|
||||
result = inferDynamicCallExprType(n, path)
|
||||
@@ -3563,9 +3693,9 @@ private module Debug {
|
||||
result = inferType(n, path)
|
||||
}
|
||||
|
||||
Addressable debugResolveCallTarget(Call c) {
|
||||
Addressable debugResolveCallTarget(InvocationExpr c, boolean dispatch) {
|
||||
c = getRelevantLocatable() and
|
||||
result = resolveCallTarget(c)
|
||||
result = resolveCallTarget(c, dispatch)
|
||||
}
|
||||
|
||||
predicate debugConditionSatisfiesConstraint(
|
||||
|
||||
@@ -11,7 +11,14 @@ import TypeInference::Consistency
|
||||
|
||||
query predicate illFormedTypeMention(TypeMention tm) {
|
||||
Consistency::illFormedTypeMention(tm) and
|
||||
not tm instanceof PathTypeReprMention and // avoid overlap with `PathTypeMention`
|
||||
// avoid overlap with `PathTypeMention`
|
||||
not tm instanceof PathTypeReprMention and
|
||||
// known limitation for type mentions that would mention an escaping type parameter
|
||||
not tm =
|
||||
any(PathTypeMention ptm |
|
||||
exists(ptm.resolvePathTypeAt(TypePath::nil())) and
|
||||
not exists(ptm.resolveType())
|
||||
) and
|
||||
// Only include inconsistencies in the source, as we otherwise get
|
||||
// inconsistencies from library code in every project.
|
||||
tm.fromSource()
|
||||
|
||||
@@ -77,7 +77,19 @@ class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PathTypeMention extends TypeMention, Path { }
|
||||
abstract class PathTypeMention extends TypeMention, Path {
|
||||
abstract Type resolvePathTypeAt(TypePath typePath);
|
||||
|
||||
final override Type resolveTypeAt(TypePath typePath) {
|
||||
result = this.resolvePathTypeAt(typePath) and
|
||||
(
|
||||
not result instanceof TypeParameter
|
||||
or
|
||||
// Prevent type parameters from escaping their scope
|
||||
this = result.(TypeParameter).getDeclaringItem().getAChild*().getADescendant()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class AliasPathTypeMention extends PathTypeMention {
|
||||
TypeAlias resolved;
|
||||
@@ -94,7 +106,7 @@ class AliasPathTypeMention extends PathTypeMention {
|
||||
* Holds if this path resolved to a type alias with a rhs. that has the
|
||||
* resulting type at `typePath`.
|
||||
*/
|
||||
override Type resolveTypeAt(TypePath typePath) {
|
||||
override Type resolvePathTypeAt(TypePath typePath) {
|
||||
result = rhs.resolveTypeAt(typePath) and
|
||||
not result = pathGetTypeParameter(resolved, _)
|
||||
or
|
||||
@@ -275,7 +287,7 @@ class NonAliasPathTypeMention extends PathTypeMention {
|
||||
result = TAssociatedTypeTypeParameter(resolved)
|
||||
}
|
||||
|
||||
override Type resolveTypeAt(TypePath typePath) {
|
||||
override Type resolvePathTypeAt(TypePath typePath) {
|
||||
typePath.isEmpty() and
|
||||
result = this.resolveRootType()
|
||||
or
|
||||
@@ -307,7 +319,9 @@ class ImplSelfMention extends PathTypeMention {
|
||||
|
||||
ImplSelfMention() { this = impl.getASelfPath() }
|
||||
|
||||
override Type resolveTypeAt(TypePath typePath) { result = resolveImplSelfTypeAt(impl, typePath) }
|
||||
override Type resolvePathTypeAt(TypePath typePath) {
|
||||
result = resolveImplSelfTypeAt(impl, typePath)
|
||||
}
|
||||
}
|
||||
|
||||
class PathTypeReprMention extends TypeMention, PathTypeRepr {
|
||||
@@ -542,13 +556,18 @@ class NeverTypeReprMention extends TypeMention, NeverTypeRepr {
|
||||
}
|
||||
|
||||
class PtrTypeReprMention extends TypeMention instanceof PtrTypeRepr {
|
||||
private PtrType resolveRootType() {
|
||||
super.isConst() and result instanceof PtrConstType
|
||||
or
|
||||
super.isMut() and result instanceof PtrMutType
|
||||
}
|
||||
|
||||
override Type resolveTypeAt(TypePath path) {
|
||||
path.isEmpty() and
|
||||
result instanceof PtrType
|
||||
path.isEmpty() and result = this.resolveRootType()
|
||||
or
|
||||
exists(TypePath suffix |
|
||||
result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
|
||||
path = TypePath::cons(getPtrTypeParameter(), suffix)
|
||||
path = TypePath::cons(this.resolveRootType().getPositionalTypeParameter(0), suffix)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ private import codeql.rust.internal.TypeInference
|
||||
private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.internal.Type
|
||||
private import codeql.rust.internal.TypeMention
|
||||
private import codeql.rust.elements.Call
|
||||
|
||||
private newtype TFunctionPosition =
|
||||
TArgumentFunctionPosition(ArgumentPosition pos) or
|
||||
@@ -352,7 +351,7 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
|
||||
|
|
||||
rnk = 0
|
||||
or
|
||||
argsAreInstantiationsOfFromIndex(call, abs, f, rnk - 1)
|
||||
argsAreInstantiationsOfToIndex(call, abs, f, rnk - 1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -361,15 +360,15 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
|
||||
}
|
||||
}
|
||||
|
||||
private module ArgIsInstantiationOfFromIndex =
|
||||
private module ArgIsInstantiationOfToIndex =
|
||||
ArgIsInstantiationOf<CallAndPos, ArgIsInstantiationOfInput>;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argsAreInstantiationsOfFromIndex(
|
||||
private predicate argsAreInstantiationsOfToIndex(
|
||||
Input::Call call, ImplOrTraitItemNode i, Function f, int rnk
|
||||
) {
|
||||
exists(FunctionPosition pos |
|
||||
ArgIsInstantiationOfFromIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and
|
||||
ArgIsInstantiationOfToIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and
|
||||
call.hasTargetCand(i, f) and
|
||||
toCheckRanked(i, f, pos, rnk)
|
||||
)
|
||||
@@ -382,7 +381,7 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
|
||||
pragma[nomagic]
|
||||
predicate argsAreInstantiationsOf(Input::Call call, ImplOrTraitItemNode i, Function f) {
|
||||
exists(int rnk |
|
||||
argsAreInstantiationsOfFromIndex(call, i, f, rnk) and
|
||||
argsAreInstantiationsOfToIndex(call, i, f, rnk) and
|
||||
rnk = max(int r | toCheckRanked(i, f, _, r))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -100,9 +100,9 @@ module AccessAfterLifetime {
|
||||
a = b.getEnclosingBlock*()
|
||||
or
|
||||
// propagate through function calls
|
||||
exists(CallExprBase ce |
|
||||
mayEncloseOnStack(a, ce.getEnclosingBlock()) and
|
||||
ce.getStaticTarget() = b.getEnclosingCallable()
|
||||
exists(Call call |
|
||||
mayEncloseOnStack(a, call.getEnclosingBlock()) and
|
||||
call.getARuntimeTarget() = b.getEnclosingCallable()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ private import codeql.rust.dataflow.FlowSource
|
||||
private import codeql.rust.dataflow.FlowSink
|
||||
private import codeql.rust.Concepts
|
||||
private import codeql.rust.dataflow.internal.Node
|
||||
private import codeql.rust.security.Barriers as Barriers
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks and barriers for detecting accesses to
|
||||
@@ -59,4 +60,10 @@ module AccessInvalidPointer {
|
||||
private class ModelsAsDataSink extends Sink {
|
||||
ModelsAsDataSink() { sinkNode(this, "pointer-access") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A barrier for invalid pointer access vulnerabilities for values checked to
|
||||
* be non-`null`.
|
||||
*/
|
||||
private class NotNullCheckBarrier extends Barrier instanceof Barriers::NotNullCheckBarrier { }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Classes to represent barriers commonly used in dataflow and taint tracking
|
||||
* Classes to represent barriers commonly used in data flow and taint tracking
|
||||
* configurations.
|
||||
*/
|
||||
|
||||
@@ -7,36 +7,58 @@ 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.controlflow.ControlFlowGraph as Cfg
|
||||
private import codeql.rust.controlflow.CfgNodes as CfgNodes
|
||||
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
|
||||
|
||||
/**
|
||||
* A node whose type is a numeric or boolean type, which may be an appropriate
|
||||
* taint flow barrier for some queries.
|
||||
*/
|
||||
/** A node whose type is a numeric type. */
|
||||
class NumericTypeBarrier extends DataFlow::Node {
|
||||
NumericTypeBarrier() {
|
||||
exists(StructType t, Struct s |
|
||||
t = TypeInference::inferType(this.asExpr()) and
|
||||
s = t.getStruct()
|
||||
|
|
||||
s instanceof Builtins::NumericType or
|
||||
s instanceof Builtins::Bool
|
||||
)
|
||||
TypeInference::inferType(this.asExpr()).(StructType).getStruct() instanceof
|
||||
Builtins::NumericType
|
||||
}
|
||||
}
|
||||
|
||||
/** A node whose type is `bool`. */
|
||||
class BooleanTypeBarrier extends DataFlow::Node {
|
||||
BooleanTypeBarrier() {
|
||||
TypeInference::inferType(this.asExpr()).(StructType).getStruct() instanceof Builtins::Bool
|
||||
}
|
||||
}
|
||||
|
||||
/** A node whose type is an integral (integer). */
|
||||
class IntegralTypeBarrier extends DataFlow::Node {
|
||||
IntegralTypeBarrier() {
|
||||
TypeInference::inferType(this.asExpr()).(StructType).getStruct() instanceof
|
||||
Builtins::IntegralType
|
||||
}
|
||||
}
|
||||
|
||||
/** A node whose type is a fieldless enum. */
|
||||
class FieldlessEnumTypeBarrier extends DataFlow::Node {
|
||||
FieldlessEnumTypeBarrier() {
|
||||
TypeInference::inferType(this.asExpr()).(EnumType).getEnum().isFieldless()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node whose type is an integral (integer) or boolean type, which may be an
|
||||
* Holds if guard expression `g` having result `branch` indicates that the
|
||||
* sub-expression `e` is not null. For example when `ptr.is_null()` is
|
||||
* `false`, we have that `ptr` is not null.
|
||||
*/
|
||||
private predicate notNullCheck(AstNode g, Expr e, boolean branch) {
|
||||
exists(MethodCallExpr call |
|
||||
call.getStaticTarget().getName().getText() = "is_null" and
|
||||
g = call and
|
||||
e = call.getReceiver() and
|
||||
branch = false
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a value checked to be non-null. This may be an
|
||||
* appropriate taint flow barrier for some queries.
|
||||
*/
|
||||
class IntegralOrBooleanTypeBarrier extends DataFlow::Node {
|
||||
IntegralOrBooleanTypeBarrier() {
|
||||
exists(StructType t, Struct s |
|
||||
t = TypeInference::inferType(this.asExpr()) and
|
||||
s = t.getStruct()
|
||||
|
|
||||
s instanceof Builtins::IntegralType or
|
||||
s instanceof Builtins::Bool
|
||||
)
|
||||
}
|
||||
class NotNullCheckBarrier extends DataFlow::Node {
|
||||
NotNullCheckBarrier() { this = DataFlow::BarrierGuard<notNullCheck/3>::getABarrierNode() }
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user