Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ private module Cached {
} or
TSummaryCall(FlowSummary::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
} or
TLambdaSynthCall(Node creation) { lambdaCreation(creation, _, _) }

/** Gets a viable run-time target for the call `call`. */
cached
Expand Down Expand Up @@ -497,6 +498,24 @@ class SummaryCall extends DelegateDataFlowCall, TSummaryCall {
override Location getLocation() { result = c.getLocation() }
}

class LambdaSynthCall extends DataFlowCall, TLambdaSynthCall {
private NodeImpl creation;

LambdaSynthCall() { this = TLambdaSynthCall(creation) }

override DataFlowCallable getARuntimeTarget() { none() }

override ControlFlow::Nodes::ElementNode getControlFlowNode() { none() }

override DataFlow::Node getNode() { none() }

override DataFlowCallable getEnclosingCallable() { result = creation.getEnclosingCallableImpl() }

override string toString() { result = "[lambda] call to " + creation }

override Location getLocation() { result = creation.getLocation() }
}

/** A parameter position. */
class ParameterPosition extends TParameterPosition {
/** Gets the underlying integer position, if any. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,12 @@
* Needed for flow through captured variables, where we treat local functions
* as if they were lambdas.
*/
abstract private class LocalFunctionCreationNode extends NodeImpl, TLocalFunctionCreationNode {
private class LocalFunctionCreationNode extends NodeImpl, TLocalFunctionCreationNode {
ControlFlow::Nodes::ElementNode cfn;
LocalFunction function;
boolean isPostUpdate;

LocalFunctionCreationNode() {
this = TLocalFunctionCreationNode(cfn, isPostUpdate) and
this = TLocalFunctionCreationNode(cfn) and
function = cfn.getAstNode().(LocalFunctionStmt).getLocalFunction()
}

Expand All @@ -156,10 +155,6 @@
ControlFlow::Nodes::ElementNode getUnderlyingControlFlowNode() { result = cfn }

override Location getLocationImpl() { result = cfn.getLocation() }
}

private class LocalFunctionCreationPreNode extends LocalFunctionCreationNode {
LocalFunctionCreationPreNode() { isPostUpdate = false }

override string toStringImpl() { result = cfn.toString() }
}
Expand Down Expand Up @@ -419,17 +414,14 @@
result.(Flow::ExprNode).getExpr() =
[
n.(ExprNode).getControlFlowNode(),
n.(LocalFunctionCreationPreNode).getUnderlyingControlFlowNode()
n.(LocalFunctionCreationNode).getUnderlyingControlFlowNode()
]
or
result.(Flow::VariableWriteSourceNode).getVariableWrite().getRhs() =
n.(ExprNode).getControlFlowNode()
or
result.(Flow::ExprPostUpdateNode).getExpr() =
[
n.(PostUpdateNode).getPreUpdateNode().(ExprNode).getControlFlowNode(),
n.(LocalFunctionCreationPostUpdateNode).getUnderlyingControlFlowNode()
]
[n.(PostUpdateNode).getPreUpdateNode().(ExprNode).getControlFlowNode(),]

Check warning

Code scanning / CodeQL

Singleton set literal Warning

Singleton set literal can be replaced by its member.
or
result.(Flow::ParameterNode).getParameter().getParameterNode() = n
or
Expand Down Expand Up @@ -767,6 +759,8 @@
VariableCapture::valueStep(nodeFrom, nodeTo)
or
nodeTo = nodeFrom.(LocalFunctionCreationNode).getAnAccess(true)
or
delegateCreationStep(nodeFrom, nodeTo)
) and
model = ""
or
Expand Down Expand Up @@ -1073,7 +1067,7 @@
l = c.getARelevantLocation()
} or
TDelegateSelfReferenceNode(Callable c) { lambdaCreationExpr(_, c) } or
TLocalFunctionCreationNode(ControlFlow::Nodes::ElementNode cfn, Boolean isPostUpdate) {
TLocalFunctionCreationNode(ControlFlow::Nodes::ElementNode cfn) {
cfn.getAstNode() instanceof LocalFunctionStmt
} or
TYieldReturnNode(ControlFlow::Nodes::ElementNode cfn) {
Expand Down Expand Up @@ -1150,13 +1144,22 @@
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
TDelegateCallArgumentContent(int i) {
i = [0 .. max(any(DelegateLikeCall dc).getNumberOfArguments()) - 1]
or
i in [0 .. 1000] // todo
or
// exists(ArgumentPosition apos |
// FlowSummaryImpl::Private::summaryArgumentNode(_, _, apos) and
// i = apos.getPosition()
// )
i = -1
} or
TDelegateCallReturnContent()

cached
newtype TContentSet =
TSingletonContent(Content c) { not c instanceof PropertyContent } or
TPropertyContentSet(Property p) { p.isUnboundDeclaration() }
TPropertyContentSet(Property p) { p.isUnboundDeclaration() } or
TVariableCaptureContentSet()

cached
newtype TContentApprox =
Expand Down Expand Up @@ -2600,7 +2603,7 @@
or
[
n.asExpr().(ControlFlowElement),
n.(LocalFunctionCreationPreNode).getUnderlyingControlFlowNode().getAstNode()
n.(LocalFunctionCreationNode).getUnderlyingControlFlowNode().getAstNode()
] = result.getADelegateCreation()
}

Expand Down Expand Up @@ -2835,16 +2838,6 @@
override string toStringImpl() { result = "[post] this" }
}

class LocalFunctionCreationPostUpdateNode extends LocalFunctionCreationNode, PostUpdateNode {
LocalFunctionCreationPostUpdateNode() { isPostUpdate = true }

override LocalFunctionCreationPreNode getPreUpdateNode() {
result = TLocalFunctionCreationNode(cfn, false)
}

override string toStringImpl() { result = "[post] " + cfn }
}

private class CapturePostUpdateNode extends PostUpdateNode, CaptureNode {
private CaptureNode pre;

Expand Down Expand Up @@ -2908,7 +2901,11 @@
* Holds if access paths with `c` at their head always should be tracked at high
* precision. This disables adaptive access path precision for such access paths.
*/
predicate forceHighPrecision(Content c) { c instanceof ElementContent }
predicate forceHighPrecision(Content c) {
c instanceof ElementContent or
c instanceof DelegateCallArgumentContent or
c instanceof DelegateCallReturnContent
}

private predicate lambdaCreationExpr(ControlFlowElement creation, Callable c) {
c =
Expand All @@ -2924,10 +2921,42 @@

/** Holds if `creation` is an expression that creates a delegate for `c`. */
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
lambdaCreationExpr(creation.asExpr(), c.asCallable(_)) and
(
lambdaCreationExpr(creation.asExpr(), c.asCallable(_))
or
creation.(LocalFunctionCreationNode).getFunction() = c.asCallable(_)
) and
exists(kind)
}

/** Holds if `creation` is an expression that creates a delegate for `c`. */
predicate lambdaCreation(
Node creation, LambdaCallKind kind, DataFlowCallable c, DataFlowCall synthCall
) {
lambdaCreation(creation, kind, c) and
synthCall = TLambdaSynthCall(creation)
}

Content getLambdaReturnContent(LambdaCallKind kind, ReturnKind rk) {
result = TDelegateCallReturnContent() and
exists(kind) and
rk = TNormalReturnKind()
}

Content getLambdaArgumentContent(LambdaCallKind kind, ArgumentPosition pos) {
(
result = TDelegateCallArgumentContent(pos.getPosition())
or
result = TDelegateCallArgumentContent(-1) and
pos.isDelegateSelf()
) and
exists(kind)
}

predicate isLambdaInstanceParameter(ParameterNode p) { p instanceof DelegateSelfReferenceNode }

predicate isVariableCaptureContentSet(ContentSet c) { c.isCapturedVariable() }

private predicate isLocalFunctionCallReceiver(
LocalFunctionCall call, LocalFunctionAccess receiver, LocalFunction f
) {
Expand Down Expand Up @@ -2973,9 +3002,7 @@
/** Holds if `call` is a lambda call where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
(
lambdaCallExpr(call, receiver.(ExprNode).getControlFlowNode()) and
// local function calls can be resolved directly without a flow analysis
not call.getControlFlowNode().getAstNode() instanceof LocalFunctionCall
lambdaCallExpr(call, receiver.(ExprNode).getControlFlowNode()) //and
or
receiver.(FlowSummaryNode).getSummaryNode() = call.(SummaryCall).getReceiver()
) and
Expand Down Expand Up @@ -3052,6 +3079,8 @@
or
VariableCapture::Flow::heuristicAllowInstanceParameterReturnInSelf(p.(DelegateSelfReferenceNode)
.getCallable())
or
p.getType() instanceof SystemLinqExpressions::DelegateExtType
}

/** An approximated `Content`. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ private import DataFlowDispatch
private import DataFlowPrivate
private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.Unification
private import semmle.code.csharp.frameworks.system.linq.Expressions

/**
* An element, viewed as a node in a data flow graph. Either an expression
Expand Down Expand Up @@ -324,6 +323,8 @@ class ContentSet extends TContentSet {
*/
predicate isProperty(Property p) { this = TPropertyContentSet(p) }

predicate isCapturedVariable() { this = TVariableCaptureContentSet() }

/**
* Holds if this content set represents the `i`th argument of a delegate call.
*/
Expand Down Expand Up @@ -362,6 +363,9 @@ class ContentSet extends TContentSet {
or
overridesOrImplementsSourceDecl(p1, p2)
)
or
this.isCapturedVariable() and
result instanceof CapturedVariableContent
}

/** Gets a textual representation of this content set. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

private import csharp
private import semmle.code.csharp.commons.QualifiedName
private import semmle.code.csharp.frameworks.system.linq.Expressions
private import codeql.dataflow.internal.FlowSummaryImpl
private import codeql.dataflow.internal.AccessPathSyntax as AccessPath
private import DataFlowImplSpecific as DataFlowImplSpecific
Expand Down
11 changes: 0 additions & 11 deletions csharp/ql/test/library-tests/arguments/lambdaArgument.expected
Original file line number Diff line number Diff line change
@@ -1,11 +0,0 @@
| lambdas.cs:8:9:8:13 | delegate call | lambdas.cs:7:23:7:23 | x | lambdas.cs:8:12:8:12 | 1 |
| lambdas.cs:11:9:11:16 | delegate call | lambdas.cs:10:23:10:23 | x | lambdas.cs:11:12:11:12 | 2 |
| lambdas.cs:11:9:11:16 | delegate call | lambdas.cs:10:30:10:30 | y | lambdas.cs:11:15:11:15 | 3 |
| lambdas.cs:12:9:12:13 | delegate call | lambdas.cs:10:23:10:23 | x | lambdas.cs:12:12:12:12 | 4 |
| lambdas.cs:13:9:13:16 | delegate call | lambdas.cs:10:23:10:23 | x | lambdas.cs:13:12:13:12 | 5 |
| lambdas.cs:13:9:13:16 | delegate call | lambdas.cs:10:30:10:30 | y | lambdas.cs:13:15:13:15 | 6 |
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:12:17:12 | 7 |
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:15:17:15 | 8 |
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:18:17:18 | 9 |
| lambdas.cs:25:9:25:23 | delegate call | lambdas.cs:24:31:24:31 | x | lambdas.cs:25:22:25:22 | 5 |
| lambdas.cs:25:9:25:23 | delegate call | lambdas.cs:24:38:24:38 | y | lambdas.cs:25:16:25:16 | 4 |
18 changes: 18 additions & 0 deletions csharp/ql/test/library-tests/csharp7/GlobalFlow.expected
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,21 @@ edges
| CSharp7.cs:175:16:175:18 | access to local variable src : String | CSharp7.cs:181:23:181:25 | access to local variable src : String | provenance | |
| CSharp7.cs:175:16:175:18 | access to local variable src : String | CSharp7.cs:182:23:182:25 | access to local variable src : String | provenance | |
| CSharp7.cs:175:22:175:30 | "tainted" : String | CSharp7.cs:175:16:175:18 | access to local variable src : String | provenance | |
| CSharp7.cs:177:9:177:32 | g(...) : g [delegate return] : String | CSharp7.cs:181:21:181:21 | access to local function g : g [delegate return] : String | provenance | |
| CSharp7.cs:177:25:177:25 | s : String | CSharp7.cs:177:31:177:31 | access to parameter s : String | provenance | |
| CSharp7.cs:178:9:178:40 | h(...) : h [delegate return] : String | CSharp7.cs:182:21:182:21 | access to local function h : h [delegate return] : String | provenance | |
| CSharp7.cs:178:25:178:25 | s : String | CSharp7.cs:178:37:178:37 | access to parameter s : String | provenance | |
| CSharp7.cs:181:21:181:21 | [post] access to local function g : null [delegate argument at position 0] : String | CSharp7.cs:177:9:177:32 | g(...) : g [delegate return] : String | provenance | |
| CSharp7.cs:181:21:181:21 | [post] access to local function g : null [delegate argument at position 0] : String | CSharp7.cs:177:25:177:25 | s : String | provenance | |
| CSharp7.cs:181:21:181:21 | access to local function g : g [delegate return] : String | CSharp7.cs:181:21:181:26 | call to local function g | provenance | |
| CSharp7.cs:181:23:181:25 | access to local variable src : String | CSharp7.cs:177:25:177:25 | s : String | provenance | |
| CSharp7.cs:181:23:181:25 | access to local variable src : String | CSharp7.cs:181:21:181:21 | [post] access to local function g : null [delegate argument at position 0] : String | provenance | |
| CSharp7.cs:181:23:181:25 | access to local variable src : String | CSharp7.cs:181:21:181:26 | call to local function g | provenance | |
| CSharp7.cs:182:21:182:21 | [post] access to local function h : null [delegate argument at position 0] : String | CSharp7.cs:178:9:178:40 | h(...) : h [delegate return] : String | provenance | |
| CSharp7.cs:182:21:182:21 | [post] access to local function h : null [delegate argument at position 0] : String | CSharp7.cs:178:25:178:25 | s : String | provenance | |
| CSharp7.cs:182:21:182:21 | access to local function h : h [delegate return] : String | CSharp7.cs:182:21:182:26 | call to local function h | provenance | |
| CSharp7.cs:182:23:182:25 | access to local variable src : String | CSharp7.cs:178:25:178:25 | s : String | provenance | |
| CSharp7.cs:182:23:182:25 | access to local variable src : String | CSharp7.cs:182:21:182:21 | [post] access to local function h : null [delegate argument at position 0] : String | provenance | |
| CSharp7.cs:182:23:182:25 | access to local variable src : String | CSharp7.cs:182:21:182:26 | call to local function h | provenance | |
nodes
| CSharp7.cs:39:9:39:9 | access to parameter x : String | semmle.label | access to parameter x : String |
Expand All @@ -47,18 +57,26 @@ nodes
| CSharp7.cs:175:16:175:18 | access to local variable src : String | semmle.label | access to local variable src : String |
| CSharp7.cs:175:22:175:30 | "tainted" | semmle.label | "tainted" |
| CSharp7.cs:175:22:175:30 | "tainted" : String | semmle.label | "tainted" : String |
| CSharp7.cs:177:9:177:32 | g(...) : g [delegate return] : String | semmle.label | g(...) : g [delegate return] : String |
| CSharp7.cs:177:25:177:25 | s : String | semmle.label | s : String |
| CSharp7.cs:177:31:177:31 | access to parameter s : String | semmle.label | access to parameter s : String |
| CSharp7.cs:178:9:178:40 | h(...) : h [delegate return] : String | semmle.label | h(...) : h [delegate return] : String |
| CSharp7.cs:178:25:178:25 | s : String | semmle.label | s : String |
| CSharp7.cs:178:37:178:37 | access to parameter s : String | semmle.label | access to parameter s : String |
| CSharp7.cs:181:21:181:21 | [post] access to local function g : null [delegate argument at position 0] : String | semmle.label | [post] access to local function g : null [delegate argument at position 0] : String |
| CSharp7.cs:181:21:181:21 | access to local function g : g [delegate return] : String | semmle.label | access to local function g : g [delegate return] : String |
| CSharp7.cs:181:21:181:26 | call to local function g | semmle.label | call to local function g |
| CSharp7.cs:181:23:181:25 | access to local variable src : String | semmle.label | access to local variable src : String |
| CSharp7.cs:182:21:182:21 | [post] access to local function h : null [delegate argument at position 0] : String | semmle.label | [post] access to local function h : null [delegate argument at position 0] : String |
| CSharp7.cs:182:21:182:21 | access to local function h : h [delegate return] : String | semmle.label | access to local function h : h [delegate return] : String |
| CSharp7.cs:182:21:182:26 | call to local function h | semmle.label | call to local function h |
| CSharp7.cs:182:23:182:25 | access to local variable src : String | semmle.label | access to local variable src : String |
subpaths
| CSharp7.cs:55:11:55:19 | "tainted" : String | CSharp7.cs:42:19:42:19 | x : String | CSharp7.cs:44:9:44:9 | access to parameter y : String | CSharp7.cs:55:30:55:31 | String t4 : String |
| CSharp7.cs:90:20:90:27 | access to field Item1 : String | CSharp7.cs:80:21:80:21 | x : String | CSharp7.cs:82:16:82:26 | access to field Item1 : String | CSharp7.cs:90:18:90:28 | call to method I |
| CSharp7.cs:181:21:181:21 | [post] access to local function g : null [delegate argument at position 0] : String | CSharp7.cs:177:25:177:25 | s : String | CSharp7.cs:177:31:177:31 | access to parameter s : String | CSharp7.cs:177:9:177:32 | g(...) : g [delegate return] : String |
| CSharp7.cs:181:23:181:25 | access to local variable src : String | CSharp7.cs:177:25:177:25 | s : String | CSharp7.cs:177:31:177:31 | access to parameter s : String | CSharp7.cs:181:21:181:26 | call to local function g |
| CSharp7.cs:182:21:182:21 | [post] access to local function h : null [delegate argument at position 0] : String | CSharp7.cs:178:25:178:25 | s : String | CSharp7.cs:178:37:178:37 | access to parameter s : String | CSharp7.cs:178:9:178:40 | h(...) : h [delegate return] : String |
| CSharp7.cs:182:23:182:25 | access to local variable src : String | CSharp7.cs:178:25:178:25 | s : String | CSharp7.cs:178:37:178:37 | access to parameter s : String | CSharp7.cs:182:21:182:26 | call to local function h |
#select
| CSharp7.cs:39:13:39:21 | "tainted" : String | CSharp7.cs:39:13:39:21 | "tainted" : String | CSharp7.cs:51:18:51:19 | access to local variable t1 | $@ | CSharp7.cs:51:18:51:19 | access to local variable t1 | access to local variable t1 |
Expand Down
Loading
Loading