mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Address review comments
This commit is contained in:
@@ -258,7 +258,8 @@ final class CallExprCfgNode extends Nodes::CallExprCfgNode {
|
||||
|
||||
/** Gets the `i`th argument of this call. */
|
||||
ExprCfgNode getSyntacticArgument(int i) {
|
||||
any(ChildMapping mapping).hasCfgChild(node, node.getSyntacticArgument(i), this, result)
|
||||
any(ChildMapping mapping)
|
||||
.hasCfgChild(node, node.getSyntacticPositionalArgument(i), this, result)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,13 +210,18 @@ module ExprTrees {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class ArgsExprTree extends StandardPostOrderTree instanceof ArgsExpr {
|
||||
ArgsExprTree() {
|
||||
class InvocationExprTree extends StandardPostOrderTree instanceof InvocationExpr {
|
||||
InvocationExprTree() {
|
||||
not this instanceof CallExpr and
|
||||
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 {
|
||||
@@ -295,7 +300,7 @@ module ExprTrees {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getFunction()
|
||||
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 {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
private import rust
|
||||
private import codeql.rust.frameworks.stdlib.Builtins
|
||||
private import DataFlowImpl
|
||||
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
|
||||
|
||||
/**
|
||||
* A path to a value contained in an object. For example a field name of a struct.
|
||||
@@ -168,10 +169,10 @@ final class TuplePositionContent extends FieldContent, TTuplePositionContent {
|
||||
* Used by the model generator to create flow summaries for higher-order
|
||||
* functions.
|
||||
*/
|
||||
final class ClosureCallArgumentContent extends Content, TClosureCallArgumentContent {
|
||||
final class FunctionCallArgumentContent extends Content, TFunctionCallArgumentContent {
|
||||
private int pos;
|
||||
|
||||
ClosureCallArgumentContent() { this = TClosureCallArgumentContent(pos) }
|
||||
FunctionCallArgumentContent() { this = TFunctionCallArgumentContent(pos) }
|
||||
|
||||
int getPosition() { result = pos }
|
||||
|
||||
@@ -269,8 +270,8 @@ newtype TContent =
|
||||
)]
|
||||
} or
|
||||
TFunctionCallReturnContent() or
|
||||
TClosureCallArgumentContent(int pos) {
|
||||
pos in [0 .. any(ClosureCallExpr c).getNumberOfPositionalArguments()]
|
||||
TFunctionCallArgumentContent(int pos) {
|
||||
pos in [0 .. any(CallExprImpl::DynamicCallExpr c).getNumberOfPositionalArguments()]
|
||||
} or
|
||||
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
|
||||
TReferenceContent()
|
||||
|
||||
@@ -10,6 +10,7 @@ private import codeql.dataflow.internal.DataFlowImpl
|
||||
private import rust
|
||||
private import SsaImpl as SsaImpl
|
||||
private import codeql.rust.controlflow.internal.Scope as Scope
|
||||
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
|
||||
private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.controlflow.ControlFlowGraph
|
||||
private import codeql.rust.dataflow.Ssa
|
||||
@@ -85,62 +86,10 @@ final class DataFlowCall extends TDataFlowCall {
|
||||
Location getLocation() { result = this.asCall().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of a parameter in a function.
|
||||
*
|
||||
* In Rust there is a 1-to-1 correspondence between parameter positions and
|
||||
* arguments positions, so we use the same underlying type for both.
|
||||
*/
|
||||
final class ParameterPosition extends TParameterPosition {
|
||||
/** Gets the underlying integer position, if any. */
|
||||
int getPosition() { this = TPositionalParameterPosition(result) }
|
||||
|
||||
predicate hasPosition() { exists(this.getPosition()) }
|
||||
|
||||
/** Holds if this position represents the `self` position. */
|
||||
predicate isSelf() { this = TSelfParameterPosition() }
|
||||
|
||||
/**
|
||||
* Holds if this position represents a reference to a closure itself. Only
|
||||
* used for tracking flow through captured variables.
|
||||
*/
|
||||
predicate isClosureSelf() { this = TClosureSelfParameterPosition() }
|
||||
|
||||
/** Gets a textual representation of this position. */
|
||||
string toString() {
|
||||
result = this.getPosition().toString()
|
||||
or
|
||||
result = "self" and this.isSelf()
|
||||
or
|
||||
result = "closure self" and this.isClosureSelf()
|
||||
}
|
||||
|
||||
ParamBase getParameterIn(ParamList ps) {
|
||||
result = ps.getParam(this.getPosition())
|
||||
or
|
||||
result = ps.getSelfParam() and this.isSelf()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of an argument in a call.
|
||||
*
|
||||
* In Rust there is a 1-to-1 correspondence between parameter positions and
|
||||
* arguments positions, so we use the same underlying type for both.
|
||||
*/
|
||||
final class ArgumentPosition extends ParameterPosition {
|
||||
/** Gets the argument of `call` at this position, if any. */
|
||||
Expr getArgument(Call call) {
|
||||
result = call.getPositionalArgument(this.getPosition())
|
||||
or
|
||||
result = call.(MethodCall).getReceiver() and this.isSelf()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
not call instanceof IndexExpr and
|
||||
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
|
||||
* invoked expression.
|
||||
*/
|
||||
predicate lambdaCallExpr(ClosureCallExpr call, LambdaCallKind kind, Expr receiver) {
|
||||
receiver = call.getClosureExpr() and
|
||||
predicate lambdaCallExpr(CallExprImpl::DynamicCallExpr call, LambdaCallKind kind, Expr receiver) {
|
||||
receiver = call.getFunction() and
|
||||
exists(kind)
|
||||
}
|
||||
|
||||
@@ -305,10 +254,6 @@ private module Aliases {
|
||||
|
||||
class DataFlowCallAlias = DataFlowCall;
|
||||
|
||||
class ParameterPositionAlias = ParameterPosition;
|
||||
|
||||
class ArgumentPositionAlias = ArgumentPosition;
|
||||
|
||||
class ContentAlias = Content;
|
||||
|
||||
class ContentSetAlias = ContentSet;
|
||||
@@ -340,6 +285,58 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
final class CastNode = Node::CastNode;
|
||||
|
||||
/**
|
||||
* The position of a parameter in a function.
|
||||
*
|
||||
* In Rust there is a 1-to-1 correspondence between parameter positions and
|
||||
* arguments positions, so we use the same underlying type for both.
|
||||
*/
|
||||
final class ParameterPosition extends TParameterPosition {
|
||||
/** Gets the underlying integer position, if any. */
|
||||
int getPosition() { this = TPositionalParameterPosition(result) }
|
||||
|
||||
predicate hasPosition() { exists(this.getPosition()) }
|
||||
|
||||
/** Holds if this position represents the `self` position. */
|
||||
predicate isSelf() { this = TSelfParameterPosition() }
|
||||
|
||||
/**
|
||||
* Holds if this position represents a reference to a closure itself. Only
|
||||
* used for tracking flow through captured variables.
|
||||
*/
|
||||
predicate isClosureSelf() { this = TClosureSelfParameterPosition() }
|
||||
|
||||
/** Gets a textual representation of this position. */
|
||||
string toString() {
|
||||
result = this.getPosition().toString()
|
||||
or
|
||||
result = "self" and this.isSelf()
|
||||
or
|
||||
result = "closure self" and this.isClosureSelf()
|
||||
}
|
||||
|
||||
ParamBase getParameterIn(ParamList ps) {
|
||||
result = ps.getParam(this.getPosition())
|
||||
or
|
||||
result = ps.getSelfParam() and this.isSelf()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of an argument in a call.
|
||||
*
|
||||
* In Rust there is a 1-to-1 correspondence between parameter positions and
|
||||
* arguments positions, so we use the same underlying type for both.
|
||||
*/
|
||||
final class ArgumentPosition extends ParameterPosition {
|
||||
/** Gets the argument of `call` at this position, if any. */
|
||||
Expr getArgument(Call call) {
|
||||
result = call.getPositionalArgument(this.getPosition())
|
||||
or
|
||||
result = call.(MethodCall).getReceiver() and this.isSelf()
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `p` is a parameter of `c` at the position `pos`. */
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
p.isParameterOf(c, pos)
|
||||
@@ -449,10 +446,6 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
ContentApprox getContentApprox(Content c) { result = c }
|
||||
|
||||
class ParameterPosition = ParameterPositionAlias;
|
||||
|
||||
class ArgumentPosition = ArgumentPositionAlias;
|
||||
|
||||
/**
|
||||
* Holds if the parameter position `ppos` matches the argument position
|
||||
* `apos`.
|
||||
@@ -664,7 +657,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
pragma[nomagic]
|
||||
additional predicate storeContentStep(Node node1, Content c, Node node2) {
|
||||
exists(CallExpr ce, TupleField tf, int pos |
|
||||
node1.asExpr() = ce.getSyntacticArgument(pos) and
|
||||
node1.asExpr() = ce.getSyntacticPositionalArgument(pos) and
|
||||
node2.asExpr() = ce and
|
||||
c = TTupleFieldContent(tf)
|
||||
|
|
||||
@@ -716,7 +709,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
exists(DataFlowCall call, int i |
|
||||
isArgumentNode(node1, call, TPositionalParameterPosition(i)) and
|
||||
lambdaCall(call, _, node2.(PostUpdateNode).getPreUpdateNode()) and
|
||||
c.(ClosureCallArgumentContent).getPosition() = i
|
||||
c.(FunctionCallArgumentContent).getPosition() = i
|
||||
)
|
||||
or
|
||||
VariableCapture::storeStep(node1, c, node2)
|
||||
@@ -825,7 +818,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
*/
|
||||
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
(
|
||||
receiver.asExpr() = call.asCall().(ClosureCallExpr).getClosureExpr()
|
||||
receiver.asExpr() = call.asCall().(CallExprImpl::DynamicCallExpr).getFunction()
|
||||
or
|
||||
call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode())
|
||||
) and
|
||||
|
||||
@@ -50,7 +50,7 @@ module Input implements InputSig<Location, RustDataFlow> {
|
||||
|
||||
ReturnKind getStandardReturnValueKind() { result = TNormalReturnKind() }
|
||||
|
||||
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }
|
||||
string encodeParameterPosition(RustDataFlow::ParameterPosition pos) { result = pos.toString() }
|
||||
|
||||
string encodeArgumentPosition(RustDataFlow::ArgumentPosition pos) { result = pos.toString() }
|
||||
|
||||
@@ -105,7 +105,9 @@ module Input implements InputSig<Location, RustDataFlow> {
|
||||
string encodeWithContent(ContentSet c, string arg) { result = "With" + encodeContent(c, arg) }
|
||||
|
||||
bindingset[token]
|
||||
ParameterPosition decodeUnknownParameterPosition(AccessPath::AccessPathTokenBase token) {
|
||||
RustDataFlow::ParameterPosition decodeUnknownParameterPosition(
|
||||
AccessPath::AccessPathTokenBase token
|
||||
) {
|
||||
// needed to support `Argument[x..y]` ranges
|
||||
token.getName() = "Argument" and
|
||||
result.getPosition() = AccessPath::parseInt(token.getAnArgument())
|
||||
@@ -132,7 +134,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
|
||||
/** Gets the argument of `source` described by `sc`, if any. */
|
||||
private Expr getSourceNodeArgument(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
|
||||
exists(ArgumentPosition pos |
|
||||
exists(RustDataFlow::ArgumentPosition pos |
|
||||
sc = Impl::Private::SummaryComponent::argument(pos) and
|
||||
result = pos.getArgument(source.getCall())
|
||||
)
|
||||
@@ -159,7 +161,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
s.head() = Impl::Private::SummaryComponent::return(_) and
|
||||
result.asExpr() = source.getCall()
|
||||
or
|
||||
exists(ArgumentPosition pos, Expr arg |
|
||||
exists(RustDataFlow::ArgumentPosition pos, Expr arg |
|
||||
s.head() = Impl::Private::SummaryComponent::parameter(pos) and
|
||||
arg = getSourceNodeArgument(source, s.tail().headOfSingleton()) and
|
||||
result.asParameter() = getCallable(arg).getParam(pos.getPosition())
|
||||
@@ -170,7 +172,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
}
|
||||
|
||||
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
|
||||
sc = Impl::Private::SummaryComponent::argument(pos) and
|
||||
call = sink.getCall() and
|
||||
|
||||
@@ -167,7 +167,7 @@ final class NameNode extends AstNodeNode, TNameNode {
|
||||
*/
|
||||
abstract class ParameterNode extends Node {
|
||||
/** Holds if this node is a parameter of `c` at position `pos`. */
|
||||
abstract predicate isParameterOf(DataFlowCallable c, ParameterPosition pos);
|
||||
abstract predicate isParameterOf(DataFlowCallable c, RustDataFlow::ParameterPosition pos);
|
||||
}
|
||||
|
||||
final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParameterNode {
|
||||
@@ -175,12 +175,12 @@ final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParam
|
||||
|
||||
SourceParameterNode() { this = TSourceParameterNode(n) }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
override predicate isParameterOf(DataFlowCallable c, RustDataFlow::ParameterPosition pos) {
|
||||
n = pos.getParameterIn(c.asCfgScope().(Callable).getParamList())
|
||||
}
|
||||
|
||||
/** Get the parameter position of this parameter. */
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
RustDataFlow::ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
/** Gets the parameter in the CFG that this node corresponds to. */
|
||||
ParamBase getParameter() { result = n }
|
||||
@@ -188,13 +188,13 @@ final class SourceParameterNode extends AstNodeNode, ParameterNode, TSourceParam
|
||||
|
||||
/** A parameter for a library callable with a flow summary. */
|
||||
final class SummaryParameterNode extends ParameterNode, FlowSummaryNode {
|
||||
private ParameterPosition pos_;
|
||||
private RustDataFlow::ParameterPosition pos_;
|
||||
|
||||
SummaryParameterNode() {
|
||||
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), pos_)
|
||||
}
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
override predicate isParameterOf(DataFlowCallable c, RustDataFlow::ParameterPosition pos) {
|
||||
this.getSummarizedCallable() = c.asSummarizedCallable() and pos = pos_
|
||||
}
|
||||
}
|
||||
@@ -210,7 +210,7 @@ final class ClosureParameterNode extends ParameterNode, TClosureSelfReferenceNod
|
||||
|
||||
final override CfgScope getCfgScope() { result = cfgScope }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
override predicate isParameterOf(DataFlowCallable c, RustDataFlow::ParameterPosition pos) {
|
||||
cfgScope = c.asCfgScope() and pos.isClosureSelf()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/**
|
||||
* This module provides the public class `ArgsExpr`.
|
||||
*/
|
||||
|
||||
private import internal.ArgsExprImpl
|
||||
|
||||
final class ArgsExpr = Impl::ArgsExpr;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* This module provides the public class `Call`.
|
||||
* This module provides the public classes `Call` and `MethodCall`.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
@@ -9,21 +9,3 @@ private import internal.CallExprImpl::Impl as CallExprImpl
|
||||
final class Call = Impl::Call;
|
||||
|
||||
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() }
|
||||
}
|
||||
|
||||
9
rust/ql/lib/codeql/rust/elements/InvocationExpr.qll
Normal file
9
rust/ql/lib/codeql/rust/elements/InvocationExpr.qll
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* This module provides the public classes `InvocationExpr` and `ArgumentPosition`.
|
||||
*/
|
||||
|
||||
private import internal.InvocationExprImpl
|
||||
|
||||
final class InvocationExpr = Impl::InvocationExpr;
|
||||
|
||||
final class ArgumentPosition = Impl::ArgumentPosition;
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ private import codeql.rust.elements.internal.generated.CallExpr
|
||||
*/
|
||||
module Impl {
|
||||
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.internal.PathResolution as PathResolution
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
@@ -25,6 +25,8 @@ module Impl {
|
||||
result = PathResolution::resolvePath(getFunctionPath(ce))
|
||||
}
|
||||
|
||||
private Expr getSyntacticArg(CallExpr ce, int i) { result = ce.getArgList().getArg(i) }
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* NOTE: Consider using `Call` instead, as that excludes call expressions that are
|
||||
@@ -38,20 +40,20 @@ module Impl {
|
||||
* 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 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
|
||||
Expr getArg(int i) { result = this.getSyntacticArgument(i) }
|
||||
Expr getArg(int i) { result = getSyntacticArg(this, i) }
|
||||
|
||||
// todo: remove once internal query has been updated
|
||||
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:
|
||||
* ```rust
|
||||
@@ -67,7 +69,23 @@ module Impl {
|
||||
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,
|
||||
* instead we check this in `getPositionalArgument` and `getReceiver`.
|
||||
*/
|
||||
class CallExprMethodCall extends CallExprCall, CallImpl::MethodCall {
|
||||
CallExprMethodCall() { not this instanceof ClosureCallExpr }
|
||||
class CallExprMethodCall extends CallImpl::MethodCall instanceof CallExprCall {
|
||||
CallExprMethodCall() { not this instanceof DynamicCallExpr }
|
||||
|
||||
private predicate isInFactMethodCall() { this.getResolvedTarget() instanceof Method }
|
||||
|
||||
override Expr getPositionalArgument(int i) {
|
||||
if this.isInFactMethodCall()
|
||||
then result = this.getSyntacticArgument(i + 1)
|
||||
else result = this.getSyntacticArgument(i)
|
||||
then result = getSyntacticArg(this, i + 1)
|
||||
else result = getSyntacticArg(this, i)
|
||||
}
|
||||
|
||||
override Expr getReceiver() {
|
||||
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:
|
||||
* ```rust
|
||||
|
||||
@@ -3,31 +3,56 @@ private import rust
|
||||
module Impl {
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
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.
|
||||
*
|
||||
* 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`,
|
||||
* - an `Operation` that targets an overloadable operator, or
|
||||
* - 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
|
||||
Expr getReceiver() { none() }
|
||||
|
||||
/**
|
||||
* Gets the `i`th positional argument of this call, if any.
|
||||
* Gets the `i`th positional argument of this call.
|
||||
*
|
||||
* Examples:
|
||||
* ```rust
|
||||
* foo(42, "bar"); // `42` is argument 0 and `"bar"` is argument 1
|
||||
* foo.bar(42); // `42` is argument 0
|
||||
* x + y; // `y` is argument 0
|
||||
* x[y]; // `y` is argument 0
|
||||
* foo(42, "bar"); // `42` is argument 0 and `"bar"` is argument 1
|
||||
* foo.bar(42); // `42` is argument 0
|
||||
* Foo::bar(foo, 42); // `42` is argument 0
|
||||
* x + y; // `y` is argument 0
|
||||
* -x; // no positional arguments
|
||||
* x[y]; // `y` is argument 0
|
||||
* ```
|
||||
*/
|
||||
Expr getPositionalArgument(int i) { none() }
|
||||
@@ -43,10 +68,11 @@ module Impl {
|
||||
/** Gets the resolved target of this call, if any. */
|
||||
Function getStaticTarget() { result = TypeInference::resolveCallTarget(this) }
|
||||
|
||||
/** Gets the name of the method called, if any. */
|
||||
string getMethodName() {
|
||||
result = any(Function m | m = this.getStaticTarget() and m.hasSelfParam()).getName().getText()
|
||||
}
|
||||
/** Gets the name of the function called, if any. */
|
||||
string getTargetName() { result = this.getStaticTarget().getName().getText() }
|
||||
|
||||
// todo: remove once internal query has been updated
|
||||
string getMethodName() { result = this.getTargetName() }
|
||||
|
||||
/** Gets a runtime target of this call, if any. */
|
||||
pragma[nomagic]
|
||||
@@ -76,10 +102,12 @@ module Impl {
|
||||
*
|
||||
* Examples:
|
||||
* ```rust
|
||||
* foo(42, "bar"); // no receiver
|
||||
* foo.bar(42); // `foo` is receiver
|
||||
* x + y; // `x` is receiver
|
||||
* x[y]; // `x` is receiver
|
||||
* foo(42, "bar"); // no receiver
|
||||
* foo.bar(42); // `foo` is receiver
|
||||
* Foo::bar(foo, 42); // `foo` is receiver
|
||||
* x + y; // `x` is receiver
|
||||
* -x; // `x` is receiver
|
||||
* x[y]; // `x` is receiver
|
||||
* ```
|
||||
*/
|
||||
override Expr getReceiver() { none() }
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.generated.IndexExpr
|
||||
|
||||
/**
|
||||
@@ -12,7 +13,6 @@ private import codeql.rust.elements.internal.generated.IndexExpr
|
||||
*/
|
||||
module Impl {
|
||||
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
|
||||
/**
|
||||
@@ -28,7 +28,7 @@ module Impl {
|
||||
this.getBase().toAbbreviatedString() + "[" + this.getIndex().toAbbreviatedString() + "]"
|
||||
}
|
||||
|
||||
override Expr getSyntacticArgument(int i) {
|
||||
override Expr getSyntacticPositionalArgument(int i) {
|
||||
i = 0 and result = this.getBase()
|
||||
or
|
||||
i = 1 and result = this.getIndex()
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ private import codeql.rust.elements.internal.generated.MethodCallExpr
|
||||
*/
|
||||
module Impl {
|
||||
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
|
||||
/**
|
||||
@@ -46,11 +46,9 @@ module Impl {
|
||||
result = strictconcat(int i | | this.toStringPart(i) order by i)
|
||||
}
|
||||
|
||||
override Expr getSyntacticArgument(int i) {
|
||||
i = 0 and result = this.getReceiver()
|
||||
or
|
||||
result = this.getPositionalArgument(i - 1)
|
||||
}
|
||||
override Expr getSyntacticPositionalArgument(int i) { result = this.getArgList().getArg(i) }
|
||||
|
||||
override Expr getSyntacticReceiver() { result = Generated::MethodCallExpr.super.getReceiver() }
|
||||
|
||||
override Expr getPositionalArgument(int i) { result = this.getArgList().getArg(i) }
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
|
||||
*/
|
||||
module Impl {
|
||||
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
|
||||
@@ -108,14 +108,14 @@ module Impl {
|
||||
* for `Add::add(x, y)`, and `x += y` is syntactic sugar for
|
||||
* `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. */
|
||||
abstract string getOperatorName();
|
||||
|
||||
/** Gets the `n`th operand of this operation, if any. */
|
||||
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.
|
||||
@@ -140,7 +140,7 @@ module Impl {
|
||||
private class OperationMethodCall extends CallImpl::MethodCall instanceof Operation {
|
||||
OperationMethodCall() { super.isOverloaded(_, _, _) }
|
||||
|
||||
override Expr getPositionalArgument(int i) { result = super.getOperand(i + 1) and i >= 0 }
|
||||
override Expr getPositionalArgument(int i) { result = super.getOperand(i + 1) }
|
||||
|
||||
override Expr getReceiver() { result = super.getOperand(0) }
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
exists(Call call, string rawAlgorithmName |
|
||||
call = this.asExpr() and
|
||||
call.getStaticTarget().getName().getText() =
|
||||
["new", "new_from_slice", "new_with_eff_key_len", "new_from_slices"] and
|
||||
call.getTargetName() = ["new", "new_from_slice", "new_with_eff_key_len", "new_from_slices"] and
|
||||
// extract the algorithm name from the type of `ce` or its receiver.
|
||||
exists(Type t, TypePath tp |
|
||||
t = inferType([call, call.(MethodCall).getReceiver()], tp) and
|
||||
|
||||
@@ -25,7 +25,7 @@ query predicate multiplePathResolutions(Path p, ItemNode i) {
|
||||
}
|
||||
|
||||
// TODO: Take other calls into account
|
||||
abstract private class CallExprBase extends ArgsExpr { }
|
||||
abstract private class CallExprBase extends InvocationExpr { }
|
||||
|
||||
private class CallExprCallExprBase extends CallExpr, CallExprBase { }
|
||||
|
||||
|
||||
@@ -1624,10 +1624,7 @@ private module MethodResolution {
|
||||
}
|
||||
|
||||
override Expr getArg(ArgumentPosition pos) {
|
||||
pos.isSelf() and
|
||||
result = MethodCallExpr.super.getReceiver()
|
||||
or
|
||||
result = super.getArgList().getArg(pos.asPosition())
|
||||
result = MethodCallExpr.super.getSyntacticArgument(pos)
|
||||
}
|
||||
|
||||
override predicate supportsAutoDerefAndBorrow() { any() }
|
||||
@@ -1685,9 +1682,9 @@ private module MethodResolution {
|
||||
|
||||
override Expr getArg(ArgumentPosition pos) {
|
||||
pos.isSelf() and
|
||||
result = super.getSyntacticArgument(0)
|
||||
result = super.getSyntacticPositionalArgument(0)
|
||||
or
|
||||
result = super.getSyntacticArgument(pos.asPosition() + 1)
|
||||
result = super.getSyntacticPositionalArgument(pos.asPosition() + 1)
|
||||
}
|
||||
|
||||
// needed for `TypeQualifierIsInstantiationOfImplSelfInput`
|
||||
@@ -2383,7 +2380,7 @@ private module NonMethodResolution {
|
||||
}
|
||||
|
||||
AstNode getNodeAt(FunctionPosition pos) {
|
||||
result = this.getSyntacticArgument(pos.asPosition())
|
||||
result = this.getSyntacticArgument(pos.asArgumentPosition())
|
||||
or
|
||||
result = this and pos.isReturn()
|
||||
}
|
||||
@@ -3415,7 +3412,7 @@ private Type inferDynamicCallExprType(Expr n, TypePath path) {
|
||||
or
|
||||
// Propagate the function's parameter type to the arguments
|
||||
exists(int index |
|
||||
n = ce.getCall().getSyntacticArgument(index) and
|
||||
n = ce.getCall().getSyntacticPositionalArgument(index) and
|
||||
path =
|
||||
path0.stripPrefix(fnParameterPath(ce.getCall().getArgList().getNumberOfArgs(), index))
|
||||
)
|
||||
@@ -3631,7 +3628,7 @@ private module Debug {
|
||||
result = inferType(n, path)
|
||||
}
|
||||
|
||||
Addressable debugResolveCallTarget(ArgsExpr c) {
|
||||
Addressable debugResolveCallTarget(InvocationExpr c) {
|
||||
c = getRelevantLocatable() and
|
||||
result = resolveCallTarget(c)
|
||||
}
|
||||
|
||||
@@ -4,28 +4,6 @@ private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.internal.Type
|
||||
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 =
|
||||
TArgumentFunctionPosition(ArgumentPosition pos) or
|
||||
TReturnFunctionPosition()
|
||||
|
||||
@@ -28,7 +28,7 @@ private class SensitiveDataCall extends SensitiveData {
|
||||
SensitiveDataClassification classification;
|
||||
|
||||
SensitiveDataCall() {
|
||||
exists(ArgsExpr call, Addressable target, string name |
|
||||
exists(InvocationExpr call, Addressable target, string name |
|
||||
call = this.asExpr() and
|
||||
target = call.getResolvedTarget() and
|
||||
name =
|
||||
|
||||
@@ -53,9 +53,9 @@ module Xss {
|
||||
/** A call to a function with "escape" or "encode" in its name. */
|
||||
private class HeuristicHtmlEncodingBarrier extends Barrier {
|
||||
HeuristicHtmlEncodingBarrier() {
|
||||
exists(Call fc |
|
||||
fc.getStaticTarget().getName().getText().regexpMatch(".*(escape|encode).*") and
|
||||
fc.getAPositionalArgument() = this.asExpr()
|
||||
exists(Call c |
|
||||
c.getStaticTarget().getName().getText().regexpMatch(".*(escape|encode).*") and
|
||||
c.getAnArgument() = this.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import codeql.Locations
|
||||
import codeql.files.FileSystem
|
||||
import codeql.rust.elements.Operation
|
||||
import codeql.rust.elements.ArithmeticOperation
|
||||
import codeql.rust.elements.ArgsExpr
|
||||
import codeql.rust.elements.InvocationExpr
|
||||
import codeql.rust.elements.AssignmentOperation
|
||||
import codeql.rust.elements.BitwiseOperation
|
||||
import codeql.rust.elements.ComparisonOperation
|
||||
|
||||
@@ -31,7 +31,7 @@ private module FlowTestImpl implements InputSig<Location, RustDataFlow> {
|
||||
|
||||
private string getSourceArgString(DataFlow::Node src) {
|
||||
defaultSource(src) and
|
||||
result = src.asExpr().(CallExpr).getSyntacticArgument(0).toString()
|
||||
result = src.asExpr().(Call).getPositionalArgument(0).toString()
|
||||
or
|
||||
sourceNode(src, _) and
|
||||
result =
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
import rust
|
||||
import codeql.util.ReportStats
|
||||
import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
|
||||
import codeql.rust.internal.TypeInference as TypeInference
|
||||
|
||||
/**
|
||||
@@ -20,7 +21,7 @@ private class RelevantFile extends File {
|
||||
|
||||
module CallTargetStats implements StatsSig {
|
||||
// TODO: Take other calls into account
|
||||
abstract private class CallExprBase extends ArgsExpr { }
|
||||
abstract private class CallExprBase extends InvocationExpr { }
|
||||
|
||||
private class CallExprCallExprBase extends CallExpr, CallExprBase { }
|
||||
|
||||
@@ -34,7 +35,7 @@ module CallTargetStats implements StatsSig {
|
||||
additional predicate isNotOkCall(CallExprBase c) {
|
||||
c.getFile() instanceof RelevantFile and
|
||||
not exists(c.getResolvedTarget()) and
|
||||
not c instanceof ClosureCallExpr
|
||||
not c instanceof CallExprImpl::DynamicCallExpr
|
||||
}
|
||||
|
||||
int getNumberOfNotOk() { result = count(CallExprBase c | isNotOkCall(c)) }
|
||||
|
||||
@@ -67,8 +67,9 @@ module ModelGeneratorCommonInput implements
|
||||
|
||||
string parameterExactAccess(R::ParamBase p) {
|
||||
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) }
|
||||
@@ -78,12 +79,16 @@ module ModelGeneratorCommonInput implements
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsApproximateOutput(QualifiedCallable c, DataFlowImpl::ParameterPosition pos) {
|
||||
string paramReturnNodeAsApproximateOutput(
|
||||
QualifiedCallable c, DataFlowImpl::RustDataFlow::ParameterPosition pos
|
||||
) {
|
||||
result = paramReturnNodeAsExactOutput(c, pos)
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsExactOutput(QualifiedCallable c, DataFlowImpl::ParameterPosition pos) {
|
||||
string paramReturnNodeAsExactOutput(
|
||||
QualifiedCallable c, DataFlowImpl::RustDataFlow::ParameterPosition pos
|
||||
) {
|
||||
result = parameterExactAccess(c.getFunction().getParam(pos.getPosition()))
|
||||
or
|
||||
pos.isSelf() and result = qualifierString()
|
||||
@@ -134,7 +139,7 @@ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputS
|
||||
predicate isCallback(DataFlow::ContentSet cs) {
|
||||
exists(Content c | c = cs.(SingletonContentSet).getContent() |
|
||||
c instanceof FunctionCallReturnContent or
|
||||
c instanceof ClosureCallArgumentContent
|
||||
c instanceof FunctionCallArgumentContent
|
||||
)
|
||||
}
|
||||
|
||||
@@ -145,7 +150,7 @@ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputS
|
||||
or
|
||||
exists(Content c | cs = DataFlowImpl::TSingletonContentSet(c) |
|
||||
exists(int pos |
|
||||
pos = c.(ClosureCallArgumentContent).getPosition() and
|
||||
pos = c.(FunctionCallArgumentContent).getPosition() and
|
||||
result = "Parameter" and
|
||||
arg = pos.toString()
|
||||
)
|
||||
|
||||
@@ -2,18 +2,15 @@ instances
|
||||
| gen_call_expr.rs:8:5:8:11 | foo(...) |
|
||||
| gen_call_expr.rs:9:5:9:23 | foo::<...>(...) |
|
||||
| gen_call_expr.rs:10:5:10:14 | ...(...) |
|
||||
| gen_call_expr.rs:11:5:11:10 | foo(...) |
|
||||
| gen_call_expr.rs:12:5:12:20 | ...::Some(...) |
|
||||
| gen_call_expr.rs:11:5:11:20 | ...::Some(...) |
|
||||
getArgList
|
||||
| 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: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:12:5:12:20 | ...::Some(...) | gen_call_expr.rs:12:17:12:20 | ArgList |
|
||||
| gen_call_expr.rs:11:5:11:20 | ...::Some(...) | gen_call_expr.rs:11:17:11:20 | ArgList |
|
||||
getAttr
|
||||
getFunction
|
||||
| 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: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:12:5:12:20 | ...::Some(...) | gen_call_expr.rs:12:5:12:16 | ...::Some |
|
||||
| gen_call_expr.rs:11:5:11:20 | ...::Some(...) | gen_call_expr.rs:11:5:11:16 | ...::Some |
|
||||
|
||||
@@ -183,7 +183,11 @@ edges
|
||||
| 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: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 | [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: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 | |
|
||||
@@ -257,7 +261,15 @@ edges
|
||||
| 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: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 | [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: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 | |
|
||||
@@ -461,6 +473,8 @@ nodes
|
||||
| test.rs:392:22:392:33 | &... | semmle.label | &... |
|
||||
| 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 | [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: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 |
|
||||
@@ -529,6 +543,8 @@ nodes
|
||||
| test.rs:450:22:450:33 | &... | semmle.label | &... |
|
||||
| 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 | [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: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 |
|
||||
|
||||
Reference in New Issue
Block a user