Skip to content

Commit 3593806

Browse files
authored
Merge pull request #11517 from aibaars/phi-reads-in-data-flow-graph
Ruby: Include SSA "phi reads" in DataFlow::Node
2 parents 898a400 + d862972 commit 3593806

File tree

9 files changed

+6211
-222
lines changed

9 files changed

+6211
-222
lines changed

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,10 @@ private predicate selfInToplevel(SelfVariable self, Module m) {
237237
*
238238
* the SSA definition for `c` is introduced by matching on `C`.
239239
*/
240-
private predicate asModulePattern(SsaDefinitionNode def, Module m) {
240+
private predicate asModulePattern(SsaDefinitionExtNode def, Module m) {
241241
exists(AsPattern ap |
242242
m = resolveConstantReadAccess(ap.getPattern()) and
243-
def.getDefinition().(Ssa::WriteDefinition).getWriteAccess() = ap.getVariableAccess()
243+
def.getDefinitionExt().(Ssa::WriteDefinition).getWriteAccess() = ap.getVariableAccess()
244244
)
245245
}
246246

@@ -982,15 +982,15 @@ private DataFlow::Node trackSingletonMethodOnInstance(MethodBase method, string
982982
*/
983983
pragma[nomagic]
984984
private predicate argMustFlowToReceiver(
985-
RelevantCall ctx, DataFlow::LocalSourceNode source, ArgumentNode arg, SsaDefinitionNode paramDef,
986-
RelevantCall call, Callable encl, string name
985+
RelevantCall ctx, DataFlow::LocalSourceNode source, ArgumentNode arg,
986+
SsaDefinitionExtNode paramDef, RelevantCall call, Callable encl, string name
987987
) {
988988
exists(ParameterNodeImpl p, ParameterPosition ppos, ArgumentPosition apos |
989989
// the receiver of `call` references `p`
990990
exists(DataFlow::Node receiver |
991991
LocalFlow::localFlowSsaParamInput(p, paramDef) and
992992
methodCall(pragma[only_bind_into](call), receiver, pragma[only_bind_into](name)) and
993-
receiver.asExpr() = paramDef.getDefinition().getARead()
993+
receiver.asExpr() = paramDef.getDefinitionExt().(Ssa::Definition).getARead()
994994
) and
995995
// `p` is a parameter of `encl`,
996996
encl = call.getScope() and

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -75,44 +75,54 @@ CfgNodes::ExprCfgNode getAPostUpdateNodeForArg(Argument arg) {
7575
module LocalFlow {
7676
private import codeql.ruby.dataflow.internal.SsaImpl
7777

78+
/** An SSA definition into which another SSA definition may flow. */
79+
private class SsaInputDefinitionExtNode extends SsaDefinitionExtNode {
80+
SsaInputDefinitionExtNode() {
81+
def instanceof Ssa::PhiNode
82+
or
83+
def instanceof SsaImpl::PhiReadNode
84+
//TODO: or def instanceof LocalFlow::UncertainExplicitSsaDefinition
85+
}
86+
}
87+
7888
/**
7989
* Holds if `nodeFrom` is a node for SSA definition `def`, which can reach `next`.
8090
*/
8191
private predicate localFlowSsaInputFromDef(
82-
SsaDefinitionNode nodeFrom, Ssa::Definition def, Ssa::Definition next
92+
SsaDefinitionExtNode nodeFrom, SsaImpl::DefinitionExt def, SsaInputDefinitionExtNode next
8393
) {
8494
exists(BasicBlock bb, int i |
85-
lastRefBeforeRedef(def, bb, i, next) and
86-
def = nodeFrom.getDefinition() and
87-
def.definesAt(_, bb, i)
95+
lastRefBeforeRedefExt(def, bb, i, next.getDefinitionExt()) and
96+
def = nodeFrom.getDefinitionExt() and
97+
def.definesAt(_, bb, i, _)
8898
)
8999
}
90100

91101
/**
92102
* Holds if `exprFrom` is a last read of SSA definition `def`, which
93103
* can reach `next`.
94104
*/
95-
predicate localFlowSsaInputFromExpr(
96-
CfgNodes::ExprCfgNode exprFrom, Ssa::Definition def, Ssa::Definition next
105+
predicate localFlowSsaInputFromRead(
106+
CfgNodes::ExprCfgNode exprFrom, SsaImpl::DefinitionExt def, SsaInputDefinitionExtNode next
97107
) {
98108
exists(BasicBlock bb, int i |
99-
lastRefBeforeRedef(def, bb, i, next) and
109+
SsaImpl::lastRefBeforeRedefExt(def, bb, i, next.getDefinitionExt()) and
100110
exprFrom = bb.getNode(i) and
101111
exprFrom.getExpr() instanceof VariableReadAccess
102112
)
103113
}
104114

105115
/** Gets the SSA definition node corresponding to parameter `p`. */
106-
SsaDefinitionNode getParameterDefNode(NamedParameter p) {
116+
SsaDefinitionExtNode getParameterDefNode(NamedParameter p) {
107117
exists(BasicBlock bb, int i |
108118
bb.getNode(i).getNode() = p.getDefiningAccess() and
109-
result.getDefinition().definesAt(_, bb, i)
119+
result.getDefinitionExt().definesAt(_, bb, i, _)
110120
)
111121
}
112122

113123
/** Gets the SSA definition node corresponding to the implicit `self` parameter for `m`. */
114-
private SsaDefinitionNode getSelfParameterDefNode(MethodBase m) {
115-
result.getDefinition().(Ssa::SelfDefinition).getSourceVariable().getDeclaringScope() = m
124+
private SsaDefinitionExtNode getSelfParameterDefNode(MethodBase m) {
125+
result.getDefinitionExt().(Ssa::SelfDefinition).getSourceVariable().getDeclaringScope() = m
116126
}
117127

118128
/**
@@ -136,41 +146,37 @@ module LocalFlow {
136146
or
137147
nodeFrom.(SelfParameterNode).getSelfVariable() = def.getSourceVariable()
138148
|
139-
nodeTo.(SsaDefinitionNode).getDefinition() = def
149+
nodeTo.(SsaDefinitionExtNode).getDefinitionExt() = def
140150
)
141151
}
142152

143153
/**
144154
* Holds if there is a local use-use flow step from `nodeFrom` to `nodeTo`
145155
* involving SSA definition `def`.
146156
*/
147-
predicate localSsaFlowStepUseUse(Ssa::Definition def, Node nodeFrom, Node nodeTo) {
148-
def.hasAdjacentReads(nodeFrom.asExpr(), nodeTo.asExpr())
157+
predicate localSsaFlowStepUseUse(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
158+
SsaImpl::adjacentReadPairExt(def, nodeFrom.asExpr(), nodeTo.asExpr())
149159
}
150160

151161
/**
152162
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
153163
* SSA definition `def`.
154164
*/
155165
private predicate localSsaFlowStep(Node nodeFrom, Node nodeTo) {
156-
exists(Ssa::Definition def |
166+
exists(SsaImpl::DefinitionExt def |
157167
// Flow from assignment into SSA definition
158168
def.(Ssa::WriteDefinition).assigns(nodeFrom.asExpr()) and
159-
nodeTo.(SsaDefinitionNode).getDefinition() = def
169+
nodeTo.(SsaDefinitionExtNode).getDefinitionExt() = def
160170
or
161171
// Flow from SSA definition to first read
162-
def = nodeFrom.(SsaDefinitionNode).getDefinition() and
163-
nodeTo.asExpr() = def.getAFirstRead()
172+
def = nodeFrom.(SsaDefinitionExtNode).getDefinitionExt() and
173+
firstReadExt(def, nodeTo.asExpr())
164174
or
165175
// Flow from read to next read
166176
localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
167177
or
168-
// Flow into phi node from definition
169-
exists(Ssa::PhiNode phi |
170-
localFlowSsaInputFromDef(nodeFrom, def, phi) and
171-
phi = nodeTo.(SsaDefinitionNode).getDefinition() and
172-
def = phi.getAnInput()
173-
)
178+
// Flow into phi (read) SSA definition node from def
179+
localFlowSsaInputFromDef(nodeFrom, def, nodeTo)
174180
)
175181
// TODO
176182
// or
@@ -287,7 +293,7 @@ private module Cached {
287293
ret.getKind() = kind
288294
)
289295
} or
290-
TSsaDefinitionNode(Ssa::Definition def) or
296+
TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) or
291297
TNormalParameterNode(Parameter p) {
292298
p instanceof SimpleParameter or
293299
p instanceof OptionalParameter or
@@ -352,10 +358,8 @@ private module Cached {
352358
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
353359
or
354360
// Flow into phi node from read
355-
exists(Ssa::Definition def, Ssa::PhiNode phi, CfgNodes::ExprCfgNode exprFrom |
356-
LocalFlow::localFlowSsaInputFromExpr(exprFrom, def, phi) and
357-
phi = nodeTo.(SsaDefinitionNode).getDefinition() and
358-
def = phi.getAnInput()
361+
exists(SsaImpl::DefinitionExt def, CfgNodes::ExprCfgNode exprFrom |
362+
LocalFlow::localFlowSsaInputFromRead(exprFrom, def, nodeTo)
359363
|
360364
exprFrom = nodeFrom.asExpr() and
361365
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
@@ -400,18 +404,16 @@ private module Cached {
400404
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
401405
or
402406
// Flow into phi node from read
403-
exists(Ssa::Definition def, Ssa::PhiNode phi, CfgNodes::ExprCfgNode exprFrom |
404-
LocalFlow::localFlowSsaInputFromExpr(exprFrom, def, phi) and
405-
phi = nodeTo.(SsaDefinitionNode).getDefinition() and
406-
def = phi.getAnInput() and
407+
exists(SsaImpl::DefinitionExt def, CfgNodes::ExprCfgNode exprFrom |
408+
LocalFlow::localFlowSsaInputFromRead(exprFrom, def, nodeTo) and
407409
exprFrom = [nodeFrom.asExpr(), nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr()]
408410
)
409411
}
410412

411-
private predicate entrySsaDefinition(SsaDefinitionNode n) {
413+
private predicate entrySsaDefinition(SsaDefinitionExtNode n) {
412414
n = LocalFlow::getParameterDefNode(_)
413415
or
414-
exists(Ssa::Definition def | def = n.getDefinition() |
416+
exists(SsaImpl::DefinitionExt def | def = n.getDefinitionExt() |
415417
def instanceof Ssa::SelfDefinition
416418
or
417419
def instanceof Ssa::CapturedEntryDefinition
@@ -520,8 +522,9 @@ import Cached
520522

521523
/** Holds if `n` should be hidden from path explanations. */
522524
predicate nodeIsHidden(Node n) {
523-
exists(Ssa::Definition def | def = n.(SsaDefinitionNode).getDefinition() |
525+
exists(SsaImpl::DefinitionExt def | def = n.(SsaDefinitionExtNode).getDefinitionExt() |
524526
def instanceof Ssa::PhiNode or
527+
def instanceof SsaImpl::PhiReadNode or
525528
def instanceof Ssa::CapturedEntryDefinition or
526529
def instanceof Ssa::CapturedCallDefinition
527530
)
@@ -542,13 +545,13 @@ predicate nodeIsHidden(Node n) {
542545
}
543546

544547
/** An SSA definition, viewed as a node in a data flow graph. */
545-
class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
546-
Ssa::Definition def;
548+
class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
549+
SsaImpl::DefinitionExt def;
547550

548-
SsaDefinitionNode() { this = TSsaDefinitionNode(def) }
551+
SsaDefinitionExtNode() { this = TSsaDefinitionExtNode(def) }
549552

550553
/** Gets the underlying SSA definition. */
551-
Ssa::Definition getDefinition() { result = def }
554+
SsaImpl::DefinitionExt getDefinitionExt() { result = def }
552555

553556
/** Gets the underlying variable. */
554557
Variable getVariable() { result = def.getSourceVariable() }
@@ -561,7 +564,7 @@ class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
561564
}
562565

563566
/** An SSA definition for a `self` variable. */
564-
class SsaSelfDefinitionNode extends LocalSourceNode, SsaDefinitionNode {
567+
class SsaSelfDefinitionNode extends LocalSourceNode, SsaDefinitionExtNode {
565568
private SelfVariable self;
566569

567570
SsaSelfDefinitionNode() { self = def.getSourceVariable() }
@@ -1078,11 +1081,11 @@ private module OutNodes {
10781081
import OutNodes
10791082

10801083
predicate jumpStep(Node pred, Node succ) {
1081-
SsaImpl::captureFlowIn(_, pred.(SsaDefinitionNode).getDefinition(),
1082-
succ.(SsaDefinitionNode).getDefinition())
1084+
SsaImpl::captureFlowIn(_, pred.(SsaDefinitionExtNode).getDefinitionExt(),
1085+
succ.(SsaDefinitionExtNode).getDefinitionExt())
10831086
or
1084-
SsaImpl::captureFlowOut(_, pred.(SsaDefinitionNode).getDefinition(),
1085-
succ.(SsaDefinitionNode).getDefinition())
1087+
SsaImpl::captureFlowOut(_, pred.(SsaDefinitionExtNode).getDefinitionExt(),
1088+
succ.(SsaDefinitionExtNode).getDefinitionExt())
10861089
or
10871090
succ.asExpr().getExpr().(ConstantReadAccess).getValue() = pred.asExpr().getExpr()
10881091
or

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ private module Cached {
373373
LocalSourceNode getConstantAccessNode(ConstantAccess access) {
374374
// Namespaces don't evaluate to the constant being accessed, they return the value of their last statement.
375375
// Use the definition of 'self' in the namespace as the representative in this case.
376-
result.(SsaDefinitionNode).getDefinition().(Ssa::SelfDefinition).getSourceVariable() =
376+
result.(SsaDefinitionExtNode).getDefinitionExt().(Ssa::SelfDefinition).getSourceVariable() =
377377
access.(Namespace).getModuleSelfVariable()
378378
or
379379
not access instanceof Namespace and
@@ -819,7 +819,7 @@ class ModuleNode instanceof Module {
819819
* This only gets `self` at the module level, not inside any (singleton) method.
820820
*/
821821
LocalSourceNode getModuleLevelSelf() {
822-
result.(SsaDefinitionNode).getVariable() = super.getADeclaration().getModuleSelfVariable()
822+
result.(SsaDefinitionExtNode).getVariable() = super.getADeclaration().getModuleSelfVariable()
823823
}
824824

825825
/**

0 commit comments

Comments
 (0)