Skip to content

Commit ca18005

Browse files
committed
Rust: Add some manual classes to CfgNodes.qll
1 parent c8736e8 commit ca18005

File tree

2 files changed

+197
-34
lines changed

2 files changed

+197
-34
lines changed

rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll

Lines changed: 165 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,54 +9,185 @@ private import internal.ControlFlowGraphImpl as CfgImpl
99
private import internal.CfgNodes
1010
import Nodes
1111

12-
/** A CFG node that corresponds to an element in the AST. */
13-
class AstCfgNode extends CfgNode {
14-
AstNode node;
12+
class AstCfgNode = CfgImpl::AstCfgNode;
1513

16-
AstCfgNode() { node = this.getAstNode() }
14+
class ExitCfgNode = CfgImpl::ExitNode;
1715

18-
/** Gets the underlying ast node. */
19-
AstNode getAstNode() { result = node }
20-
}
16+
/**
17+
* An assignment expression, for example
18+
*
19+
* ```rust
20+
* x = y;
21+
* ```
22+
*/
23+
final class AssignmentExprCfgNode extends BinaryExprCfgNode {
24+
AssignmentExpr a;
2125

22-
/** A CFG node that corresponds to a parameter in the AST. */
23-
class ParamCfgNode extends AstCfgNode {
24-
override Param node;
26+
AssignmentExprCfgNode() { a = this.getBinaryExpr() }
2527

26-
/** Gets the underlying parameter. */
27-
Param getParam() { result = node }
28+
/** Gets the underlying `AssignmentExpr`. */
29+
AssignmentExpr getAssignmentExpr() { result = a }
2830
}
2931

30-
/** A CFG node that corresponds to a parameter in the AST. */
31-
class PatCfgNode extends AstCfgNode {
32-
override Pat node;
32+
/**
33+
* A match expression. For example:
34+
* ```rust
35+
* match x {
36+
* Option::Some(y) => y,
37+
* Option::None => 0,
38+
* }
39+
* ```
40+
* ```rust
41+
* match x {
42+
* Some(y) if y != 0 => 1 / y,
43+
* _ => 0,
44+
* }
45+
* ```
46+
*/
47+
final class MatchExprCfgNode extends Nodes::MatchExprCfgNode {
48+
private MatchExpr node;
3349

34-
/** Gets the underlying pattern. */
35-
Pat getPat() { result = node }
36-
}
50+
MatchExprCfgNode() { node = this.getMatchExpr() }
51+
52+
/**
53+
* Gets the pattern of the `i`th match arm, if it exists.
54+
*/
55+
PatCfgNode getArmPat(int i) {
56+
any(ChildMapping mapping).hasCfgChild(node, node.getArm(i).getPat(), this, result)
57+
}
3758

38-
/** A CFG node that corresponds to an expression in the AST. */
39-
class ExprCfgNode extends AstCfgNode {
40-
override Expr node;
59+
/**
60+
* Gets the guard of the `i`th match arm, if it exists.
61+
*/
62+
ExprCfgNode getArmGuard(int i) {
63+
any(ChildMapping mapping)
64+
.hasCfgChild(node, node.getArm(i).getGuard().getCondition(), this, result)
65+
}
4166

42-
/** Gets the underlying expression. */
43-
Expr getExpr() { result = node }
67+
/**
68+
* Gets the expression of the `i`th match arm, if it exists.
69+
*/
70+
ExprCfgNode getArmExpr(int i) {
71+
any(ChildMapping mapping).hasCfgChild(node, node.getArm(i).getExpr(), this, result)
72+
}
4473
}
4574

46-
/** A CFG node that corresponds to a call in the AST. */
47-
class CallExprCfgNode extends ExprCfgNode {
48-
override CallExpr node;
75+
/**
76+
* A block expression. For example:
77+
* ```rust
78+
* {
79+
* let x = 42;
80+
* }
81+
* ```
82+
* ```rust
83+
* 'label: {
84+
* let x = 42;
85+
* x
86+
* }
87+
* ```
88+
*/
89+
final class BlockExprCfgNode extends Nodes::BlockExprCfgNode {
90+
private BlockExprChildMapping node;
4991

50-
/** Gets the underlying `CallExpr`. */
51-
CallExpr getCallExpr() { result = node }
92+
BlockExprCfgNode() { node = this.getAstNode() }
93+
94+
/**
95+
* Gets the tail expression of this block, if it exists.
96+
*/
97+
ExprCfgNode getTailExpr() {
98+
any(ChildMapping mapping).hasCfgChild(node, node.getStmtList().getTailExpr(), this, result)
99+
}
100+
}
101+
102+
/**
103+
* A break expression. For example:
104+
* ```rust
105+
* loop {
106+
* if not_ready() {
107+
* break;
108+
* }
109+
* }
110+
* ```
111+
* ```rust
112+
* let x = 'label: loop {
113+
* if done() {
114+
* break 'label 42;
115+
* }
116+
* };
117+
* ```
118+
* ```rust
119+
* let x = 'label: {
120+
* if exit() {
121+
* break 'label 42;
122+
* }
123+
* 0;
124+
* };
125+
* ```
126+
*/
127+
final class BreakExprCfgNode extends Nodes::BreakExprCfgNode {
128+
/**
129+
* Gets the target of this `break` expression.
130+
*
131+
* The target is either a `LoopExpr`, a `ForExpr`, a `WhileExpr`, or a
132+
* `BlockExpr`.
133+
*/
134+
ExprCfgNode getTarget() {
135+
any(ChildMapping mapping)
136+
.hasCfgChild(this.getBreakExpr().getTarget(), this.getBreakExpr(), result, this)
137+
}
52138
}
53139

54-
/** A CFG node that corresponds to a call in the AST. */
55-
class MethodCallExprCfgNode extends ExprCfgNode {
56-
override MethodCallExpr node;
140+
/**
141+
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
142+
*/
143+
final class CallExprBaseCfgNode extends Nodes::CallExprBaseCfgNode {
144+
private CallExprBaseChildMapping node;
57145

58-
/** Gets the underlying `MethodCallExpr`. */
59-
MethodCallExpr getMethodCallExpr() { result = node }
146+
CallExprBaseCfgNode() { node = this.getAstNode() }
147+
148+
/** Gets the `i`th argument of this call. */
149+
ExprCfgNode getArgument(int i) {
150+
any(ChildMapping mapping).hasCfgChild(node, node.getArgList().getArg(i), this, result)
151+
}
60152
}
61153

62-
final class ExitCfgNode = CfgImpl::ExitNode;
154+
/**
155+
* A method call expression. For example:
156+
* ```rust
157+
* x.foo(42);
158+
* x.foo::<u32, u64>(42);
159+
* ```
160+
*/
161+
final class MethodCallExprCfgNode extends CallExprBaseCfgNode, Nodes::MethodCallExprCfgNode { }
162+
163+
/**
164+
* A function call expression. For example:
165+
* ```rust
166+
* foo(42);
167+
* foo::<u32, u64>(42);
168+
* foo[0](42);
169+
* foo(1) = 4;
170+
* ```
171+
*/
172+
final class CallExprCfgNode extends CallExprBaseCfgNode, Nodes::CallExprCfgNode { }
173+
174+
/**
175+
* A record expression. For example:
176+
* ```rust
177+
* let first = Foo { a: 1, b: 2 };
178+
* let second = Foo { a: 2, ..first };
179+
* Foo { a: 1, b: 2 }[2] = 10;
180+
* Foo { .. } = second;
181+
* ```
182+
*/
183+
final class RecordExprCfgNode extends Nodes::RecordExprCfgNode {
184+
private RecordExprChildMapping node;
185+
186+
RecordExprCfgNode() { node = this.getRecordExpr() }
187+
188+
/** Gets the `i`th record expression. */
189+
ExprCfgNode getExpr(int i) {
190+
any(ChildMapping mapping)
191+
.hasCfgChild(node, node.getRecordExprFieldList().getField(i).getExpr(), this, result)
192+
}
193+
}

rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,38 @@ private module CfgNodesInput implements InputSig<Location> {
4040

4141
import MakeCfgNodes<Location, CfgNodesInput>
4242

43+
class MatchExprChildMapping extends ParentAstNode, MatchExpr {
44+
override predicate relevantChild(AstNode child) {
45+
child = this.getAnArm().getPat()
46+
or
47+
child = this.getAnArm().getGuard().getCondition()
48+
or
49+
child = this.getAnArm().getExpr()
50+
}
51+
}
52+
53+
class BlockExprChildMapping extends ParentAstNode, BlockExpr {
54+
override predicate relevantChild(AstNode child) { child = this.getStmtList().getTailExpr() }
55+
}
56+
57+
class BreakExprTargetChildMapping extends ParentAstNode, Expr {
58+
override predicate relevantChild(AstNode child) { child.(BreakExpr).getTarget() = this }
59+
}
60+
61+
class CallExprBaseChildMapping extends ParentAstNode, CallExprBase {
62+
override predicate relevantChild(AstNode child) { child = this.getArgList().getAnArg() }
63+
}
64+
65+
class RecordExprChildMapping extends ParentAstNode, RecordExpr {
66+
override predicate relevantChild(AstNode child) {
67+
child = this.getRecordExprFieldList().getAField().getExpr()
68+
}
69+
}
70+
71+
class FormatArgsExprChildMapping extends ParentAstNode, CfgImpl::ExprTrees::FormatArgsExprTree {
72+
override predicate relevantChild(AstNode child) { child = this.getChildNode(_) }
73+
}
74+
4375
private class ChildMappingImpl extends ChildMapping {
4476
/** Gets a CFG node for `child`, where `child` is a relevant child node of `parent`. */
4577
private CfgNode getRelevantChildCfgNode(AstNode parent, AstNode child) {

0 commit comments

Comments
 (0)