mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Rust: Use nodes from CfgNodes.qll in DataFlowImpl.qll
This commit is contained in:
@@ -9,6 +9,7 @@ module Ssa {
|
||||
private import rust
|
||||
private import codeql.rust.controlflow.BasicBlocks
|
||||
private import codeql.rust.controlflow.ControlFlowGraph
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as CfgImpl
|
||||
private import internal.SsaImpl as SsaImpl
|
||||
|
||||
@@ -221,11 +222,11 @@ module Ssa {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
predicate assigns(CfgNode value) {
|
||||
exists(AssignmentExpr ae, BasicBlock bb, int i |
|
||||
predicate assigns(ExprCfgNode value) {
|
||||
exists(AssignmentExprCfgNode ae, BasicBlock bb, int i |
|
||||
this.definesAt(_, bb, i) and
|
||||
ae.getLhs() = bb.getNode(i).getAstNode() and
|
||||
value.getAstNode() = ae.getRhs()
|
||||
ae.getLhs() = bb.getNode(i) and
|
||||
value = ae.getRhs()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
|
||||
MethodCallExprCfgNode asMethodCallExprCfgNode() { this = TMethodCall(result) }
|
||||
|
||||
ExprCfgNode asExprCfgNode() {
|
||||
CallExprBaseCfgNode asExprCfgNode() {
|
||||
result = this.asCallExprCfgNode() or result = this.asMethodCallExprCfgNode()
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ module Node {
|
||||
/**
|
||||
* Gets the expression that corresponds to this node, if any.
|
||||
*/
|
||||
Expr asExpr() { none() }
|
||||
ExprCfgNode asExpr() { none() }
|
||||
|
||||
/** Gets the enclosing callable. */
|
||||
DataFlowCallable getEnclosingCallable() { result = TCfgScope(this.getCfgScope()) }
|
||||
@@ -115,13 +115,13 @@ module Node {
|
||||
abstract class AstCfgFlowNode extends Node {
|
||||
AstCfgNode n;
|
||||
|
||||
override CfgNode getCfgNode() { result = n }
|
||||
final override CfgNode getCfgNode() { result = n }
|
||||
|
||||
override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() }
|
||||
final override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() }
|
||||
|
||||
override Location getLocation() { result = n.getAstNode().getLocation() }
|
||||
final override Location getLocation() { result = n.getAstNode().getLocation() }
|
||||
|
||||
override string toString() { result = n.getAstNode().toString() }
|
||||
final override string toString() { result = n.getAstNode().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,7 +137,7 @@ module Node {
|
||||
|
||||
ExprNode() { this = TExprNode(n) }
|
||||
|
||||
override Expr asExpr() { result = n.getExpr() }
|
||||
override ExprCfgNode asExpr() { result = n }
|
||||
}
|
||||
|
||||
final class PatNode extends AstCfgFlowNode, TPatNode {
|
||||
@@ -159,7 +159,7 @@ module Node {
|
||||
ParameterNode() { this = TParameterNode(n) }
|
||||
|
||||
/** Gets the parameter in the AST that this node corresponds to. */
|
||||
Param getParameter() { result = n.getParam() }
|
||||
ParamCfgNode getParameter() { result = n }
|
||||
}
|
||||
|
||||
final class ArgumentNode = NaNode;
|
||||
@@ -197,7 +197,7 @@ module Node {
|
||||
}
|
||||
|
||||
final private class ExprOutNode extends ExprNode, OutNode {
|
||||
ExprOutNode() { this.asExpr() instanceof CallExpr }
|
||||
ExprOutNode() { this.asExpr() instanceof CallExprCfgNode }
|
||||
|
||||
/** Gets the underlying call CFG node that includes this out node. */
|
||||
override DataFlowCall getCall() { result.asExprCfgNode() = this.getCfgNode() }
|
||||
@@ -228,13 +228,13 @@ final class Node = Node::Node;
|
||||
module SsaFlow {
|
||||
private module Impl = SsaImpl::DataFlowIntegration;
|
||||
|
||||
private Node::ParameterNode toParameterNode(Param p) { result.getParameter() = p }
|
||||
private Node::ParameterNode toParameterNode(ParamCfgNode p) { result.getParameter() = p }
|
||||
|
||||
/** Converts a control flow node into an SSA control flow node. */
|
||||
Impl::Node asNode(Node n) {
|
||||
n = TSsaNode(result)
|
||||
or
|
||||
result.(Impl::ExprNode).getExpr() = n.(Node::ExprNode).getCfgNode()
|
||||
result.(Impl::ExprNode).getExpr() = n.asExpr()
|
||||
or
|
||||
n = toParameterNode(result.(Impl::ParameterNode).getParameter())
|
||||
}
|
||||
@@ -248,29 +248,18 @@ module SsaFlow {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds for expressions `e` that evaluate to the value of any last (in
|
||||
* evaluation order) subexpressions within it. E.g., expressions that propagate
|
||||
* a values from a subexpression.
|
||||
*
|
||||
* For instance, the predicate holds for if expressions as `if b { e1 } else {
|
||||
* e2 }` evalates to the value of one of the subexpressions `e1` or `e2`.
|
||||
*/
|
||||
private predicate propagatesValue(Expr e) {
|
||||
e instanceof IfExpr or
|
||||
e instanceof LoopExpr or
|
||||
e instanceof ReturnExpr or
|
||||
e instanceof BreakExpr or
|
||||
e.(BlockExpr).getStmtList().hasTailExpr() or
|
||||
e instanceof MatchExpr
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that may execute last in `n`, and which, when it executes last,
|
||||
* will be the value of `n`.
|
||||
*/
|
||||
private ExprCfgNode getALastEvalNode(ExprCfgNode n) {
|
||||
propagatesValue(n.getExpr()) and result.getASuccessor() = n
|
||||
private ExprCfgNode getALastEvalNode(ExprCfgNode e) {
|
||||
e = any(IfExprCfgNode n | result = [n.getThen(), n.getElse()]) or
|
||||
result = e.(LoopExprCfgNode).getLoopBody() or
|
||||
result = e.(ReturnExprCfgNode).getExpr() or
|
||||
result = e.(BreakExprCfgNode).getExpr() or
|
||||
result = e.(BlockExprCfgNode).getTailExpr() or
|
||||
result = e.(MatchExprCfgNode).getArmExpr(_) or
|
||||
result.(BreakExprCfgNode).getTarget() = e
|
||||
}
|
||||
|
||||
module LocalFlow {
|
||||
@@ -278,9 +267,9 @@ module LocalFlow {
|
||||
predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
|
||||
nodeFrom.getCfgNode() = getALastEvalNode(nodeTo.getCfgNode())
|
||||
or
|
||||
exists(LetStmt s |
|
||||
nodeFrom.getCfgNode().getAstNode() = s.getInitializer() and
|
||||
nodeTo.getCfgNode().getAstNode() = s.getPat()
|
||||
exists(LetStmtCfgNode s |
|
||||
nodeFrom.getCfgNode() = s.getInitializer() and
|
||||
nodeTo.getCfgNode() = s.getPat()
|
||||
)
|
||||
or
|
||||
// An edge from a pattern/expression to its corresponding SSA definition.
|
||||
@@ -288,6 +277,11 @@ module LocalFlow {
|
||||
nodeTo.(Node::SsaNode).getDefinitionExt().(Ssa::WriteDefinition).getControlFlowNode()
|
||||
or
|
||||
SsaFlow::localFlowStep(_, nodeFrom, nodeTo, _)
|
||||
or
|
||||
exists(AssignmentExprCfgNode a |
|
||||
a.getRhs() = nodeFrom.getCfgNode() and
|
||||
a.getLhs() = nodeTo.getCfgNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +323,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
class DataFlowExpr = ExprCfgNode;
|
||||
|
||||
/** Gets the node corresponding to `e`. */
|
||||
Node exprNode(DataFlowExpr e) { result.getCfgNode() = e }
|
||||
Node exprNode(DataFlowExpr e) { result.asExpr() = e }
|
||||
|
||||
final class DataFlowCall = DataFlowCallAlias;
|
||||
|
||||
|
||||
@@ -474,14 +474,14 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
|
||||
|
||||
/** Holds if SSA definition `def` assigns `value` to the underlying variable. */
|
||||
predicate ssaDefAssigns(WriteDefinition def, Expr value) {
|
||||
exists(BasicBlock bb, int i | def.definesAt(_, bb, i) and value = bb.getNode(i))
|
||||
none() // handled in `DataFlowImpl.qll` instead
|
||||
}
|
||||
|
||||
class Parameter = Param;
|
||||
class Parameter = CfgNodes::ParamCfgNode;
|
||||
|
||||
/** Holds if SSA definition `def` initializes parameter `p` at function entry. */
|
||||
predicate ssaDefInitializesParam(WriteDefinition def, Parameter p) {
|
||||
exists(BasicBlock bb, int i | bb.getNode(i).getAstNode() = p and def.definesAt(_, bb, i))
|
||||
none() // handled in `DataFlowImpl.qll` instead
|
||||
}
|
||||
|
||||
class Guard extends CfgNodes::AstCfgNode {
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
| main.rs:51:17:51:17 | 1 | main.rs:51:9:51:13 | i |
|
||||
| main.rs:53:5:53:5 | [SSA] i | main.rs:54:10:54:10 | i |
|
||||
| main.rs:53:5:53:5 | i | main.rs:53:5:53:5 | [SSA] i |
|
||||
| main.rs:53:9:53:17 | CallExpr | main.rs:53:5:53:5 | i |
|
||||
| main.rs:61:9:61:9 | [SSA] i | main.rs:62:11:62:11 | i |
|
||||
| main.rs:61:9:61:9 | i | main.rs:61:9:61:9 | [SSA] i |
|
||||
| main.rs:61:13:61:31 | CallExpr | main.rs:61:9:61:9 | i |
|
||||
@@ -93,7 +94,6 @@
|
||||
| main.rs:122:9:122:9 | [SSA] a | main.rs:128:5:128:5 | a |
|
||||
| main.rs:122:9:122:9 | a | main.rs:122:9:122:9 | [SSA] a |
|
||||
| main.rs:122:13:127:5 | BlockExpr | main.rs:122:9:122:9 | a |
|
||||
| main.rs:123:12:123:12 | b | main.rs:123:9:125:9 | IfExpr |
|
||||
| main.rs:124:13:124:26 | BreakExpr | main.rs:122:13:127:5 | BlockExpr |
|
||||
| main.rs:124:26:124:26 | 1 | main.rs:124:13:124:26 | BreakExpr |
|
||||
| main.rs:126:9:126:9 | 2 | main.rs:122:13:127:5 | BlockExpr |
|
||||
@@ -103,7 +103,8 @@
|
||||
| main.rs:132:9:132:9 | [SSA] a | main.rs:138:5:138:5 | a |
|
||||
| main.rs:132:9:132:9 | a | main.rs:132:9:132:9 | [SSA] a |
|
||||
| main.rs:132:13:137:5 | BlockExpr | main.rs:132:9:132:9 | a |
|
||||
| main.rs:133:12:133:12 | b | main.rs:133:9:135:9 | IfExpr |
|
||||
| main.rs:134:13:134:26 | BreakExpr | main.rs:132:13:137:5 | BlockExpr |
|
||||
| main.rs:134:26:134:26 | 1 | main.rs:134:13:134:26 | BreakExpr |
|
||||
| main.rs:136:9:136:22 | BreakExpr | main.rs:132:13:137:5 | BlockExpr |
|
||||
| main.rs:136:22:136:22 | 2 | main.rs:136:9:136:22 | BreakExpr |
|
||||
| main.rs:138:5:138:5 | a | main.rs:131:38:139:1 | BlockExpr |
|
||||
|
||||
@@ -4,6 +4,7 @@ edges
|
||||
| main.rs:24:13:24:21 | CallExpr : unit | main.rs:27:10:27:10 | c | provenance | |
|
||||
| main.rs:31:13:31:21 | CallExpr : unit | main.rs:36:10:36:10 | b | provenance | |
|
||||
| main.rs:45:15:45:23 | CallExpr : unit | main.rs:47:10:47:10 | b | provenance | |
|
||||
| main.rs:53:9:53:17 | CallExpr : unit | main.rs:54:10:54:10 | i | provenance | |
|
||||
nodes
|
||||
| main.rs:15:10:15:18 | CallExpr | semmle.label | CallExpr |
|
||||
| main.rs:19:13:19:21 | CallExpr : unit | semmle.label | CallExpr : unit |
|
||||
@@ -14,6 +15,8 @@ nodes
|
||||
| main.rs:36:10:36:10 | b | semmle.label | b |
|
||||
| main.rs:45:15:45:23 | CallExpr : unit | semmle.label | CallExpr : unit |
|
||||
| main.rs:47:10:47:10 | b | semmle.label | b |
|
||||
| main.rs:53:9:53:17 | CallExpr : unit | semmle.label | CallExpr : unit |
|
||||
| main.rs:54:10:54:10 | i | semmle.label | i |
|
||||
subpaths
|
||||
testFailures
|
||||
#select
|
||||
@@ -22,3 +25,4 @@ testFailures
|
||||
| main.rs:27:10:27:10 | c | main.rs:24:13:24:21 | CallExpr : unit | main.rs:27:10:27:10 | c | $@ | main.rs:24:13:24:21 | CallExpr : unit | CallExpr : unit |
|
||||
| main.rs:36:10:36:10 | b | main.rs:31:13:31:21 | CallExpr : unit | main.rs:36:10:36:10 | b | $@ | main.rs:31:13:31:21 | CallExpr : unit | CallExpr : unit |
|
||||
| main.rs:47:10:47:10 | b | main.rs:45:15:45:23 | CallExpr : unit | main.rs:47:10:47:10 | b | $@ | main.rs:45:15:45:23 | CallExpr : unit | CallExpr : unit |
|
||||
| main.rs:54:10:54:10 | i | main.rs:53:9:53:17 | CallExpr : unit | main.rs:54:10:54:10 | i | $@ | main.rs:53:9:53:17 | CallExpr : unit | CallExpr : unit |
|
||||
|
||||
@@ -51,7 +51,7 @@ fn assignment() {
|
||||
let mut i = 1;
|
||||
sink(i);
|
||||
i = source(2);
|
||||
sink(i); // $ MISSING: hasValueFlow=2
|
||||
sink(i); // $ hasValueFlow=2
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -5,26 +5,27 @@
|
||||
|
||||
import rust
|
||||
private import codeql.dataflow.test.InlineFlowTest
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.dataflow.internal.DataFlowImpl
|
||||
private import codeql.rust.dataflow.internal.TaintTrackingImpl
|
||||
private import internal.InlineExpectationsTestImpl as InlineExpectationsTestImpl
|
||||
|
||||
// Holds if the target expression of `call` is a path and the string representation of the path is `name`.
|
||||
private predicate callTargetName(CallExpr call, string name) {
|
||||
call.getExpr().(PathExpr).toString() = name
|
||||
private predicate callTargetName(CallExprCfgNode call, string name) {
|
||||
call.getExpr().(PathExprCfgNode).toString() = name
|
||||
}
|
||||
|
||||
private module FlowTestImpl implements InputSig<Location, RustDataFlow> {
|
||||
predicate defaultSource(DataFlow::Node source) { callTargetName(source.asExpr(), "source") }
|
||||
|
||||
predicate defaultSink(DataFlow::Node sink) {
|
||||
any(CallExpr call | callTargetName(call, "sink")).getArgList().getAnArg() = sink.asExpr()
|
||||
any(CallExprCfgNode call | callTargetName(call, "sink")).getArgument(_) = sink.asExpr()
|
||||
}
|
||||
|
||||
private string getSourceArgString(DataFlow::Node src) {
|
||||
defaultSource(src) and
|
||||
result = src.asExpr().(CallExpr).getArgList().getArg(0).toString()
|
||||
result = src.asExpr().(CallExprCfgNode).getArgument(0).toString()
|
||||
}
|
||||
|
||||
bindingset[src, sink]
|
||||
|
||||
Reference in New Issue
Block a user