Address review comments

This commit is contained in:
Tom Hvitved
2025-12-03 21:08:42 +01:00
parent 38a572dfa0
commit bc6d38ebb4
28 changed files with 328 additions and 247 deletions

View File

@@ -258,7 +258,8 @@ final class CallExprCfgNode extends Nodes::CallExprCfgNode {
/** Gets the `i`th argument of this call. */ /** Gets the `i`th argument of this call. */
ExprCfgNode getSyntacticArgument(int i) { ExprCfgNode getSyntacticArgument(int i) {
any(ChildMapping mapping).hasCfgChild(node, node.getSyntacticArgument(i), this, result) any(ChildMapping mapping)
.hasCfgChild(node, node.getSyntacticPositionalArgument(i), this, result)
} }
} }

View File

@@ -210,13 +210,18 @@ module ExprTrees {
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() } override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
} }
class ArgsExprTree extends StandardPostOrderTree instanceof ArgsExpr { class InvocationExprTree extends StandardPostOrderTree instanceof InvocationExpr {
ArgsExprTree() { InvocationExprTree() {
not this instanceof CallExpr and not this instanceof CallExpr and
not this instanceof BinaryLogicalOperation not this instanceof BinaryLogicalOperation
} }
override AstNode getChildNode(int i) { result = super.getSyntacticArgument(i) } override AstNode getChildNode(int i) {
i = 0 and
result = super.getSyntacticReceiver()
or
result = super.getSyntacticPositionalArgument(i - 1)
}
} }
class LogicalOrExprTree extends PostOrderTree, LogicalOrExpr { class LogicalOrExprTree extends PostOrderTree, LogicalOrExpr {
@@ -295,7 +300,7 @@ module ExprTrees {
override AstNode getChildNode(int i) { override AstNode getChildNode(int i) {
i = 0 and result = super.getFunction() i = 0 and result = super.getFunction()
or or
result = super.getSyntacticArgument(i - 1) result = super.getSyntacticPositionalArgument(i - 1)
} }
} }
@@ -533,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 { class ReturnExprTree extends StandardPostOrderTree instanceof ReturnExpr {
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() } override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
} }

View File

@@ -5,6 +5,7 @@
private import rust private import rust
private import codeql.rust.frameworks.stdlib.Builtins private import codeql.rust.frameworks.stdlib.Builtins
private import DataFlowImpl 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. * A path to a value contained in an object. For example a field name of a struct.
@@ -168,10 +169,10 @@ final class TuplePositionContent extends FieldContent, TTuplePositionContent {
* Used by the model generator to create flow summaries for higher-order * Used by the model generator to create flow summaries for higher-order
* functions. * functions.
*/ */
final class ClosureCallArgumentContent extends Content, TClosureCallArgumentContent { final class FunctionCallArgumentContent extends Content, TFunctionCallArgumentContent {
private int pos; private int pos;
ClosureCallArgumentContent() { this = TClosureCallArgumentContent(pos) } FunctionCallArgumentContent() { this = TFunctionCallArgumentContent(pos) }
int getPosition() { result = pos } int getPosition() { result = pos }
@@ -269,8 +270,8 @@ newtype TContent =
)] )]
} or } or
TFunctionCallReturnContent() or TFunctionCallReturnContent() or
TClosureCallArgumentContent(int pos) { TFunctionCallArgumentContent(int pos) {
pos in [0 .. any(ClosureCallExpr c).getNumberOfPositionalArguments()] pos in [0 .. any(CallExprImpl::DynamicCallExpr c).getNumberOfPositionalArguments()]
} or } or
TCapturedVariableContent(VariableCapture::CapturedVariable v) or TCapturedVariableContent(VariableCapture::CapturedVariable v) or
TReferenceContent() TReferenceContent()

View File

@@ -10,6 +10,7 @@ private import codeql.dataflow.internal.DataFlowImpl
private import rust private import rust
private import SsaImpl as SsaImpl private import SsaImpl as SsaImpl
private import codeql.rust.controlflow.internal.Scope as Scope 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.PathResolution
private import codeql.rust.controlflow.ControlFlowGraph private import codeql.rust.controlflow.ControlFlowGraph
private import codeql.rust.dataflow.Ssa private import codeql.rust.dataflow.Ssa
@@ -85,62 +86,10 @@ final class DataFlowCall extends TDataFlowCall {
Location getLocation() { result = this.asCall().getLocation() } 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.(MethodCall).getReceiver() and this.isSelf()
}
}
/** /**
* Holds if `arg` is an argument of `call` at the position `pos`. * Holds if `arg` is an argument of `call` at the position `pos`.
*/ */
predicate isArgumentForCall(Expr arg, Call call, ArgumentPosition pos) { predicate isArgumentForCall(Expr arg, Call call, RustDataFlow::ArgumentPosition pos) {
// TODO: Handle index expressions as calls in data flow. // TODO: Handle index expressions as calls in data flow.
not call instanceof IndexExpr and not call instanceof IndexExpr and
arg = pos.getArgument(call) arg = pos.getArgument(call)
@@ -292,8 +241,8 @@ predicate lambdaCreationExpr(Expr creation) {
* Holds if `call` is a lambda call of kind `kind` where `receiver` is the * Holds if `call` is a lambda call of kind `kind` where `receiver` is the
* invoked expression. * invoked expression.
*/ */
predicate lambdaCallExpr(ClosureCallExpr call, LambdaCallKind kind, Expr receiver) { predicate lambdaCallExpr(CallExprImpl::DynamicCallExpr call, LambdaCallKind kind, Expr receiver) {
receiver = call.getClosureExpr() and receiver = call.getFunction() and
exists(kind) exists(kind)
} }
@@ -305,10 +254,6 @@ private module Aliases {
class DataFlowCallAlias = DataFlowCall; class DataFlowCallAlias = DataFlowCall;
class ParameterPositionAlias = ParameterPosition;
class ArgumentPositionAlias = ArgumentPosition;
class ContentAlias = Content; class ContentAlias = Content;
class ContentSetAlias = ContentSet; class ContentSetAlias = ContentSet;
@@ -340,6 +285,58 @@ module RustDataFlow implements InputSig<Location> {
final class CastNode = Node::CastNode; 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`. */ /** Holds if `p` is a parameter of `c` at the position `pos`. */
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) { predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
p.isParameterOf(c, pos) p.isParameterOf(c, pos)
@@ -449,10 +446,6 @@ module RustDataFlow implements InputSig<Location> {
ContentApprox getContentApprox(Content c) { result = c } ContentApprox getContentApprox(Content c) { result = c }
class ParameterPosition = ParameterPositionAlias;
class ArgumentPosition = ArgumentPositionAlias;
/** /**
* Holds if the parameter position `ppos` matches the argument position * Holds if the parameter position `ppos` matches the argument position
* `apos`. * `apos`.
@@ -664,7 +657,7 @@ module RustDataFlow implements InputSig<Location> {
pragma[nomagic] pragma[nomagic]
additional predicate storeContentStep(Node node1, Content c, Node node2) { additional predicate storeContentStep(Node node1, Content c, Node node2) {
exists(CallExpr ce, TupleField tf, int pos | exists(CallExpr ce, TupleField tf, int pos |
node1.asExpr() = ce.getSyntacticArgument(pos) and node1.asExpr() = ce.getSyntacticPositionalArgument(pos) and
node2.asExpr() = ce and node2.asExpr() = ce and
c = TTupleFieldContent(tf) c = TTupleFieldContent(tf)
| |
@@ -716,7 +709,7 @@ module RustDataFlow implements InputSig<Location> {
exists(DataFlowCall call, int i | exists(DataFlowCall call, int i |
isArgumentNode(node1, call, TPositionalParameterPosition(i)) and isArgumentNode(node1, call, TPositionalParameterPosition(i)) and
lambdaCall(call, _, node2.(PostUpdateNode).getPreUpdateNode()) and lambdaCall(call, _, node2.(PostUpdateNode).getPreUpdateNode()) and
c.(ClosureCallArgumentContent).getPosition() = i c.(FunctionCallArgumentContent).getPosition() = i
) )
or or
VariableCapture::storeStep(node1, c, node2) VariableCapture::storeStep(node1, c, node2)
@@ -825,7 +818,7 @@ module RustDataFlow implements InputSig<Location> {
*/ */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
( (
receiver.asExpr() = call.asCall().(ClosureCallExpr).getClosureExpr() receiver.asExpr() = call.asCall().(CallExprImpl::DynamicCallExpr).getFunction()
or or
call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode()) call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode())
) and ) and

View File

@@ -50,7 +50,7 @@ module Input implements InputSig<Location, RustDataFlow> {
ReturnKind getStandardReturnValueKind() { result = TNormalReturnKind() } 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 = pos.toString() } string encodeArgumentPosition(RustDataFlow::ArgumentPosition pos) { result = pos.toString() }
@@ -105,7 +105,9 @@ module Input implements InputSig<Location, RustDataFlow> {
string encodeWithContent(ContentSet c, string arg) { result = "With" + encodeContent(c, arg) } string encodeWithContent(ContentSet c, string arg) { result = "With" + encodeContent(c, arg) }
bindingset[token] bindingset[token]
ParameterPosition decodeUnknownParameterPosition(AccessPath::AccessPathTokenBase token) { RustDataFlow::ParameterPosition decodeUnknownParameterPosition(
AccessPath::AccessPathTokenBase token
) {
// needed to support `Argument[x..y]` ranges // needed to support `Argument[x..y]` ranges
token.getName() = "Argument" and token.getName() = "Argument" and
result.getPosition() = AccessPath::parseInt(token.getAnArgument()) result.getPosition() = AccessPath::parseInt(token.getAnArgument())
@@ -132,7 +134,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
/** Gets the argument of `source` described by `sc`, if any. */ /** Gets the argument of `source` described by `sc`, if any. */
private Expr getSourceNodeArgument(Input::SourceBase source, Impl::Private::SummaryComponent sc) { private Expr getSourceNodeArgument(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
exists(ArgumentPosition pos | exists(RustDataFlow::ArgumentPosition pos |
sc = Impl::Private::SummaryComponent::argument(pos) and sc = Impl::Private::SummaryComponent::argument(pos) and
result = pos.getArgument(source.getCall()) result = pos.getArgument(source.getCall())
) )
@@ -159,7 +161,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
s.head() = Impl::Private::SummaryComponent::return(_) and s.head() = Impl::Private::SummaryComponent::return(_) and
result.asExpr() = source.getCall() result.asExpr() = source.getCall()
or or
exists(ArgumentPosition pos, Expr arg | exists(RustDataFlow::ArgumentPosition pos, Expr arg |
s.head() = Impl::Private::SummaryComponent::parameter(pos) and s.head() = Impl::Private::SummaryComponent::parameter(pos) and
arg = getSourceNodeArgument(source, s.tail().headOfSingleton()) and arg = getSourceNodeArgument(source, s.tail().headOfSingleton()) and
result.asParameter() = getCallable(arg).getParam(pos.getPosition()) result.asParameter() = getCallable(arg).getParam(pos.getPosition())
@@ -170,7 +172,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
} }
RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) { RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {
exists(ArgsExpr call, Expr arg, ArgumentPosition pos | exists(InvocationExpr call, Expr arg, RustDataFlow::ArgumentPosition pos |
result.asExpr() = arg and result.asExpr() = arg and
sc = Impl::Private::SummaryComponent::argument(pos) and sc = Impl::Private::SummaryComponent::argument(pos) and
call = sink.getCall() and call = sink.getCall() and

View File

@@ -167,7 +167,7 @@ final class NameNode extends AstNodeNode, TNameNode {
*/ */
abstract class ParameterNode extends Node { abstract class ParameterNode extends Node {
/** Holds if this node is a parameter of `c` at position `pos`. */ /** 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 { final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParameterNode {
@@ -175,12 +175,12 @@ final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParam
SourceParameterNode() { this = TSourceParameterNode(n) } 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()) n = pos.getParameterIn(c.asCfgScope().(Callable).getParamList())
} }
/** Get the parameter position of this parameter. */ /** 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. */ /** Gets the parameter in the CFG that this node corresponds to. */
ParamBase getParameter() { result = n } ParamBase getParameter() { result = n }
@@ -188,13 +188,13 @@ final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParam
/** A parameter for a library callable with a flow summary. */ /** A parameter for a library callable with a flow summary. */
final class SummaryParameterNode extends ParameterNode, FlowSummaryNode { final class SummaryParameterNode extends ParameterNode, FlowSummaryNode {
private ParameterPosition pos_; private RustDataFlow::ParameterPosition pos_;
SummaryParameterNode() { SummaryParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), pos_) 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_ this.getSummarizedCallable() = c.asSummarizedCallable() and pos = pos_
} }
} }
@@ -210,7 +210,7 @@ final class ClosureParameterNode extends ParameterNode, TClosureSelfReferenceNod
final override CfgScope getCfgScope() { result = cfgScope } 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() cfgScope = c.asCfgScope() and pos.isClosureSelf()
} }

View File

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

View File

@@ -1,5 +1,5 @@
/** /**
* This module provides the public class `Call`. * This module provides the public classes `Call` and `MethodCall`.
*/ */
private import rust private import rust
@@ -9,21 +9,3 @@ private import internal.CallExprImpl::Impl as CallExprImpl
final class Call = Impl::Call; final class Call = Impl::Call;
final class MethodCall = Impl::MethodCall; final class MethodCall = Impl::MethodCall;
/**
* A call expression that targets a closure.
*
* Closure calls never have a static target, and the set of potential
* run-time targets is only available internally to the data flow library.
*/
class ClosureCallExpr extends CallExprImpl::CallExprCall {
ClosureCallExpr() {
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()
)
}
/** Gets the closure expression being called. */
Expr getClosureExpr() { result = super.getFunction() }
}

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

View File

@@ -1,37 +0,0 @@
private import rust
module Impl {
private import codeql.rust.internal.TypeInference as TypeInference
private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
/**
* An expression with arguments.
*
* Either a `CallExpr`, a `MethodCallExpr`, an `Operation`, or an `IndexExpr`.
*/
abstract class ArgsExpr extends ExprImpl::Expr {
/**
* Gets the `i`th syntactic argument of this expression.
*
* Examples:
* ```rust
* foo(42, "bar"); // `42` is argument 0 and `"bar"` is argument 1
* foo.bar(42); // `foo` is argument 0 and `42` is argument 1
* x + y; // `x` is argument 0 and `y` is argument 1
* x[y]; // `x` is argument 0 and `y` is argument 1
* ```
*/
Expr getSyntacticArgument(int i) { none() }
/** Gets an argument of this expression. */
Expr getASyntacticArgument() { result = this.getSyntacticArgument(_) }
/** Gets the number of 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) }
}
}

View File

@@ -12,7 +12,7 @@ private import codeql.rust.elements.internal.generated.CallExpr
*/ */
module Impl { module Impl {
private import rust private import rust
private import codeql.rust.elements.internal.ArgsExprImpl::Impl as ArgsExprImpl private import codeql.rust.elements.internal.InvocationExprImpl::Impl as InvocationExprImpl
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
private import codeql.rust.internal.PathResolution as PathResolution private import codeql.rust.internal.PathResolution as PathResolution
private import codeql.rust.internal.TypeInference as TypeInference private import codeql.rust.internal.TypeInference as TypeInference
@@ -25,6 +25,8 @@ module Impl {
result = PathResolution::resolvePath(getFunctionPath(ce)) 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 // the following QLdoc is generated: if you need to edit it, do it in the schema file
/** /**
* NOTE: Consider using `Call` instead, as that excludes call expressions that are * NOTE: Consider using `Call` instead, as that excludes call expressions that are
@@ -38,20 +40,20 @@ module Impl {
* Option::Some(42); // tuple variant instantiation * Option::Some(42); // tuple variant instantiation
* ``` * ```
*/ */
class CallExpr extends Generated::CallExpr, ArgsExprImpl::ArgsExpr { class CallExpr extends Generated::CallExpr, InvocationExprImpl::InvocationExpr {
override string toStringImpl() { result = this.getFunction().toAbbreviatedString() + "(...)" } override string toStringImpl() { result = this.getFunction().toAbbreviatedString() + "(...)" }
override Expr getSyntacticArgument(int i) { result = this.getArgList().getArg(i) } override Expr getSyntacticPositionalArgument(int i) { result = getSyntacticArg(this, i) }
// todo: remove once internal query has been updated // todo: remove once internal query has been updated
Expr getArg(int i) { result = this.getSyntacticArgument(i) } Expr getArg(int i) { result = getSyntacticArg(this, i) }
// todo: remove once internal query has been updated // todo: remove once internal query has been updated
int getNumberOfArgs() { result = this.getNumberOfSyntacticArguments() } int getNumberOfArgs() { result = this.getNumberOfSyntacticArguments() }
} }
/** /**
* A call expression that is _not_ an instantiation of a tuple struct or a tuple enum variant. * A call expression that is _not_ an instantiation of a tuple struct or a tuple variant.
* *
* For example: * For example:
* ```rust * ```rust
@@ -67,7 +69,23 @@ module Impl {
not this instanceof TupleVariantExpr not this instanceof TupleVariantExpr
} }
override Expr getPositionalArgument(int i) { result = super.getSyntacticArgument(i) } 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()
)
}
} }
/** /**
@@ -77,20 +95,20 @@ module Impl {
* layer, we do not check that the resolved target is a method in the charpred, * layer, we do not check that the resolved target is a method in the charpred,
* instead we check this in `getPositionalArgument` and `getReceiver`. * instead we check this in `getPositionalArgument` and `getReceiver`.
*/ */
class CallExprMethodCall extends CallExprCall, CallImpl::MethodCall { class CallExprMethodCall extends CallImpl::MethodCall instanceof CallExprCall {
CallExprMethodCall() { not this instanceof ClosureCallExpr } CallExprMethodCall() { not this instanceof DynamicCallExpr }
private predicate isInFactMethodCall() { this.getResolvedTarget() instanceof Method } private predicate isInFactMethodCall() { this.getResolvedTarget() instanceof Method }
override Expr getPositionalArgument(int i) { override Expr getPositionalArgument(int i) {
if this.isInFactMethodCall() if this.isInFactMethodCall()
then result = this.getSyntacticArgument(i + 1) then result = getSyntacticArg(this, i + 1)
else result = this.getSyntacticArgument(i) else result = getSyntacticArg(this, i)
} }
override Expr getReceiver() { override Expr getReceiver() {
this.isInFactMethodCall() and this.isInFactMethodCall() and
result = super.getSyntacticArgument(0) result = getSyntacticArg(this, 0)
} }
} }
@@ -119,7 +137,7 @@ module Impl {
} }
/** /**
* A call expression that instantiates a tuple enum variant. * A call expression that instantiates a tuple variant.
* *
* For example: * For example:
* ```rust * ```rust

View File

@@ -3,31 +3,56 @@ private import rust
module Impl { module Impl {
private import codeql.rust.internal.TypeInference as TypeInference private import codeql.rust.internal.TypeInference as TypeInference
private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
private import codeql.rust.elements.internal.ArgsExprImpl::Impl as ArgsExprImpl private import codeql.rust.elements.internal.InvocationExprImpl::Impl as InvocationExprImpl
/** /**
* A call. * A call.
* *
* Either * Either
* *
* - a `CallExpr` that is _not_ an instantiation of a tuple struct or a tuple enum variant, * - a `CallExpr` that is _not_ an instantiation of a tuple struct or a tuple variant,
* - a `MethodCallExpr`, * - a `MethodCallExpr`,
* - an `Operation` that targets an overloadable operator, or * - an `Operation` that targets an overloadable operator, or
* - an `IndexExpr`. * - an `IndexExpr`.
*/ */
abstract class Call extends ArgsExprImpl::ArgsExpr { 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 an argument of this call. */
Expr getAnArgument() { result = this.getArgument(_) }
// todo: remove once internal query has been updated // todo: remove once internal query has been updated
Expr getReceiver() { none() } Expr getReceiver() { none() }
/** /**
* Gets the `i`th positional argument of this call, if any. * Gets the `i`th positional argument of this call.
* *
* Examples: * Examples:
* ```rust * ```rust
* foo(42, "bar"); // `42` is argument 0 and `"bar"` is argument 1 * foo(42, "bar"); // `42` is argument 0 and `"bar"` is argument 1
* foo.bar(42); // `42` is argument 0 * foo.bar(42); // `42` is argument 0
* x + y; // `y` is argument 0 * Foo::bar(foo, 42); // `42` is argument 0
* x[y]; // `y` is argument 0 * x + y; // `y` is argument 0
* -x; // no positional arguments
* x[y]; // `y` is argument 0
* ``` * ```
*/ */
Expr getPositionalArgument(int i) { none() } Expr getPositionalArgument(int i) { none() }
@@ -43,10 +68,11 @@ module Impl {
/** Gets the resolved target of this call, if any. */ /** Gets the resolved target of this call, if any. */
Function getStaticTarget() { result = TypeInference::resolveCallTarget(this) } Function getStaticTarget() { result = TypeInference::resolveCallTarget(this) }
/** Gets the name of the method called, if any. */ /** Gets the name of the function called, if any. */
string getMethodName() { string getTargetName() { result = this.getStaticTarget().getName().getText() }
result = any(Function m | m = this.getStaticTarget() and m.hasSelfParam()).getName().getText()
} // todo: remove once internal query has been updated
string getMethodName() { result = this.getTargetName() }
/** Gets a runtime target of this call, if any. */ /** Gets a runtime target of this call, if any. */
pragma[nomagic] pragma[nomagic]
@@ -76,10 +102,12 @@ module Impl {
* *
* Examples: * Examples:
* ```rust * ```rust
* foo(42, "bar"); // no receiver * foo(42, "bar"); // no receiver
* foo.bar(42); // `foo` is receiver * foo.bar(42); // `foo` is receiver
* x + y; // `x` is receiver * Foo::bar(foo, 42); // `foo` is receiver
* x[y]; // `x` is receiver * x + y; // `x` is receiver
* -x; // `x` is receiver
* x[y]; // `x` is receiver
* ``` * ```
*/ */
override Expr getReceiver() { none() } override Expr getReceiver() { none() }

View File

@@ -4,6 +4,7 @@
* INTERNAL: Do not use. * INTERNAL: Do not use.
*/ */
private import rust
private import codeql.rust.elements.internal.generated.IndexExpr private import codeql.rust.elements.internal.generated.IndexExpr
/** /**
@@ -12,7 +13,6 @@ private import codeql.rust.elements.internal.generated.IndexExpr
*/ */
module Impl { module Impl {
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
private import codeql.rust.elements.internal.ArgsExprImpl::Impl as ArgsExprImpl
// the following QLdoc is generated: if you need to edit it, do it in the schema file // the following QLdoc is generated: if you need to edit it, do it in the schema file
/** /**
@@ -28,7 +28,7 @@ module Impl {
this.getBase().toAbbreviatedString() + "[" + this.getIndex().toAbbreviatedString() + "]" this.getBase().toAbbreviatedString() + "[" + this.getIndex().toAbbreviatedString() + "]"
} }
override Expr getSyntacticArgument(int i) { override Expr getSyntacticPositionalArgument(int i) {
i = 0 and result = this.getBase() i = 0 and result = this.getBase()
or or
i = 1 and result = this.getIndex() i = 1 and result = this.getIndex()

View File

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

View File

@@ -13,7 +13,7 @@ private import codeql.rust.elements.internal.generated.MethodCallExpr
*/ */
module Impl { module Impl {
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
private import codeql.rust.elements.internal.ArgsExprImpl::Impl as ArgsExprImpl 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 // the following QLdoc is generated: if you need to edit it, do it in the schema file
/** /**
@@ -46,11 +46,9 @@ module Impl {
result = strictconcat(int i | | this.toStringPart(i) order by i) result = strictconcat(int i | | this.toStringPart(i) order by i)
} }
override Expr getSyntacticArgument(int i) { override Expr getSyntacticPositionalArgument(int i) { result = this.getArgList().getArg(i) }
i = 0 and result = this.getReceiver()
or override Expr getSyntacticReceiver() { result = Generated::MethodCallExpr.super.getReceiver() }
result = this.getPositionalArgument(i - 1)
}
override Expr getPositionalArgument(int i) { result = this.getArgList().getArg(i) } override Expr getPositionalArgument(int i) { result = this.getArgList().getArg(i) }

View File

@@ -13,7 +13,7 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
*/ */
module Impl { module Impl {
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
private import codeql.rust.elements.internal.ArgsExprImpl::Impl as ArgsExprImpl private import codeql.rust.elements.internal.InvocationExprImpl::Impl as InvocationExprImpl
/** /**
* Holds if the operator `op` with arity `arity` is overloaded to a trait with * Holds if the operator `op` with arity `arity` is overloaded to a trait with
@@ -108,14 +108,14 @@ module Impl {
* for `Add::add(x, y)`, and `x += y` is syntactic sugar for * for `Add::add(x, y)`, and `x += y` is syntactic sugar for
* `AddAssign::add_assign(&mut x, y)`. * `AddAssign::add_assign(&mut x, y)`.
*/ */
abstract class Operation extends ArgsExprImpl::ArgsExpr { abstract class Operation extends InvocationExprImpl::InvocationExpr {
/** Gets the operator name of this operation, if it exists. */ /** Gets the operator name of this operation, if it exists. */
abstract string getOperatorName(); abstract string getOperatorName();
/** Gets the `n`th operand of this operation, if any. */ /** Gets the `n`th operand of this operation, if any. */
abstract Expr getOperand(int n); abstract Expr getOperand(int n);
override Expr getSyntacticArgument(int i) { result = this.getOperand(i) } override Expr getSyntacticPositionalArgument(int i) { result = this.getOperand(i) }
/** /**
* Gets the number of operands of this operation. * Gets the number of operands of this operation.
@@ -140,7 +140,7 @@ module Impl {
private class OperationMethodCall extends CallImpl::MethodCall instanceof Operation { private class OperationMethodCall extends CallImpl::MethodCall instanceof Operation {
OperationMethodCall() { super.isOverloaded(_, _, _) } OperationMethodCall() { super.isOverloaded(_, _, _) }
override Expr getPositionalArgument(int i) { result = super.getOperand(i + 1) and i >= 0 } override Expr getPositionalArgument(int i) { result = super.getOperand(i + 1) }
override Expr getReceiver() { result = super.getOperand(0) } override Expr getReceiver() { result = super.getOperand(0) }
} }

View File

@@ -26,8 +26,7 @@ class StreamCipherInit extends Cryptography::CryptographicOperation::Range {
// `cipher::KeyIvInit::new`, `cipher::KeyIvInit::new_from_slices`, `rc2::Rc2::new_with_eff_key_len` or similar. // `cipher::KeyIvInit::new`, `cipher::KeyIvInit::new_from_slices`, `rc2::Rc2::new_with_eff_key_len` or similar.
exists(Call call, string rawAlgorithmName | exists(Call call, string rawAlgorithmName |
call = this.asExpr() and call = this.asExpr() and
call.getStaticTarget().getName().getText() = call.getTargetName() = ["new", "new_from_slice", "new_with_eff_key_len", "new_from_slices"] and
["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. // extract the algorithm name from the type of `ce` or its receiver.
exists(Type t, TypePath tp | exists(Type t, TypePath tp |
t = inferType([call, call.(MethodCall).getReceiver()], tp) and t = inferType([call, call.(MethodCall).getReceiver()], tp) and

View File

@@ -25,7 +25,7 @@ query predicate multiplePathResolutions(Path p, ItemNode i) {
} }
// TODO: Take other calls into account // TODO: Take other calls into account
abstract private class CallExprBase extends ArgsExpr { } abstract private class CallExprBase extends InvocationExpr { }
private class CallExprCallExprBase extends CallExpr, CallExprBase { } private class CallExprCallExprBase extends CallExpr, CallExprBase { }

View File

@@ -1624,10 +1624,7 @@ private module MethodResolution {
} }
override Expr getArg(ArgumentPosition pos) { override Expr getArg(ArgumentPosition pos) {
pos.isSelf() and result = MethodCallExpr.super.getSyntacticArgument(pos)
result = MethodCallExpr.super.getReceiver()
or
result = super.getArgList().getArg(pos.asPosition())
} }
override predicate supportsAutoDerefAndBorrow() { any() } override predicate supportsAutoDerefAndBorrow() { any() }
@@ -1685,9 +1682,9 @@ private module MethodResolution {
override Expr getArg(ArgumentPosition pos) { override Expr getArg(ArgumentPosition pos) {
pos.isSelf() and pos.isSelf() and
result = super.getSyntacticArgument(0) result = super.getSyntacticPositionalArgument(0)
or or
result = super.getSyntacticArgument(pos.asPosition() + 1) result = super.getSyntacticPositionalArgument(pos.asPosition() + 1)
} }
// needed for `TypeQualifierIsInstantiationOfImplSelfInput` // needed for `TypeQualifierIsInstantiationOfImplSelfInput`
@@ -2383,7 +2380,7 @@ private module NonMethodResolution {
} }
AstNode getNodeAt(FunctionPosition pos) { AstNode getNodeAt(FunctionPosition pos) {
result = this.getSyntacticArgument(pos.asPosition()) result = this.getSyntacticArgument(pos.asArgumentPosition())
or or
result = this and pos.isReturn() result = this and pos.isReturn()
} }
@@ -3415,7 +3412,7 @@ private Type inferDynamicCallExprType(Expr n, TypePath path) {
or or
// Propagate the function's parameter type to the arguments // Propagate the function's parameter type to the arguments
exists(int index | exists(int index |
n = ce.getCall().getSyntacticArgument(index) and n = ce.getCall().getSyntacticPositionalArgument(index) and
path = path =
path0.stripPrefix(fnParameterPath(ce.getCall().getArgList().getNumberOfArgs(), index)) path0.stripPrefix(fnParameterPath(ce.getCall().getArgList().getNumberOfArgs(), index))
) )
@@ -3631,7 +3628,7 @@ private module Debug {
result = inferType(n, path) result = inferType(n, path)
} }
Addressable debugResolveCallTarget(ArgsExpr c) { Addressable debugResolveCallTarget(InvocationExpr c) {
c = getRelevantLocatable() and c = getRelevantLocatable() and
result = resolveCallTarget(c) result = resolveCallTarget(c)
} }

View File

@@ -4,28 +4,6 @@ private import codeql.rust.internal.PathResolution
private import codeql.rust.internal.Type private import codeql.rust.internal.Type
private import codeql.rust.internal.TypeMention private import codeql.rust.internal.TypeMention
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"
}
}
private newtype TFunctionPosition = private newtype TFunctionPosition =
TArgumentFunctionPosition(ArgumentPosition pos) or TArgumentFunctionPosition(ArgumentPosition pos) or
TReturnFunctionPosition() TReturnFunctionPosition()

View File

@@ -28,7 +28,7 @@ private class SensitiveDataCall extends SensitiveData {
SensitiveDataClassification classification; SensitiveDataClassification classification;
SensitiveDataCall() { SensitiveDataCall() {
exists(ArgsExpr call, Addressable target, string name | exists(InvocationExpr call, Addressable target, string name |
call = this.asExpr() and call = this.asExpr() and
target = call.getResolvedTarget() and target = call.getResolvedTarget() and
name = name =

View File

@@ -53,9 +53,9 @@ module Xss {
/** A call to a function with "escape" or "encode" in its name. */ /** A call to a function with "escape" or "encode" in its name. */
private class HeuristicHtmlEncodingBarrier extends Barrier { private class HeuristicHtmlEncodingBarrier extends Barrier {
HeuristicHtmlEncodingBarrier() { HeuristicHtmlEncodingBarrier() {
exists(Call fc | exists(Call c |
fc.getStaticTarget().getName().getText().regexpMatch(".*(escape|encode).*") and c.getStaticTarget().getName().getText().regexpMatch(".*(escape|encode).*") and
fc.getAPositionalArgument() = this.asExpr() c.getAnArgument() = this.asExpr()
) )
} }
} }

View File

@@ -6,7 +6,7 @@ import codeql.Locations
import codeql.files.FileSystem import codeql.files.FileSystem
import codeql.rust.elements.Operation import codeql.rust.elements.Operation
import codeql.rust.elements.ArithmeticOperation import codeql.rust.elements.ArithmeticOperation
import codeql.rust.elements.ArgsExpr import codeql.rust.elements.InvocationExpr
import codeql.rust.elements.AssignmentOperation import codeql.rust.elements.AssignmentOperation
import codeql.rust.elements.BitwiseOperation import codeql.rust.elements.BitwiseOperation
import codeql.rust.elements.ComparisonOperation import codeql.rust.elements.ComparisonOperation

View File

@@ -31,7 +31,7 @@ private module FlowTestImpl implements InputSig<Location, RustDataFlow> {
private string getSourceArgString(DataFlow::Node src) { private string getSourceArgString(DataFlow::Node src) {
defaultSource(src) and defaultSource(src) and
result = src.asExpr().(CallExpr).getSyntacticArgument(0).toString() result = src.asExpr().(Call).getPositionalArgument(0).toString()
or or
sourceNode(src, _) and sourceNode(src, _) and
result = result =

View File

@@ -6,6 +6,7 @@
import rust import rust
import codeql.util.ReportStats import codeql.util.ReportStats
import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
import codeql.rust.internal.TypeInference as TypeInference import codeql.rust.internal.TypeInference as TypeInference
/** /**
@@ -20,7 +21,7 @@ private class RelevantFile extends File {
module CallTargetStats implements StatsSig { module CallTargetStats implements StatsSig {
// TODO: Take other calls into account // TODO: Take other calls into account
abstract private class CallExprBase extends ArgsExpr { } abstract private class CallExprBase extends InvocationExpr { }
private class CallExprCallExprBase extends CallExpr, CallExprBase { } private class CallExprCallExprBase extends CallExpr, CallExprBase { }
@@ -34,7 +35,7 @@ module CallTargetStats implements StatsSig {
additional predicate isNotOkCall(CallExprBase c) { additional predicate isNotOkCall(CallExprBase c) {
c.getFile() instanceof RelevantFile and c.getFile() instanceof RelevantFile and
not exists(c.getResolvedTarget()) and not exists(c.getResolvedTarget()) and
not c instanceof ClosureCallExpr not c instanceof CallExprImpl::DynamicCallExpr
} }
int getNumberOfNotOk() { result = count(CallExprBase c | isNotOkCall(c)) } int getNumberOfNotOk() { result = count(CallExprBase c | isNotOkCall(c)) }

View File

@@ -67,8 +67,9 @@ module ModelGeneratorCommonInput implements
string parameterExactAccess(R::ParamBase p) { string parameterExactAccess(R::ParamBase p) {
result = result =
"Argument[" + any(DataFlowImpl::ParameterPosition pos | p = pos.getParameterIn(_)).toString() + "Argument[" +
"]" any(DataFlowImpl::RustDataFlow::ParameterPosition pos | p = pos.getParameterIn(_))
.toString() + "]"
} }
string parameterApproximateAccess(R::ParamBase p) { result = parameterExactAccess(p) } string parameterApproximateAccess(R::ParamBase p) { result = parameterExactAccess(p) }
@@ -78,12 +79,16 @@ module ModelGeneratorCommonInput implements
} }
bindingset[c] bindingset[c]
string paramReturnNodeAsApproximateOutput(QualifiedCallable c, DataFlowImpl::ParameterPosition pos) { string paramReturnNodeAsApproximateOutput(
QualifiedCallable c, DataFlowImpl::RustDataFlow::ParameterPosition pos
) {
result = paramReturnNodeAsExactOutput(c, pos) result = paramReturnNodeAsExactOutput(c, pos)
} }
bindingset[c] bindingset[c]
string paramReturnNodeAsExactOutput(QualifiedCallable c, DataFlowImpl::ParameterPosition pos) { string paramReturnNodeAsExactOutput(
QualifiedCallable c, DataFlowImpl::RustDataFlow::ParameterPosition pos
) {
result = parameterExactAccess(c.getFunction().getParam(pos.getPosition())) result = parameterExactAccess(c.getFunction().getParam(pos.getPosition()))
or or
pos.isSelf() and result = qualifierString() pos.isSelf() and result = qualifierString()
@@ -134,7 +139,7 @@ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputS
predicate isCallback(DataFlow::ContentSet cs) { predicate isCallback(DataFlow::ContentSet cs) {
exists(Content c | c = cs.(SingletonContentSet).getContent() | exists(Content c | c = cs.(SingletonContentSet).getContent() |
c instanceof FunctionCallReturnContent or c instanceof FunctionCallReturnContent or
c instanceof ClosureCallArgumentContent c instanceof FunctionCallArgumentContent
) )
} }
@@ -145,7 +150,7 @@ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputS
or or
exists(Content c | cs = DataFlowImpl::TSingletonContentSet(c) | exists(Content c | cs = DataFlowImpl::TSingletonContentSet(c) |
exists(int pos | exists(int pos |
pos = c.(ClosureCallArgumentContent).getPosition() and pos = c.(FunctionCallArgumentContent).getPosition() and
result = "Parameter" and result = "Parameter" and
arg = pos.toString() arg = pos.toString()
) )

View File

@@ -2,18 +2,15 @@ instances
| gen_call_expr.rs:8:5:8:11 | foo(...) | | gen_call_expr.rs:8:5:8:11 | foo(...) |
| gen_call_expr.rs:9:5:9:23 | foo::<...>(...) | | gen_call_expr.rs:9:5:9:23 | foo::<...>(...) |
| gen_call_expr.rs:10:5:10:14 | ...(...) | | gen_call_expr.rs:10:5:10:14 | ...(...) |
| gen_call_expr.rs:11:5:11:10 | foo(...) | | gen_call_expr.rs:11:5:11:20 | ...::Some(...) |
| gen_call_expr.rs:12:5:12:20 | ...::Some(...) |
getArgList getArgList
| gen_call_expr.rs:8:5:8:11 | foo(...) | gen_call_expr.rs:8:8:8:11 | ArgList | | gen_call_expr.rs:8:5:8:11 | foo(...) | gen_call_expr.rs:8:8:8:11 | ArgList |
| gen_call_expr.rs:9:5:9:23 | foo::<...>(...) | gen_call_expr.rs:9:20:9:23 | ArgList | | gen_call_expr.rs:9:5:9:23 | foo::<...>(...) | gen_call_expr.rs:9:20:9:23 | ArgList |
| gen_call_expr.rs:10:5:10:14 | ...(...) | gen_call_expr.rs:10:11:10:14 | ArgList | | gen_call_expr.rs:10:5:10:14 | ...(...) | gen_call_expr.rs:10:11:10:14 | ArgList |
| gen_call_expr.rs:11:5:11:10 | foo(...) | gen_call_expr.rs:11:8:11:10 | ArgList | | gen_call_expr.rs:11:5:11:20 | ...::Some(...) | gen_call_expr.rs:11:17:11:20 | ArgList |
| gen_call_expr.rs:12:5:12:20 | ...::Some(...) | gen_call_expr.rs:12:17:12:20 | ArgList |
getAttr getAttr
getFunction getFunction
| gen_call_expr.rs:8:5:8:11 | foo(...) | gen_call_expr.rs:8:5:8:7 | foo | | gen_call_expr.rs:8:5:8:11 | foo(...) | gen_call_expr.rs:8:5:8:7 | foo |
| gen_call_expr.rs:9:5:9:23 | foo::<...>(...) | gen_call_expr.rs:9:5:9:19 | foo::<...> | | gen_call_expr.rs:9:5:9:23 | foo::<...>(...) | gen_call_expr.rs:9:5:9:19 | foo::<...> |
| gen_call_expr.rs:10:5:10:14 | ...(...) | gen_call_expr.rs:10:5:10:10 | foo[0] | | gen_call_expr.rs:10:5:10:14 | ...(...) | gen_call_expr.rs:10:5:10:10 | foo[0] |
| gen_call_expr.rs:11:5:11:10 | foo(...) | gen_call_expr.rs:11:5:11:7 | foo | | gen_call_expr.rs:11:5:11:20 | ...::Some(...) | gen_call_expr.rs:11:5:11:16 | ...::Some |
| gen_call_expr.rs:12:5:12:20 | ...::Some(...) | gen_call_expr.rs:12:5:12:16 | ...::Some |

View File

@@ -183,7 +183,11 @@ edges
| test.rs:389:61:389:66 | [post] buffer | test.rs:392:23:392:33 | buffer[...] | provenance | | | test.rs:389:61:389:66 | [post] buffer | test.rs:392:23:392:33 | buffer[...] | provenance | |
| test.rs:391:23:391:28 | buffer | test.rs:391:22:391:28 | &buffer | provenance | | | test.rs:391:23:391:28 | buffer | test.rs:391:22:391:28 | &buffer | provenance | |
| test.rs:392:23:392:33 | buffer[...] | test.rs:392:22:392:33 | &... | provenance | | | test.rs:392:23:392:33 | buffer[...] | test.rs:392:22:392:33 | &... | provenance | |
| test.rs:399:63:399:73 | &mut reader [&ref] | test.rs:399:63:399:73 | [post] &mut reader [&ref] | provenance | MaD:13 |
| test.rs:399:63:399:73 | &mut reader [&ref] | test.rs:399:76:399:87 | [post] &mut buffer1 [&ref] | provenance | MaD:13 | | test.rs:399:63:399:73 | &mut reader [&ref] | test.rs:399:76:399:87 | [post] &mut buffer1 [&ref] | provenance | MaD:13 |
| test.rs:399:63:399:73 | [post] &mut reader [&ref] | test.rs:399:68:399:73 | [post] reader | provenance | |
| test.rs:399:68:399:73 | [post] reader | test.rs:403:31:403:36 | reader | provenance | |
| test.rs:399:68:399:73 | [post] reader | test.rs:408:55:408:60 | reader | provenance | |
| test.rs:399:68:399:73 | reader | test.rs:399:63:399:73 | &mut reader [&ref] | provenance | | | test.rs:399:68:399:73 | reader | test.rs:399:63:399:73 | &mut reader [&ref] | provenance | |
| test.rs:399:76:399:87 | [post] &mut buffer1 [&ref] | test.rs:399:81:399:87 | [post] buffer1 | provenance | | | test.rs:399:76:399:87 | [post] &mut buffer1 [&ref] | test.rs:399:81:399:87 | [post] buffer1 | provenance | |
| test.rs:399:81:399:87 | [post] buffer1 | test.rs:400:19:400:40 | buffer1[...] | provenance | | | test.rs:399:81:399:87 | [post] buffer1 | test.rs:400:19:400:40 | buffer1[...] | provenance | |
@@ -257,7 +261,15 @@ edges
| test.rs:447:61:447:66 | [post] buffer | test.rs:450:23:450:33 | buffer[...] | provenance | | | test.rs:447:61:447:66 | [post] buffer | test.rs:450:23:450:33 | buffer[...] | provenance | |
| test.rs:448:19:448:24 | buffer | test.rs:448:18:448:24 | &buffer | provenance | | | test.rs:448:19:448:24 | buffer | test.rs:448:18:448:24 | &buffer | provenance | |
| test.rs:450:23:450:33 | buffer[...] | test.rs:450:22:450:33 | &... | provenance | | | test.rs:450:23:450:33 | buffer[...] | test.rs:450:22:450:33 | &... | provenance | |
| test.rs:457:63:457:74 | &mut reader2 [&ref] | test.rs:457:63:457:74 | [post] &mut reader2 [&ref] | provenance | MaD:13 |
| test.rs:457:63:457:74 | &mut reader2 [&ref] | test.rs:457:77:457:88 | [post] &mut buffer1 [&ref] | provenance | MaD:13 | | test.rs:457:63:457:74 | &mut reader2 [&ref] | test.rs:457:77:457:88 | [post] &mut buffer1 [&ref] | provenance | MaD:13 |
| test.rs:457:63:457:74 | [post] &mut reader2 [&ref] | test.rs:457:68:457:74 | [post] reader2 | provenance | |
| test.rs:457:68:457:74 | [post] reader2 | test.rs:461:31:461:37 | reader2 | provenance | |
| test.rs:457:68:457:74 | [post] reader2 | test.rs:467:44:467:50 | reader2 | provenance | |
| test.rs:457:68:457:74 | [post] reader2 | test.rs:479:26:479:32 | reader2 | provenance | |
| test.rs:457:68:457:74 | [post] reader2 | test.rs:486:31:486:37 | reader2 | provenance | |
| test.rs:457:68:457:74 | [post] reader2 | test.rs:493:31:493:37 | reader2 | provenance | |
| test.rs:457:68:457:74 | [post] reader2 | test.rs:500:31:500:37 | reader2 | provenance | |
| test.rs:457:68:457:74 | reader2 | test.rs:457:63:457:74 | &mut reader2 [&ref] | provenance | | | test.rs:457:68:457:74 | reader2 | test.rs:457:63:457:74 | &mut reader2 [&ref] | provenance | |
| test.rs:457:77:457:88 | [post] &mut buffer1 [&ref] | test.rs:457:82:457:88 | [post] buffer1 | provenance | | | test.rs:457:77:457:88 | [post] &mut buffer1 [&ref] | test.rs:457:82:457:88 | [post] buffer1 | provenance | |
| test.rs:457:82:457:88 | [post] buffer1 | test.rs:458:19:458:40 | buffer1[...] | provenance | | | test.rs:457:82:457:88 | [post] buffer1 | test.rs:458:19:458:40 | buffer1[...] | provenance | |
@@ -461,6 +473,8 @@ nodes
| test.rs:392:22:392:33 | &... | semmle.label | &... | | test.rs:392:22:392:33 | &... | semmle.label | &... |
| test.rs:392:23:392:33 | buffer[...] | semmle.label | buffer[...] | | test.rs:392:23:392:33 | buffer[...] | semmle.label | buffer[...] |
| test.rs:399:63:399:73 | &mut reader [&ref] | semmle.label | &mut reader [&ref] | | test.rs:399:63:399:73 | &mut reader [&ref] | semmle.label | &mut reader [&ref] |
| test.rs:399:63:399:73 | [post] &mut reader [&ref] | semmle.label | [post] &mut reader [&ref] |
| test.rs:399:68:399:73 | [post] reader | semmle.label | [post] reader |
| test.rs:399:68:399:73 | reader | semmle.label | reader | | test.rs:399:68:399:73 | reader | semmle.label | reader |
| test.rs:399:76:399:87 | [post] &mut buffer1 [&ref] | semmle.label | [post] &mut buffer1 [&ref] | | test.rs:399:76:399:87 | [post] &mut buffer1 [&ref] | semmle.label | [post] &mut buffer1 [&ref] |
| test.rs:399:81:399:87 | [post] buffer1 | semmle.label | [post] buffer1 | | test.rs:399:81:399:87 | [post] buffer1 | semmle.label | [post] buffer1 |
@@ -529,6 +543,8 @@ nodes
| test.rs:450:22:450:33 | &... | semmle.label | &... | | test.rs:450:22:450:33 | &... | semmle.label | &... |
| test.rs:450:23:450:33 | buffer[...] | semmle.label | buffer[...] | | test.rs:450:23:450:33 | buffer[...] | semmle.label | buffer[...] |
| test.rs:457:63:457:74 | &mut reader2 [&ref] | semmle.label | &mut reader2 [&ref] | | test.rs:457:63:457:74 | &mut reader2 [&ref] | semmle.label | &mut reader2 [&ref] |
| test.rs:457:63:457:74 | [post] &mut reader2 [&ref] | semmle.label | [post] &mut reader2 [&ref] |
| test.rs:457:68:457:74 | [post] reader2 | semmle.label | [post] reader2 |
| test.rs:457:68:457:74 | reader2 | semmle.label | reader2 | | test.rs:457:68:457:74 | reader2 | semmle.label | reader2 |
| test.rs:457:77:457:88 | [post] &mut buffer1 [&ref] | semmle.label | [post] &mut buffer1 [&ref] | | test.rs:457:77:457:88 | [post] &mut buffer1 [&ref] | semmle.label | [post] &mut buffer1 [&ref] |
| test.rs:457:82:457:88 | [post] buffer1 | semmle.label | [post] buffer1 | | test.rs:457:82:457:88 | [post] buffer1 | semmle.label | [post] buffer1 |