Skip to content

Commit 67f31ff

Browse files
committed
Ruby: Add tests for phi reads
1 parent bd78e73 commit 67f31ff

File tree

9 files changed

+220
-15
lines changed

9 files changed

+220
-15
lines changed
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import codeql.ruby.dataflow.SSA
2-
import codeql.ruby.dataflow.internal.SsaImpl::Consistency
2+
import codeql.ruby.dataflow.internal.SsaImpl
3+
import Consistency
34

45
class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
56
override predicate hasLocationInfo(
@@ -8,3 +9,11 @@ class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
89
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
910
}
1011
}
12+
13+
class MyRelevantDefinitionExt extends RelevantDefinitionExt, DefinitionExt {
14+
override predicate hasLocationInfo(
15+
string filepath, int startline, int startcolumn, int endline, int endcolumn
16+
) {
17+
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
18+
}
19+
}

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

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ private import codeql.ssa.Ssa as SsaImplCommon
22
private import codeql.ruby.AST
33
private import codeql.ruby.CFG as Cfg
44
private import codeql.ruby.controlflow.internal.ControlFlowGraphImplShared as ControlFlowGraphImplShared
5+
private import codeql.ruby.dataflow.SSA
56
private import codeql.ruby.ast.Variable
67
private import Cfg::CfgNodes::ExprNodes
78

@@ -61,7 +62,23 @@ private module SsaInput implements SsaImplCommon::InputSig {
6162
}
6263
}
6364

64-
import SsaImplCommon::Make<SsaInput>
65+
private import SsaImplCommon::Make<SsaInput> as Impl
66+
67+
class Definition = Impl::Definition;
68+
69+
class WriteDefinition = Impl::WriteDefinition;
70+
71+
class UncertainWriteDefinition = Impl::UncertainWriteDefinition;
72+
73+
class PhiNode = Impl::PhiNode;
74+
75+
module Consistency = Impl::Consistency;
76+
77+
module ExposedForTestingOnly {
78+
predicate ssaDefReachesReadExt = Impl::ssaDefReachesReadExt/4;
79+
80+
predicate phiHasInputFromBlockExt = Impl::phiHasInputFromBlockExt/3;
81+
}
6582

6683
/** Holds if `v` is uninitialized at index `i` in entry block `bb`. */
6784
predicate uninitializedWrite(Cfg::EntryBasicBlock bb, int i, LocalVariable v) {
@@ -204,7 +221,7 @@ private predicate adjacentDefRead(
204221
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2,
205222
SsaInput::SourceVariable v
206223
) {
207-
adjacentDefRead(def, bb1, i1, bb2, i2) and
224+
Impl::adjacentDefRead(def, bb1, i1, bb2, i2) and
208225
v = def.getSourceVariable()
209226
}
210227

@@ -220,7 +237,7 @@ private predicate adjacentDefReachesRead(
220237
exists(SsaInput::BasicBlock bb3, int i3 |
221238
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
222239
SsaInput::variableRead(bb3, i3, _, false) and
223-
adjacentDefRead(def, bb3, i3, bb2, i2)
240+
Impl::adjacentDefRead(def, bb3, i3, bb2, i2)
224241
)
225242
}
226243

@@ -243,11 +260,11 @@ private predicate adjacentDefReachesUncertainRead(
243260
/** Same as `lastRefRedef`, but skips uncertain reads. */
244261
pragma[nomagic]
245262
private predicate lastRefSkipUncertainReads(Definition def, SsaInput::BasicBlock bb, int i) {
246-
lastRef(def, bb, i) and
263+
Impl::lastRef(def, bb, i) and
247264
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
248265
or
249266
exists(SsaInput::BasicBlock bb0, int i0 |
250-
lastRef(def, bb0, i0) and
267+
Impl::lastRef(def, bb0, i0) and
251268
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
252269
)
253270
}
@@ -304,7 +321,7 @@ private module Cached {
304321
cached
305322
VariableReadAccessCfgNode getARead(Definition def) {
306323
exists(LocalVariable v, Cfg::BasicBlock bb, int i |
307-
ssaDefReachesRead(v, def, bb, i) and
324+
Impl::ssaDefReachesRead(v, def, bb, i) and
308325
variableReadActual(bb, i, v) and
309326
result = bb.getNode(i)
310327
)
@@ -315,7 +332,7 @@ private module Cached {
315332
Definition def, CallCfgNode call, LocalVariable v, Cfg::CfgScope scope
316333
) {
317334
exists(Cfg::BasicBlock bb, int i |
318-
ssaDefReachesRead(v, def, bb, i) and
335+
Impl::ssaDefReachesRead(v, def, bb, i) and
319336
capturedCallRead(call, bb, i, v) and
320337
scope.getOuterCfgScope() = bb.getScope()
321338
)
@@ -360,7 +377,7 @@ private module Cached {
360377
Definition def, LocalVariable v, Cfg::CfgScope scope
361378
) {
362379
exists(Cfg::BasicBlock bb, int i |
363-
ssaDefReachesRead(v, def, bb, i) and
380+
Impl::ssaDefReachesRead(v, def, bb, i) and
364381
capturedExitRead(bb, i, v) and
365382
scope = bb.getScope().getOuterCfgScope*()
366383
)
@@ -403,7 +420,7 @@ private module Cached {
403420

404421
cached
405422
Definition phiHasInputFromBlock(PhiNode phi, Cfg::BasicBlock bb) {
406-
phiHasInputFromBlock(phi, result, bb)
423+
Impl::phiHasInputFromBlock(phi, result, bb)
407424
}
408425

409426
/**
@@ -459,19 +476,45 @@ private module Cached {
459476
*/
460477
cached
461478
predicate lastRefBeforeRedef(Definition def, Cfg::BasicBlock bb, int i, Definition next) {
462-
lastRefRedef(def, bb, i, next) and
479+
Impl::lastRefRedef(def, bb, i, next) and
463480
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
464481
or
465482
exists(SsaInput::BasicBlock bb0, int i0 |
466-
lastRefRedef(def, bb0, i0, next) and
483+
Impl::lastRefRedef(def, bb0, i0, next) and
467484
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
468485
)
469486
}
470487

471488
cached
472489
Definition uncertainWriteDefinitionInput(UncertainWriteDefinition def) {
473-
uncertainWriteDefinitionInput(def, result)
490+
Impl::uncertainWriteDefinitionInput(def, result)
474491
}
475492
}
476493

477494
import Cached
495+
496+
/**
497+
* An extended static single assignment (SSA) definition.
498+
*
499+
* This is either a normal SSA definition (`Definition`) or a
500+
* phi-read node (`PhiReadNode`).
501+
*
502+
* Only intended for internal use.
503+
*/
504+
class DefinitionExt extends Impl::DefinitionExt {
505+
override string toString() { result = this.(Ssa::Definition).toString() }
506+
507+
/** Gets the location of this definition. */
508+
Location getLocation() { result = this.(Ssa::Definition).getLocation() }
509+
}
510+
511+
/**
512+
* A phi-read node.
513+
*
514+
* Only intended for internal use.
515+
*/
516+
class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
517+
override string toString() { result = "SSA phi read(" + this.getSourceVariable() + ")" }
518+
519+
override Location getLocation() { result = this.getBasicBlock().getLocation() }
520+
}

ruby/ql/test/library-tests/variables/parameter.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ parameterVariable
3838
| ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo |
3939
| ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a |
4040
| ssa.rb:66:15:66:15 | a | ssa.rb:66:15:66:15 | a |
41+
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 |
42+
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 |
43+
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 |
44+
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 |
4145
parameterNoVariable
4246
| parameters.rb:45:22:45:22 | _ |
4347
parameterVariableNoAccess

ruby/ql/test/library-tests/variables/ssa.expected

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ definition
164164
| ssa.rb:83:7:87:5 | <captured> self | ssa.rb:81:1:88:3 | self |
165165
| ssa.rb:84:10:86:8 | <captured> captured | ssa.rb:82:3:82:10 | captured |
166166
| ssa.rb:84:10:86:8 | <captured> self | ssa.rb:81:1:88:3 | self |
167+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self |
168+
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 |
169+
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 |
170+
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 |
171+
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 |
172+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x |
167173
read
168174
| class_variables.rb:1:1:29:4 | self (class_variables.rb) | class_variables.rb:1:1:29:4 | self | class_variables.rb:3:1:3:5 | self |
169175
| class_variables.rb:5:1:7:3 | self (print) | class_variables.rb:5:1:7:3 | self | class_variables.rb:6:2:6:6 | self |
@@ -347,6 +353,18 @@ read
347353
| ssa.rb:83:7:87:5 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:84:6:86:8 | self |
348354
| ssa.rb:84:10:86:8 | <captured> captured | ssa.rb:82:3:82:10 | captured | ssa.rb:85:15:85:22 | captured |
349355
| ssa.rb:84:10:86:8 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:85:10:85:22 | self |
356+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self |
357+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self |
358+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:99:5:99:10 | self |
359+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:101:5:101:10 | self |
360+
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 | ssa.rb:92:7:92:8 | b1 |
361+
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:94:10:94:11 | b2 |
362+
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:98:7:98:8 | b3 |
363+
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:100:10:100:11 | b4 |
364+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x |
365+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x |
366+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x |
367+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x |
350368
firstRead
351369
| class_variables.rb:1:1:29:4 | self (class_variables.rb) | class_variables.rb:1:1:29:4 | self | class_variables.rb:3:1:3:5 | self |
352370
| class_variables.rb:5:1:7:3 | self (print) | class_variables.rb:5:1:7:3 | self | class_variables.rb:6:2:6:6 | self |
@@ -485,6 +503,18 @@ firstRead
485503
| ssa.rb:83:7:87:5 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:84:6:86:8 | self |
486504
| ssa.rb:84:10:86:8 | <captured> captured | ssa.rb:82:3:82:10 | captured | ssa.rb:85:15:85:22 | captured |
487505
| ssa.rb:84:10:86:8 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:85:10:85:22 | self |
506+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self |
507+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self |
508+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:99:5:99:10 | self |
509+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:101:5:101:10 | self |
510+
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 | ssa.rb:92:7:92:8 | b1 |
511+
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:94:10:94:11 | b2 |
512+
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:98:7:98:8 | b3 |
513+
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:100:10:100:11 | b4 |
514+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x |
515+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x |
516+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x |
517+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x |
488518
lastRead
489519
| class_variables.rb:1:1:29:4 | self (class_variables.rb) | class_variables.rb:1:1:29:4 | self | class_variables.rb:3:1:3:5 | self |
490520
| class_variables.rb:5:1:7:3 | self (print) | class_variables.rb:5:1:7:3 | self | class_variables.rb:6:2:6:6 | self |
@@ -624,6 +654,18 @@ lastRead
624654
| ssa.rb:83:7:87:5 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:84:6:86:8 | self |
625655
| ssa.rb:84:10:86:8 | <captured> captured | ssa.rb:82:3:82:10 | captured | ssa.rb:85:15:85:22 | captured |
626656
| ssa.rb:84:10:86:8 | <captured> self | ssa.rb:81:1:88:3 | self | ssa.rb:85:10:85:22 | self |
657+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self |
658+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self |
659+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:99:5:99:10 | self |
660+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:101:5:101:10 | self |
661+
| ssa.rb:90:9:90:10 | b1 | ssa.rb:90:9:90:10 | b1 | ssa.rb:92:7:92:8 | b1 |
662+
| ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:94:10:94:11 | b2 |
663+
| ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:98:7:98:8 | b3 |
664+
| ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:100:10:100:11 | b4 |
665+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x |
666+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x |
667+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x |
668+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x |
627669
adjacentReads
628670
| class_variables.rb:26:1:29:3 | self (N) | class_variables.rb:26:1:29:3 | self | class_variables.rb:27:3:27:11 | self | class_variables.rb:28:3:28:7 | self |
629671
| instance_variables.rb:1:1:44:4 | self (instance_variables.rb) | instance_variables.rb:1:1:44:4 | self | instance_variables.rb:1:1:1:4 | self | instance_variables.rb:11:1:11:9 | self |
@@ -674,6 +716,14 @@ adjacentReads
674716
| ssa.rb:38:1:42:3 | self (m4) | ssa.rb:38:1:42:3 | self | ssa.rb:39:8:39:9 | self | ssa.rb:41:3:41:13 | self |
675717
| ssa.rb:66:11:70:5 | <captured> captured | ssa.rb:65:3:65:10 | captured | ssa.rb:68:10:68:17 | captured | ssa.rb:69:5:69:12 | captured |
676718
| ssa.rb:66:11:70:5 | <captured> self | ssa.rb:64:1:72:3 | self | ssa.rb:67:5:67:10 | self | ssa.rb:68:5:68:17 | self |
719+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self | ssa.rb:99:5:99:10 | self |
720+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self | ssa.rb:101:5:101:10 | self |
721+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self | ssa.rb:99:5:99:10 | self |
722+
| ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self | ssa.rb:101:5:101:10 | self |
723+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | ssa.rb:99:10:99:10 | x |
724+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | ssa.rb:101:10:101:10 | x |
725+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | ssa.rb:99:10:99:10 | x |
726+
| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | ssa.rb:101:10:101:10 | x |
677727
phi
678728
| parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | <uninitialized> |
679729
| parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:20 | ... = ... |
@@ -689,3 +739,30 @@ phi
689739
| ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | ssa.rb:45:3:45:7 | ... = ... |
690740
| ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:49:1:51:3 | <uninitialized> |
691741
| ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:49:14:49:19 | ... = ... |
742+
phiReadNode
743+
| parameters.rb:26:3:26:11 | SSA phi read(name) | parameters.rb:25:15:25:18 | name |
744+
| ssa.rb:5:3:13:5 | SSA phi read(self) | ssa.rb:1:1:16:3 | self |
745+
| ssa.rb:19:9:19:9 | SSA phi read(self) | ssa.rb:18:1:23:3 | self |
746+
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:90:1:103:3 | self |
747+
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:3 | x |
748+
| ssa.rb:94:3:95:10 | SSA phi read(self) | ssa.rb:90:1:103:3 | self |
749+
| ssa.rb:94:3:95:10 | SSA phi read(x) | ssa.rb:91:3:91:3 | x |
750+
phiReadNodeRead
751+
| parameters.rb:26:3:26:11 | SSA phi read(name) | parameters.rb:25:15:25:18 | name | parameters.rb:26:8:26:11 | name |
752+
| ssa.rb:5:3:13:5 | SSA phi read(self) | ssa.rb:1:1:16:3 | self | ssa.rb:15:3:15:8 | self |
753+
| ssa.rb:19:9:19:9 | SSA phi read(self) | ssa.rb:18:1:23:3 | self | ssa.rb:20:5:20:10 | self |
754+
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:90:1:103:3 | self | ssa.rb:99:5:99:10 | self |
755+
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:90:1:103:3 | self | ssa.rb:101:5:101:10 | self |
756+
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x |
757+
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x |
758+
phiReadInput
759+
| parameters.rb:26:3:26:11 | SSA phi read(name) | parameters.rb:25:15:25:18 | name |
760+
| ssa.rb:5:3:13:5 | SSA phi read(self) | ssa.rb:1:1:16:3 | self (m) |
761+
| ssa.rb:19:9:19:9 | SSA phi read(self) | ssa.rb:18:1:23:3 | self (m1) |
762+
| ssa.rb:19:9:19:9 | SSA phi read(self) | ssa.rb:19:9:19:9 | SSA phi read(self) |
763+
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:90:1:103:3 | self (m12) |
764+
| ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:94:3:95:10 | SSA phi read(self) |
765+
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:7 | ... = ... |
766+
| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:94:3:95:10 | SSA phi read(x) |
767+
| ssa.rb:94:3:95:10 | SSA phi read(self) | ssa.rb:90:1:103:3 | self (m12) |
768+
| ssa.rb:94:3:95:10 | SSA phi read(x) | ssa.rb:91:3:91:7 | ... = ... |

ruby/ql/test/library-tests/variables/ssa.ql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import codeql.ruby.AST
22
import codeql.ruby.CFG
33
import codeql.ruby.dataflow.SSA
4+
import codeql.ruby.dataflow.internal.SsaImpl
5+
import ExposedForTestingOnly
46

57
query predicate definition(Ssa::Definition def, Variable v) { def.getSourceVariable() = v }
68

@@ -24,3 +26,17 @@ query predicate adjacentReads(Ssa::Definition def, Variable v, CfgNode read1, Cf
2426
query predicate phi(Ssa::PhiNode phi, Variable v, Ssa::Definition input) {
2527
phi.getSourceVariable() = v and input = phi.getAnInput()
2628
}
29+
30+
query predicate phiReadNode(PhiReadNode phi, Variable v) { phi.getSourceVariable() = v }
31+
32+
query predicate phiReadNodeRead(PhiReadNode phi, Variable v, CfgNode read) {
33+
phi.getSourceVariable() = v and
34+
exists(BasicBlock bb, int i |
35+
ssaDefReachesReadExt(v, phi, bb, i) and
36+
read = bb.getNode(i)
37+
)
38+
}
39+
40+
query predicate phiReadInput(PhiReadNode phi, DefinitionExt inp) {
41+
phiHasInputFromBlockExt(phi, inp, _)
42+
}

ruby/ql/test/library-tests/variables/ssa.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,19 @@ def m11
8585
puts captured
8686
end
8787
end
88+
end
89+
90+
def m12(b1, b2, b3, b4)
91+
x = 0
92+
if (b1) then
93+
puts x
94+
elsif (b2) then
95+
puts x
96+
end
97+
# phi read for x
98+
if (b3) then
99+
puts x
100+
elsif (b4) then
101+
puts x
102+
end
88103
end

0 commit comments

Comments
 (0)