Skip to content

Commit fdda514

Browse files
committed
C#: Add new class AssignableDefinitionNode to the data-flow library
1 parent d0ac846 commit fdda514

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

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

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -554,15 +554,10 @@ class SsaDefinitionNode extends Node, TSsaDefinitionNode {
554554

555555
private module ParameterNodes {
556556
/**
557-
* Holds if SSA definition node `node` is an entry definition for parameter `p`.
557+
* Holds if definition node `node` is an entry definition for parameter `p`.
558558
*/
559-
predicate explicitParameterNode(SsaDefinitionNode node, Parameter p) {
560-
exists(Ssa::ExplicitDefinition def, AssignableDefinitions::ImplicitParameterDefinition pdef |
561-
node = TSsaDefinitionNode(def)
562-
|
563-
pdef = def.getADefinition() and
564-
p = pdef.getParameter()
565-
)
559+
predicate explicitParameterNode(AssignableDefinitionNode node, Parameter p) {
560+
p = node.getDefinition().(AssignableDefinitions::ImplicitParameterDefinition).getParameter()
566561
}
567562

568563
/**
@@ -1126,13 +1121,14 @@ private module OutNodes {
11261121
* A data flow node that reads a value returned by a callable using an
11271122
* `out` or `ref` parameter.
11281123
*/
1129-
class ParamOutNode extends OutNode, SsaDefinitionNode {
1124+
class ParamOutNode extends OutNode, AssignableDefinitionNode {
11301125
private AssignableDefinitions::OutRefDefinition outRefDef;
1126+
private ControlFlow::Node cfn;
11311127

1132-
ParamOutNode() { outRefDef = this.getDefinition().(Ssa::ExplicitDefinition).getADefinition() }
1128+
ParamOutNode() { outRefDef = this.getDefinitionAtNode(cfn) }
11331129

11341130
override DataFlowCall getCall(ReturnKind kind) {
1135-
result = csharpCall(_, this.getDefinition().getControlFlowNode()) and
1131+
result = csharpCall(_, cfn) and
11361132
exists(Parameter p |
11371133
p.getSourceDeclaration().getPosition() = kind.(OutRefReturnKind).getPosition() and
11381134
outRefDef.getTargetAccess() = result.getExpr().(Call).getArgumentForParameter(p)
@@ -1458,10 +1454,8 @@ class CastNode extends Node {
14581454
CastNode() {
14591455
this.asExpr() instanceof Cast
14601456
or
1461-
exists(Ssa::ExplicitDefinition def |
1462-
def = this.(SsaDefinitionNode).getDefinition() and
1463-
def.getADefinition() instanceof AssignableDefinitions::PatternDefinition
1464-
)
1457+
this.(AssignableDefinitionNode).getDefinition() instanceof
1458+
AssignableDefinitions::PatternDefinition
14651459
or
14661460
readStep(_, _, this)
14671461
or

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

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,23 @@ class Node extends TNode {
1919
* if any.
2020
*/
2121
Expr asExprAtNode(ControlFlow::Nodes::ElementNode cfn) {
22-
this = TExprNode(cfn) and
23-
result = cfn.getElement()
22+
result = this.(ExprNode).getExprAtNode(cfn)
2423
}
2524

2625
/** Gets the parameter corresponding to this node, if any. */
2726
DotNet::Parameter asParameter() { result = this.(ParameterNode).getParameter() }
2827

28+
/** Gets the definition corresponding to this node, if any. */
29+
AssignableDefinition asDefinition() { result = this.asDefinitionAtNode(_) }
30+
31+
/**
32+
* Gets the definition corresponding to this node, at control flow node `cfn`,
33+
* if any.
34+
*/
35+
AssignableDefinition asDefinitionAtNode(ControlFlow::Node cfn) {
36+
result = this.(AssignableDefinitionNode).getDefinitionAtNode(cfn)
37+
}
38+
2939
/** Gets the type of this node. */
3040
cached
3141
DotNet::Type getType() { none() }
@@ -140,6 +150,22 @@ class ParameterNode extends Node {
140150
predicate isParameterOf(DataFlowCallable c, int i) { none() }
141151
}
142152

153+
/** A definition, viewed as a node in a data flow graph. */
154+
class AssignableDefinitionNode extends Node, TSsaDefinitionNode {
155+
private Ssa::ExplicitDefinition edef;
156+
157+
AssignableDefinitionNode() { this = TSsaDefinitionNode(edef) }
158+
159+
/** Gets the underlying definition. */
160+
AssignableDefinition getDefinition() { result = this.getDefinitionAtNode(_) }
161+
162+
/** Gets the underlying definition, at control flow node `cfn`, if any. */
163+
AssignableDefinition getDefinitionAtNode(ControlFlow::Node cfn) {
164+
result = edef.getADefinition() and
165+
cfn = edef.getControlFlowNode()
166+
}
167+
}
168+
143169
/** Gets a node corresponding to expression `e`. */
144170
ExprNode exprNode(DotNet::Expr e) { result.getExpr() = e }
145171

@@ -148,6 +174,11 @@ ExprNode exprNode(DotNet::Expr e) { result.getExpr() = e }
148174
*/
149175
ParameterNode parameterNode(DotNet::Parameter p) { result.getParameter() = p }
150176

177+
/** Gets a node corresponding to the definition `def`. */
178+
AssignableDefinitionNode assignableDefinitionNode(AssignableDefinition def) {
179+
result.getDefinition() = def
180+
}
181+
151182
/**
152183
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
153184
* (intra-procedural) step.

0 commit comments

Comments
 (0)