Skip to content

Commit 59d87e2

Browse files
authored
Merge pull request github#4557 from hvitved/csharp/dataflow/parameters
C#: Simpler data-flow modelling of parameters
2 parents b6007cf + e6f81bc commit 59d87e2

File tree

11 files changed

+105
-139
lines changed

11 files changed

+105
-139
lines changed

csharp/ql/src/semmle/code/cil/Declaration.qll

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ class Declaration extends DotNet::Declaration, Element, @cil_declaration {
2424

2525
override Declaration getUnboundDeclaration() { result = this }
2626

27-
/** Holds if this declaration is a source declaration. */
28-
final predicate isUnboundDeclaration() { this = getUnboundDeclaration() }
29-
3027
/**
3128
* DEPRECATED: Use `isUnboundDeclaration()` instead.
3229
*

csharp/ql/src/semmle/code/csharp/Member.qll

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ private import TypeRef
1616
class Declaration extends DotNet::Declaration, Element, @declaration {
1717
override ValueOrRefType getDeclaringType() { none() }
1818

19-
/** Holds if this declaration is unbound. */
20-
final predicate isUnboundDeclaration() { this = this.getUnboundDeclaration() }
21-
2219
/** Holds if this declaration is unconstructed and in source code. */
2320
final predicate isSourceDeclaration() { this.fromSource() and this.isUnboundDeclaration() }
2421

csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ class SummaryDelegateCall extends DelegateDataFlowCall, TSummaryDelegateCall {
391391

392392
override DataFlowCallable getARuntimeTarget(CallContext::CallContext cc) {
393393
exists(SummaryDelegateParameterSink p |
394-
p = TSummaryParameterNode(c, pos) and
394+
p.isParameterOf(c, pos) and
395395
result = p.getARuntimeTarget(cc)
396396
)
397397
}

csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 35 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,20 @@ module LocalFlow {
278278
)
279279
}
280280

281+
private Ssa::Definition getSsaDefinition(Node n) {
282+
result = n.(SsaDefinitionNode).getDefinition()
283+
or
284+
result = n.(ExplicitParameterNode).getSsaDefinition()
285+
}
286+
281287
/**
282288
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
283289
* SSA definition `def.
284290
*/
285291
predicate localSsaFlowStep(Ssa::Definition def, Node nodeFrom, Node nodeTo) {
286-
// Flow from SSA definition to first read
292+
// Flow from SSA definition/parameter to first read
287293
exists(ControlFlow::Node cfn |
288-
def = nodeFrom.(SsaDefinitionNode).getDefinition() and
294+
def = getSsaDefinition(nodeFrom) and
289295
nodeTo.asExprAtNode(cfn) = def.getAFirstReadAtNode(cfn)
290296
)
291297
or
@@ -323,11 +329,10 @@ module LocalFlow {
323329
)
324330
}
325331

326-
predicate localFlowCapturedVarStep(SsaDefinitionNode nodeFrom, ImplicitCapturedArgumentNode nodeTo) {
332+
predicate localFlowCapturedVarStep(Node nodeFrom, ImplicitCapturedArgumentNode nodeTo) {
327333
// Flow from SSA definition to implicit captured variable argument
328334
exists(Ssa::ExplicitDefinition def, ControlFlow::Nodes::ElementNode call |
329-
def = nodeFrom.getDefinition()
330-
|
335+
def = getSsaDefinition(nodeFrom) and
331336
def.isCapturedVariableDefinitionFlowIn(_, call, _) and
332337
nodeTo = TImplicitCapturedArgumentNode(call, def.getSourceVariable().getAssignable())
333338
)
@@ -569,9 +574,15 @@ private module Cached {
569574
Stages::DataFlowStage::forceCachingInSameStage() and cfn.getElement() instanceof Expr
570575
} or
571576
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
572-
TSsaDefinitionNode(Ssa::Definition def) or
573-
TInstanceParameterNode(Callable c) { c.hasBody() and not c.(Modifiable).isStatic() } or
574-
TCilParameterNode(CIL::MethodParameter p) { p.getMethod().hasBody() } or
577+
TSsaDefinitionNode(Ssa::Definition def) {
578+
// Handled by `TExplicitParameterNode` below
579+
not def.(Ssa::ExplicitDefinition).getADefinition() instanceof
580+
AssignableDefinitions::ImplicitParameterDefinition
581+
} or
582+
TExplicitParameterNode(DotNet::Parameter p) { p.isUnboundDeclaration() } or
583+
TInstanceParameterNode(Callable c) {
584+
c.isUnboundDeclaration() and not c.(Modifiable).isStatic()
585+
} or
575586
TYieldReturnNode(ControlFlow::Nodes::ElementNode cfn) {
576587
any(Callable c).canYieldReturn(cfn.getElement())
577588
} or
@@ -605,18 +616,6 @@ private module Cached {
605616
cfn.getElement() = fla.getQualifier()
606617
)
607618
} or
608-
TSummaryParameterNode(SummarizedCallable c, int i) {
609-
exists(SummaryInput input | FlowSummaryImpl::Private::summary(c, input, _, _, _, _) |
610-
input = SummaryInput::parameter(i)
611-
or
612-
input = SummaryInput::delegate(i)
613-
)
614-
or
615-
exists(SummaryOutput output |
616-
FlowSummaryImpl::Private::summary(c, _, _, output, _, _) and
617-
output = SummaryOutput::delegate(i, _)
618-
)
619-
} or
620619
TSummaryInternalNode(
621620
SummarizedCallable c, FlowSummaryImpl::Private::SummaryInternalNodeState state
622621
) {
@@ -801,12 +800,10 @@ private module Cached {
801800
cached
802801
predicate isUnreachableInCall(Node n, DataFlowCall call) {
803802
exists(
804-
SsaDefinitionNode paramNode, Ssa::ExplicitDefinition param, Guard guard,
805-
ControlFlow::SuccessorTypes::BooleanSuccessor bs
803+
ExplicitParameterNode paramNode, Guard guard, ControlFlow::SuccessorTypes::BooleanSuccessor bs
806804
|
807805
viableConstantBooleanParamArg(paramNode, bs.getValue().booleanNot(), call) and
808-
paramNode.getDefinition() = param and
809-
param.getARead() = guard and
806+
paramNode.getSsaDefinition().getARead() = guard and
810807
guard.controlsBlock(n.getControlFlowNode().getBasicBlock(), bs, _)
811808
)
812809
}
@@ -874,6 +871,11 @@ private module Cached {
874871
def instanceof Ssa::ImplicitCallDefinition
875872
)
876873
or
874+
exists(Parameter p |
875+
p = n.(ParameterNode).getParameter() and
876+
not p.fromSource()
877+
)
878+
or
877879
n instanceof YieldReturnNode
878880
or
879881
n instanceof ImplicitCapturedArgumentNode
@@ -905,33 +907,25 @@ class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
905907

906908
override Location getLocationImpl() { result = def.getLocation() }
907909

908-
override string toStringImpl() {
909-
not explicitParameterNode(this, _) and
910-
result = def.toString()
911-
}
910+
override string toStringImpl() { result = def.toString() }
912911
}
913912

914913
private module ParameterNodes {
915914
abstract private class ParameterNodeImpl extends ParameterNode, NodeImpl { }
916915

917-
/**
918-
* Holds if definition node `node` is an entry definition for parameter `p`.
919-
*/
920-
predicate explicitParameterNode(AssignableDefinitionNode node, Parameter p) {
921-
p = node.getDefinition().(AssignableDefinitions::ImplicitParameterDefinition).getParameter()
922-
}
923-
924916
/**
925917
* The value of an explicit parameter at function entry, viewed as a node in a data
926918
* flow graph.
927919
*/
928-
class ExplicitParameterNode extends ParameterNodeImpl {
920+
class ExplicitParameterNode extends ParameterNodeImpl, TExplicitParameterNode {
929921
private DotNet::Parameter parameter;
930922

931-
ExplicitParameterNode() {
932-
explicitParameterNode(this, parameter)
933-
or
934-
this = TCilParameterNode(parameter)
923+
ExplicitParameterNode() { this = TExplicitParameterNode(parameter) }
924+
925+
/** Gets the SSA definition corresponding to this parameter, if any. */
926+
Ssa::ExplicitDefinition getSsaDefinition() {
927+
result.getADefinition().(AssignableDefinitions::ImplicitParameterDefinition).getParameter() =
928+
this.getParameter()
935929
}
936930

937931
override DotNet::Parameter getParameter() { result = parameter }
@@ -1037,46 +1031,6 @@ private module ParameterNodes {
10371031
c = this.getEnclosingCallable()
10381032
}
10391033
}
1040-
1041-
/** A parameter node for a callable with a flow summary. */
1042-
class SummaryParameterNode extends ParameterNodeImpl, SummaryNodeImpl, TSummaryParameterNode {
1043-
private SummarizedCallable sc;
1044-
private int i;
1045-
1046-
SummaryParameterNode() { this = TSummaryParameterNode(sc, i) }
1047-
1048-
override Parameter getParameter() { result = sc.getParameter(i) }
1049-
1050-
override predicate isParameterOf(DataFlowCallable c, int pos) {
1051-
c = sc and
1052-
pos = i
1053-
}
1054-
1055-
override Callable getEnclosingCallableImpl() { result = sc }
1056-
1057-
override Type getTypeImpl() {
1058-
result = sc.getParameter(i).getType()
1059-
or
1060-
i = -1 and
1061-
result = sc.getDeclaringType()
1062-
}
1063-
1064-
override ControlFlow::Node getControlFlowNodeImpl() { none() }
1065-
1066-
override Location getLocationImpl() {
1067-
result = sc.getParameter(i).getLocation()
1068-
or
1069-
i = -1 and
1070-
result = sc.getLocation()
1071-
}
1072-
1073-
override string toStringImpl() {
1074-
result = "[summary] " + sc.getParameter(i)
1075-
or
1076-
i = -1 and
1077-
result = "[summary] this"
1078-
}
1079-
}
10801034
}
10811035

10821036
import ParameterNodes
@@ -1934,7 +1888,7 @@ private class ConstantBooleanArgumentNode extends ExprNode {
19341888

19351889
pragma[noinline]
19361890
private predicate viableConstantBooleanParamArg(
1937-
SsaDefinitionNode paramNode, boolean b, DataFlowCall call
1891+
ParameterNode paramNode, boolean b, DataFlowCall call
19381892
) {
19391893
exists(ConstantBooleanArgumentNode arg |
19401894
viableParamArg(call, paramNode, arg) and

csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,10 @@ class ExprNode extends Node {
119119
class ParameterNode extends Node {
120120
ParameterNode() {
121121
// charpred needed to avoid making `ParameterNode` abstract
122-
explicitParameterNode(this, _) or
122+
this = TExplicitParameterNode(_) or
123123
this.(SsaDefinitionNode).getDefinition() instanceof
124124
ImplicitCapturedParameterNodeImpl::SsaCapturedEntryDefinition or
125-
this = TInstanceParameterNode(_) or
126-
this = TCilParameterNode(_) or
127-
this = TSummaryParameterNode(_, _)
125+
this = TInstanceParameterNode(_)
128126
}
129127

130128
/** Gets the parameter corresponding to this node, if any. */

csharp/ql/src/semmle/code/csharp/dataflow/internal/DelegateDataFlow.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ private import semmle.code.csharp.dataflow.CallContext
1010
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
1111
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
1212
private import semmle.code.csharp.dataflow.internal.DataFlowPublic
13+
private import semmle.code.csharp.dataflow.FlowSummary
1314
private import semmle.code.csharp.dispatch.Dispatch
1415
private import semmle.code.csharp.frameworks.system.linq.Expressions
1516

@@ -102,9 +103,10 @@ class DelegateCallExpr extends DelegateFlowSink, DataFlow::ExprNode {
102103
}
103104

104105
/** A parameter of delegate type belonging to a callable with a flow summary. */
105-
class SummaryDelegateParameterSink extends DelegateFlowSink, SummaryParameterNode {
106+
class SummaryDelegateParameterSink extends DelegateFlowSink, ParameterNode {
106107
SummaryDelegateParameterSink() {
107-
this.getType() instanceof SystemLinqExpressions::DelegateExtType
108+
this.getType() instanceof SystemLinqExpressions::DelegateExtType and
109+
this.isParameterOf(any(SummarizedCallable c), _)
108110
}
109111
}
110112

csharp/ql/src/semmle/code/csharp/dataflow/internal/FlowSummarySpecific.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ module Private {
8787
NodeImpl inputNode(SummarizableCallable c, SummaryInput input) {
8888
exists(int i |
8989
input = TParameterSummaryInput(i) and
90-
result = DataFlowPrivate::TSummaryParameterNode(c, i)
90+
result.(ParameterNode).isParameterOf(c, i)
9191
)
9292
or
9393
exists(int i |

csharp/ql/src/semmle/code/dotnet/Declaration.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ class Declaration extends NamedElement, @dotnet_declaration {
5252
* | `C<int>.Method<string>` | `C<>.Method<>` |
5353
*/
5454
Declaration getUnboundDeclaration() { result = this }
55+
56+
/** Holds if this declaration is unbound. */
57+
final predicate isUnboundDeclaration() { this.getUnboundDeclaration() = this }
5558
}
5659

5760
/** A member of a type. */

csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
| CSharp7.cs:7:7:7:14 | this | CSharp7.cs:9:9:9:9 | this access |
12
| CSharp7.cs:9:9:9:9 | [post] this access | CSharp7.cs:10:9:10:9 | this access |
23
| CSharp7.cs:9:9:9:9 | this access | CSharp7.cs:10:9:10:9 | this access |
34
| CSharp7.cs:10:9:10:9 | [post] this access | CSharp7.cs:11:9:11:9 | this access |

csharp/ql/test/library-tests/dataflow/delegates/DelegateFlow.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
summaryDelegateCall
2-
| file://:0:0:0:0 | [summary] valueFactory | DelegateFlow.cs:104:23:104:30 | (...) => ... | DelegateFlow.cs:105:23:105:23 | access to local variable f |
3-
| file://:0:0:0:0 | [summary] valueFactory | DelegateFlow.cs:106:13:106:20 | (...) => ... | DelegateFlow.cs:107:23:107:23 | access to local variable f |
2+
| file://:0:0:0:0 | valueFactory | DelegateFlow.cs:104:23:104:30 | (...) => ... | DelegateFlow.cs:105:23:105:23 | access to local variable f |
3+
| file://:0:0:0:0 | valueFactory | DelegateFlow.cs:106:13:106:20 | (...) => ... | DelegateFlow.cs:107:23:107:23 | access to local variable f |
44
delegateCall
55
| DelegateFlow.cs:9:9:9:12 | delegate call | DelegateFlow.cs:5:10:5:11 | M1 | DelegateFlow.cs:17:12:17:13 | delegate creation of type Action<Int32> |
66
| DelegateFlow.cs:9:9:9:12 | delegate call | DelegateFlow.cs:5:10:5:11 | M1 | DelegateFlow.cs:22:12:22:12 | access to parameter a |

0 commit comments

Comments
 (0)