mirror of
https://github.com/github/codeql.git
synced 2026-04-23 07:45:17 +02:00
Rust: Use Call in data flow
This commit is contained in:
@@ -8,6 +8,7 @@ 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.internal.PathResolution
|
||||
@@ -55,11 +56,7 @@ final class DataFlowCallable extends TDataFlowCallable {
|
||||
|
||||
final class DataFlowCall extends TDataFlowCall {
|
||||
/** Gets the underlying call in the CFG, if any. */
|
||||
CallExprCfgNode asCallExprCfgNode() { result = this.asCallBaseExprCfgNode() }
|
||||
|
||||
MethodCallExprCfgNode asMethodCallExprCfgNode() { result = this.asCallBaseExprCfgNode() }
|
||||
|
||||
CallExprBaseCfgNode asCallBaseExprCfgNode() { this = TCall(result) }
|
||||
CallCfgNode asCallCfgNode() { this = TCall(result) }
|
||||
|
||||
predicate isSummaryCall(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
@@ -68,7 +65,7 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
}
|
||||
|
||||
DataFlowCallable getEnclosingCallable() {
|
||||
result = TCfgScope(this.asCallBaseExprCfgNode().getExpr().getEnclosingCfgScope())
|
||||
result = TCfgScope(this.asCallCfgNode().getExpr().getEnclosingCfgScope())
|
||||
or
|
||||
exists(FlowSummaryImpl::Public::SummarizedCallable c |
|
||||
this.isSummaryCall(c, _) and
|
||||
@@ -77,7 +74,7 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
}
|
||||
|
||||
string toString() {
|
||||
result = this.asCallBaseExprCfgNode().toString()
|
||||
result = this.asCallCfgNode().toString()
|
||||
or
|
||||
exists(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
@@ -87,7 +84,7 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
)
|
||||
}
|
||||
|
||||
Location getLocation() { result = this.asCallBaseExprCfgNode().getLocation() }
|
||||
Location getLocation() { result = this.asCallCfgNode().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,38 +132,23 @@ final class ParameterPosition extends TParameterPosition {
|
||||
*/
|
||||
final class ArgumentPosition extends ParameterPosition {
|
||||
/** Gets the argument of `call` at this position, if any. */
|
||||
Expr getArgument(CallExprBase call) {
|
||||
result = call.getArgList().getArg(this.getPosition())
|
||||
Expr getArgument(Call call) {
|
||||
result = call.getArgument(this.getPosition())
|
||||
or
|
||||
this.isSelf() and
|
||||
result = call.(MethodCallExpr).getReceiver()
|
||||
result = call.getReceiver() and this.isSelf()
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `call` invokes a qualified path that resolves to a method. */
|
||||
private predicate callToMethod(CallExpr call) {
|
||||
exists(Path path |
|
||||
path = call.getFunction().(PathExpr).getPath() and
|
||||
path.hasQualifier() and
|
||||
resolvePath(path).(Function).getParamList().hasSelfParam()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(ExprCfgNode arg, CallExprBaseCfgNode call, ParameterPosition pos) {
|
||||
if callToMethod(call.(CallExprCfgNode).getCallExpr())
|
||||
then
|
||||
// The first argument is for the `self` parameter
|
||||
arg = call.getArgument(0) and pos.isSelf()
|
||||
or
|
||||
// Succeeding arguments are shifted left
|
||||
arg = call.getArgument(pos.getPosition() + 1)
|
||||
else arg = call.getArgument(pos.getPosition())
|
||||
predicate isArgumentForCall(ExprCfgNode arg, CallCfgNode call, ParameterPosition pos) {
|
||||
call.getArgument(pos.getPosition()) = arg
|
||||
or
|
||||
call.getReceiver() = arg and pos.isSelf() and not call.getCall().receiverImplicitlyBorrowed()
|
||||
}
|
||||
|
||||
/** Provides logic related to SSA. */
|
||||
@@ -419,9 +401,9 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
/** Gets a viable implementation of the target of the given `Call`. */
|
||||
DataFlowCallable viableCallable(DataFlowCall call) {
|
||||
result.asCfgScope() = call.asCallBaseExprCfgNode().getCallExprBase().getStaticTarget()
|
||||
result.asCfgScope() = call.asCallCfgNode().getCall().getStaticTarget()
|
||||
or
|
||||
result.asLibraryCallable().getACall() = call.asCallBaseExprCfgNode().getCallExprBase()
|
||||
result.asLibraryCallable().getACall() = call.asCallCfgNode().getCall()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -812,7 +794,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
*/
|
||||
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
(
|
||||
receiver.asExpr() = call.asCallExprCfgNode().getFunction() and
|
||||
receiver.asExpr() = call.asCallCfgNode().(CallExprCfgNode).getFunction() and
|
||||
// All calls to complex expressions and local variable accesses are lambda call.
|
||||
exists(Expr f | f = receiver.asExpr().getExpr() |
|
||||
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
|
||||
@@ -976,7 +958,7 @@ private module Cached {
|
||||
|
||||
cached
|
||||
newtype TDataFlowCall =
|
||||
TCall(CallExprBaseCfgNode c) { Stages::DataFlowStage::ref() } or
|
||||
TCall(CallCfgNode c) { Stages::DataFlowStage::ref() } or
|
||||
TSummaryCall(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
) {
|
||||
|
||||
@@ -153,7 +153,7 @@ private import Make<Location, RustDataFlow, Input> as Impl
|
||||
|
||||
private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
DataFlowCall getACall(Public::SummarizedCallable sc) {
|
||||
result.asCallBaseExprCfgNode().getCallExprBase() = sc.(LibraryCallable).getACall()
|
||||
result.asCallCfgNode().getCall() = sc.(LibraryCallable).getACall()
|
||||
}
|
||||
|
||||
RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
|
||||
|
||||
@@ -224,13 +224,13 @@ abstract class ArgumentNode extends Node {
|
||||
}
|
||||
|
||||
final class ExprArgumentNode extends ArgumentNode, ExprNode {
|
||||
private CallExprBaseCfgNode call_;
|
||||
private CallCfgNode call_;
|
||||
private RustDataFlow::ArgumentPosition pos_;
|
||||
|
||||
ExprArgumentNode() { isArgumentForCall(n, call_, pos_) }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call.asCallBaseExprCfgNode() = call_ and pos = pos_
|
||||
call.asCallCfgNode() = call_ and pos = pos_
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ final class ExprArgumentNode extends ArgumentNode, ExprNode {
|
||||
* has taken place.
|
||||
*/
|
||||
final class ReceiverNode extends ArgumentNode, TReceiverNode {
|
||||
private MethodCallExprCfgNode n;
|
||||
private CallCfgNode n;
|
||||
|
||||
ReceiverNode() { this = TReceiverNode(n, false) }
|
||||
|
||||
@@ -248,7 +248,7 @@ final class ReceiverNode extends ArgumentNode, TReceiverNode {
|
||||
MethodCallExprCfgNode getMethodCall() { result = n }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call.asMethodCallExprCfgNode() = n and pos = TSelfParameterPosition()
|
||||
call.asCallCfgNode() = n and pos = TSelfParameterPosition()
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() }
|
||||
@@ -281,7 +281,7 @@ final class ClosureArgumentNode extends ArgumentNode, ExprNode {
|
||||
ClosureArgumentNode() { lambdaCallExpr(call_, _, this.asExpr()) }
|
||||
|
||||
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
|
||||
call.asCallExprCfgNode() = call_ and
|
||||
call.asCallCfgNode() = call_ and
|
||||
pos.isClosureSelf()
|
||||
}
|
||||
}
|
||||
@@ -330,11 +330,11 @@ abstract class OutNode extends Node {
|
||||
}
|
||||
|
||||
final private class ExprOutNode extends ExprNode, OutNode {
|
||||
ExprOutNode() { this.asExpr() instanceof CallExprBaseCfgNode }
|
||||
ExprOutNode() { this.asExpr() instanceof CallCfgNode }
|
||||
|
||||
/** Gets the underlying call CFG node that includes this out node. */
|
||||
override DataFlowCall getCall(ReturnKind kind) {
|
||||
result.asCallBaseExprCfgNode() = this.getCfgNode() and
|
||||
result.asCallCfgNode() = this.getCfgNode() and
|
||||
kind = TNormalReturnKind()
|
||||
}
|
||||
}
|
||||
@@ -404,7 +404,7 @@ final class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
|
||||
}
|
||||
|
||||
final class ReceiverPostUpdateNode extends PostUpdateNode, TReceiverNode {
|
||||
private MethodCallExprCfgNode n;
|
||||
private CallCfgNode n;
|
||||
|
||||
ReceiverPostUpdateNode() { this = TReceiverNode(n, true) }
|
||||
|
||||
@@ -467,11 +467,12 @@ newtype TNode =
|
||||
any(FieldExprCfgNode access).getContainer(), //
|
||||
any(TryExprCfgNode try).getExpr(), //
|
||||
any(PrefixExprCfgNode pe | pe.getOperatorName() = "*").getExpr(), //
|
||||
any(AwaitExprCfgNode a).getExpr(), any(MethodCallExprCfgNode mc).getReceiver(), //
|
||||
any(AwaitExprCfgNode a).getExpr(), //
|
||||
any(MethodCallExprCfgNode mc).getReceiver(), //
|
||||
getPostUpdateReverseStep(any(PostUpdateNode n).getPreUpdateNode().asExpr(), _)
|
||||
]
|
||||
} or
|
||||
TReceiverNode(MethodCallExprCfgNode mc, Boolean isPost) or
|
||||
TReceiverNode(CallCfgNode mc, Boolean isPost) { mc.getCall().receiverImplicitlyBorrowed() } or
|
||||
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
|
||||
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
|
||||
TClosureSelfReferenceNode(CfgScope c) { lambdaCreationExpr(c, _) } or
|
||||
|
||||
@@ -85,6 +85,14 @@ edges
|
||||
| main.rs:175:9:175:35 | MyInt {...} [MyInt] | main.rs:173:42:176:5 | { ... } [MyInt] | provenance | |
|
||||
| main.rs:175:24:175:27 | self [MyInt] | main.rs:175:24:175:33 | self.value | provenance | |
|
||||
| main.rs:175:24:175:33 | self.value | main.rs:175:9:175:35 | MyInt {...} [MyInt] | provenance | |
|
||||
| main.rs:195:9:195:9 | a [MyInt] | main.rs:197:13:197:13 | a [MyInt] | provenance | |
|
||||
| main.rs:195:13:195:38 | MyInt {...} [MyInt] | main.rs:195:9:195:9 | a [MyInt] | provenance | |
|
||||
| main.rs:195:28:195:36 | source(...) | main.rs:195:13:195:38 | MyInt {...} [MyInt] | provenance | |
|
||||
| main.rs:197:9:197:9 | c [MyInt] | main.rs:198:10:198:10 | c [MyInt] | provenance | |
|
||||
| main.rs:197:13:197:13 | a [MyInt] | main.rs:173:12:173:15 | SelfParam [MyInt] | provenance | |
|
||||
| main.rs:197:13:197:13 | a [MyInt] | main.rs:197:13:197:17 | ... + ... [MyInt] | provenance | |
|
||||
| main.rs:197:13:197:17 | ... + ... [MyInt] | main.rs:197:9:197:9 | c [MyInt] | provenance | |
|
||||
| main.rs:198:10:198:10 | c [MyInt] | main.rs:198:10:198:16 | c.value | provenance | |
|
||||
| main.rs:205:9:205:9 | a [MyInt] | main.rs:173:12:173:15 | SelfParam [MyInt] | provenance | |
|
||||
| main.rs:205:9:205:9 | a [MyInt] | main.rs:207:13:207:20 | a.add(...) [MyInt] | provenance | |
|
||||
| main.rs:205:13:205:38 | MyInt {...} [MyInt] | main.rs:205:9:205:9 | a [MyInt] | provenance | |
|
||||
@@ -213,6 +221,14 @@ nodes
|
||||
| main.rs:175:9:175:35 | MyInt {...} [MyInt] | semmle.label | MyInt {...} [MyInt] |
|
||||
| main.rs:175:24:175:27 | self [MyInt] | semmle.label | self [MyInt] |
|
||||
| main.rs:175:24:175:33 | self.value | semmle.label | self.value |
|
||||
| main.rs:195:9:195:9 | a [MyInt] | semmle.label | a [MyInt] |
|
||||
| main.rs:195:13:195:38 | MyInt {...} [MyInt] | semmle.label | MyInt {...} [MyInt] |
|
||||
| main.rs:195:28:195:36 | source(...) | semmle.label | source(...) |
|
||||
| main.rs:197:9:197:9 | c [MyInt] | semmle.label | c [MyInt] |
|
||||
| main.rs:197:13:197:13 | a [MyInt] | semmle.label | a [MyInt] |
|
||||
| main.rs:197:13:197:17 | ... + ... [MyInt] | semmle.label | ... + ... [MyInt] |
|
||||
| main.rs:198:10:198:10 | c [MyInt] | semmle.label | c [MyInt] |
|
||||
| main.rs:198:10:198:16 | c.value | semmle.label | c.value |
|
||||
| main.rs:205:9:205:9 | a [MyInt] | semmle.label | a [MyInt] |
|
||||
| main.rs:205:13:205:38 | MyInt {...} [MyInt] | semmle.label | MyInt {...} [MyInt] |
|
||||
| main.rs:205:28:205:36 | source(...) | semmle.label | source(...) |
|
||||
@@ -262,6 +278,7 @@ subpaths
|
||||
| main.rs:134:29:134:29 | a | main.rs:110:27:110:32 | ...: i64 | main.rs:110:42:116:5 | { ... } | main.rs:134:13:134:30 | mn.data_through(...) |
|
||||
| main.rs:147:38:147:38 | a | main.rs:110:27:110:32 | ...: i64 | main.rs:110:42:116:5 | { ... } | main.rs:147:13:147:39 | ...::data_through(...) |
|
||||
| main.rs:165:24:165:33 | source(...) | main.rs:159:12:159:17 | ...: i64 | main.rs:159:28:161:5 | { ... } [MyInt] | main.rs:165:13:165:34 | ...::new(...) [MyInt] |
|
||||
| main.rs:197:13:197:13 | a [MyInt] | main.rs:173:12:173:15 | SelfParam [MyInt] | main.rs:173:42:176:5 | { ... } [MyInt] | main.rs:197:13:197:17 | ... + ... [MyInt] |
|
||||
| main.rs:205:9:205:9 | a [MyInt] | main.rs:173:12:173:15 | SelfParam [MyInt] | main.rs:173:42:176:5 | { ... } [MyInt] | main.rs:207:13:207:20 | a.add(...) [MyInt] |
|
||||
| main.rs:254:49:254:49 | a [MyInt] | main.rs:242:18:242:21 | SelfParam [MyInt] | main.rs:242:48:244:5 | { ... } [MyInt] | main.rs:254:30:254:53 | ...::take_self(...) [MyInt] |
|
||||
| main.rs:259:54:259:54 | b [MyInt] | main.rs:246:26:246:37 | ...: MyInt [MyInt] | main.rs:246:49:248:5 | { ... } [MyInt] | main.rs:259:30:259:55 | ...::take_second(...) [MyInt] |
|
||||
@@ -280,6 +297,7 @@ testFailures
|
||||
| main.rs:135:10:135:10 | b | main.rs:133:13:133:21 | source(...) | main.rs:135:10:135:10 | b | $@ | main.rs:133:13:133:21 | source(...) | source(...) |
|
||||
| main.rs:148:10:148:10 | b | main.rs:146:13:146:22 | source(...) | main.rs:148:10:148:10 | b | $@ | main.rs:146:13:146:22 | source(...) | source(...) |
|
||||
| main.rs:167:10:167:10 | m | main.rs:165:24:165:33 | source(...) | main.rs:167:10:167:10 | m | $@ | main.rs:165:24:165:33 | source(...) | source(...) |
|
||||
| main.rs:198:10:198:16 | c.value | main.rs:195:28:195:36 | source(...) | main.rs:198:10:198:16 | c.value | $@ | main.rs:195:28:195:36 | source(...) | source(...) |
|
||||
| main.rs:208:10:208:16 | d.value | main.rs:205:28:205:36 | source(...) | main.rs:208:10:208:16 | d.value | $@ | main.rs:205:28:205:36 | source(...) | source(...) |
|
||||
| main.rs:255:10:255:10 | c | main.rs:252:28:252:36 | source(...) | main.rs:255:10:255:10 | c | $@ | main.rs:252:28:252:36 | source(...) | source(...) |
|
||||
| main.rs:260:10:260:10 | c | main.rs:258:28:258:37 | source(...) | main.rs:260:10:260:10 | c | $@ | main.rs:258:28:258:37 | source(...) | source(...) |
|
||||
|
||||
@@ -195,7 +195,7 @@ fn test_operator_overloading() {
|
||||
let a = MyInt { value: source(5) };
|
||||
let b = MyInt { value: 2 };
|
||||
let c = a + b;
|
||||
sink(c.value); // $ MISSING: hasValueFlow=5
|
||||
sink(c.value); // $ hasValueFlow=5
|
||||
|
||||
let a = MyInt { value: 2 };
|
||||
let b = MyInt { value: source(6) };
|
||||
|
||||
@@ -41,8 +41,10 @@
|
||||
| main.rs:165:24:165:33 | source(...) | main.rs:1:1:3:1 | fn source |
|
||||
| main.rs:167:5:167:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
|
||||
| main.rs:195:28:195:36 | source(...) | main.rs:1:1:3:1 | fn source |
|
||||
| main.rs:197:13:197:17 | ... + ... | main.rs:173:5:176:5 | fn add |
|
||||
| main.rs:198:5:198:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
|
||||
| main.rs:201:28:201:36 | source(...) | main.rs:1:1:3:1 | fn source |
|
||||
| main.rs:202:13:202:17 | ... + ... | main.rs:173:5:176:5 | fn add |
|
||||
| main.rs:203:5:203:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
|
||||
| main.rs:205:28:205:36 | source(...) | main.rs:1:1:3:1 | fn source |
|
||||
| main.rs:207:13:207:20 | a.add(...) | main.rs:173:5:176:5 | fn add |
|
||||
@@ -50,10 +52,12 @@
|
||||
| main.rs:212:28:212:37 | source(...) | main.rs:1:1:3:1 | fn source |
|
||||
| main.rs:215:5:215:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
|
||||
| main.rs:218:28:218:37 | source(...) | main.rs:1:1:3:1 | fn source |
|
||||
| main.rs:219:5:219:10 | ... *= ... | main.rs:180:5:182:5 | fn mul_assign |
|
||||
| main.rs:220:5:220:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
|
||||
| main.rs:223:28:223:37 | source(...) | main.rs:1:1:3:1 | fn source |
|
||||
| main.rs:226:5:226:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
|
||||
| main.rs:228:28:228:37 | source(...) | main.rs:1:1:3:1 | fn source |
|
||||
| main.rs:229:13:229:14 | * ... | main.rs:188:5:190:5 | fn deref |
|
||||
| main.rs:230:5:230:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
|
||||
| main.rs:252:28:252:36 | source(...) | main.rs:1:1:3:1 | fn source |
|
||||
| main.rs:254:30:254:53 | ...::take_self(...) | main.rs:242:5:244:5 | fn take_self |
|
||||
|
||||
Reference in New Issue
Block a user