Skip to content

Commit 83464d4

Browse files
authored
Merge pull request github#10773 from asgerf/rb/bugfix-singleton-class-resolution
Ruby: bugfix in type-tracking singleton class resolution
2 parents d389a18 + ed165c6 commit 83464d4

File tree

7 files changed

+127
-3
lines changed

7 files changed

+127
-3
lines changed

ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ private MethodBase getAMethod(ModuleBase mod, boolean instance) {
123123
if result instanceof SingletonMethod then instance = false else instance = true
124124
or
125125
exists(SingletonClass cls |
126-
cls.getValue().(SelfVariableAccess).getCfgScope() = mod and
126+
cls.getValue().(SelfVariableAccess).getVariable().getDeclaringScope() = mod and
127127
result = cls.getAMethod().(Method) and
128128
instance = false
129129
)
@@ -136,7 +136,7 @@ private MethodBase getAMethod(ModuleBase mod, boolean instance) {
136136
pragma[nomagic]
137137
private Node fieldPredecessor(ModuleBase mod, boolean instance, string field) {
138138
exists(InstanceVariableWriteAccess access, AssignExpr assign |
139-
access.getReceiver().getCfgScope() = getAMethod(mod, instance) and
139+
access.getReceiver().getVariable().getDeclaringScope() = getAMethod(mod, instance) and
140140
field = access.getVariable().getName() and
141141
assign.getLeftOperand() = access and
142142
result.asExpr().getExpr() = assign.getRightOperand()
@@ -150,7 +150,7 @@ private Node fieldPredecessor(ModuleBase mod, boolean instance, string field) {
150150
pragma[nomagic]
151151
private Node fieldSuccessor(ModuleBase mod, boolean instance, string field) {
152152
exists(InstanceVariableReadAccess access |
153-
access.getReceiver().getCfgScope() = getAMethod(mod, instance) and
153+
access.getReceiver().getVariable().getDeclaringScope() = getAMethod(mod, instance) and
154154
result.asExpr().getExpr() = access and
155155
field = access.getVariable().getName()
156156
)

ruby/ql/test/library-tests/modules/ancestors.expected

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ hello.rb:
120120
# 18| HelloWorld
121121
#-----| super -> Greeting
122122

123+
instance_fields.rb:
124+
# 11| A_target
125+
#-----| super -> Object
126+
127+
# 26| B_target
128+
#-----| super -> Object
129+
123130
modules.rb:
124131
# 1| Empty
125132

ruby/ql/test/library-tests/modules/callgraph.expected

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ getTarget
219219
| hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello |
220220
| hello.rb:20:16:20:20 | call to super | hello.rb:13:5:15:7 | message |
221221
| hello.rb:20:30:20:34 | call to world | hello.rb:5:5:7:7 | world |
222+
| instance_fields.rb:4:22:4:35 | call to new | calls.rb:117:5:117:16 | new |
223+
| instance_fields.rb:7:13:7:25 | call to target | instance_fields.rb:12:5:13:7 | target |
224+
| instance_fields.rb:19:22:19:35 | call to new | calls.rb:117:5:117:16 | new |
225+
| instance_fields.rb:22:13:22:25 | call to target | instance_fields.rb:27:5:28:7 | target |
222226
| modules.rb:12:5:12:26 | call to puts | calls.rb:102:5:102:30 | puts |
223227
| modules.rb:22:3:22:19 | call to puts | calls.rb:102:5:102:30 | puts |
224228
| modules.rb:33:3:33:25 | call to puts | calls.rb:102:5:102:30 | puts |
@@ -435,6 +439,12 @@ publicMethod
435439
| hello.rb:5:5:7:7 | world |
436440
| hello.rb:13:5:15:7 | message |
437441
| hello.rb:19:5:21:7 | message |
442+
| instance_fields.rb:3:9:5:11 | create |
443+
| instance_fields.rb:6:9:8:11 | use |
444+
| instance_fields.rb:12:5:13:7 | target |
445+
| instance_fields.rb:18:9:20:11 | create |
446+
| instance_fields.rb:21:9:23:11 | use |
447+
| instance_fields.rb:27:5:28:7 | target |
438448
| modules.rb:9:5:10:7 | method_in_foo_bar |
439449
| modules.rb:16:3:17:5 | method_in_foo |
440450
| modules.rb:27:3:28:5 | method_in_another_definition_of_foo |
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
class A
2+
class << self
3+
def create
4+
@field = ::A_target.new
5+
end
6+
def use
7+
@field.target
8+
end
9+
end
10+
end
11+
class A_target
12+
def target
13+
end
14+
end
15+
16+
class B
17+
class << self
18+
def create
19+
@field = ::B_target.new
20+
end
21+
def use
22+
@field.target
23+
end
24+
end
25+
end
26+
class B_target
27+
def target
28+
end
29+
end

ruby/ql/test/library-tests/modules/methods.expected

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ getMethod
4747
| hello.rb:1:1:8:3 | EnglishWords | world | hello.rb:5:5:7:7 | world |
4848
| hello.rb:11:1:16:3 | Greeting | message | hello.rb:13:5:15:7 | message |
4949
| hello.rb:18:1:22:3 | HelloWorld | message | hello.rb:19:5:21:7 | message |
50+
| instance_fields.rb:11:1:14:3 | A_target | target | instance_fields.rb:12:5:13:7 | target |
51+
| instance_fields.rb:26:1:29:3 | B_target | target | instance_fields.rb:27:5:28:7 | target |
5052
| modules.rb:4:1:24:3 | Foo | method_in_another_definition_of_foo | modules.rb:27:3:28:5 | method_in_another_definition_of_foo |
5153
| modules.rb:4:1:24:3 | Foo | method_in_foo | modules.rb:16:3:17:5 | method_in_foo |
5254
| modules.rb:5:3:14:5 | Foo::Bar | method_in_another_definition_of_foo_bar | modules.rb:52:3:53:5 | method_in_another_definition_of_foo_bar |
@@ -430,6 +432,14 @@ lookupMethod
430432
| hello.rb:18:1:22:3 | HelloWorld | puts | calls.rb:102:5:102:30 | puts |
431433
| hello.rb:18:1:22:3 | HelloWorld | to_s | calls.rb:172:5:173:7 | to_s |
432434
| hello.rb:18:1:22:3 | HelloWorld | world | hello.rb:5:5:7:7 | world |
435+
| instance_fields.rb:11:1:14:3 | A_target | new | calls.rb:117:5:117:16 | new |
436+
| instance_fields.rb:11:1:14:3 | A_target | puts | calls.rb:102:5:102:30 | puts |
437+
| instance_fields.rb:11:1:14:3 | A_target | target | instance_fields.rb:12:5:13:7 | target |
438+
| instance_fields.rb:11:1:14:3 | A_target | to_s | calls.rb:172:5:173:7 | to_s |
439+
| instance_fields.rb:26:1:29:3 | B_target | new | calls.rb:117:5:117:16 | new |
440+
| instance_fields.rb:26:1:29:3 | B_target | puts | calls.rb:102:5:102:30 | puts |
441+
| instance_fields.rb:26:1:29:3 | B_target | target | instance_fields.rb:27:5:28:7 | target |
442+
| instance_fields.rb:26:1:29:3 | B_target | to_s | calls.rb:172:5:173:7 | to_s |
433443
| modules.rb:4:1:24:3 | Foo | method_in_another_definition_of_foo | modules.rb:27:3:28:5 | method_in_another_definition_of_foo |
434444
| modules.rb:4:1:24:3 | Foo | method_in_foo | modules.rb:16:3:17:5 | method_in_foo |
435445
| modules.rb:5:3:14:5 | Foo::Bar | method_in_another_definition_of_foo_bar | modules.rb:52:3:53:5 | method_in_another_definition_of_foo_bar |
@@ -852,6 +862,22 @@ enclosingMethod
852862
| hello.rb:20:30:20:34 | self | hello.rb:19:5:21:7 | message |
853863
| hello.rb:20:38:20:40 | "!" | hello.rb:19:5:21:7 | message |
854864
| hello.rb:20:39:20:39 | ! | hello.rb:19:5:21:7 | message |
865+
| instance_fields.rb:4:13:4:18 | @field | instance_fields.rb:3:9:5:11 | create |
866+
| instance_fields.rb:4:13:4:18 | self | instance_fields.rb:3:9:5:11 | create |
867+
| instance_fields.rb:4:13:4:35 | ... = ... | instance_fields.rb:3:9:5:11 | create |
868+
| instance_fields.rb:4:22:4:31 | A_target | instance_fields.rb:3:9:5:11 | create |
869+
| instance_fields.rb:4:22:4:35 | call to new | instance_fields.rb:3:9:5:11 | create |
870+
| instance_fields.rb:7:13:7:18 | @field | instance_fields.rb:6:9:8:11 | use |
871+
| instance_fields.rb:7:13:7:18 | self | instance_fields.rb:6:9:8:11 | use |
872+
| instance_fields.rb:7:13:7:25 | call to target | instance_fields.rb:6:9:8:11 | use |
873+
| instance_fields.rb:19:13:19:18 | @field | instance_fields.rb:18:9:20:11 | create |
874+
| instance_fields.rb:19:13:19:18 | self | instance_fields.rb:18:9:20:11 | create |
875+
| instance_fields.rb:19:13:19:35 | ... = ... | instance_fields.rb:18:9:20:11 | create |
876+
| instance_fields.rb:19:22:19:31 | B_target | instance_fields.rb:18:9:20:11 | create |
877+
| instance_fields.rb:19:22:19:35 | call to new | instance_fields.rb:18:9:20:11 | create |
878+
| instance_fields.rb:22:13:22:18 | @field | instance_fields.rb:21:9:23:11 | use |
879+
| instance_fields.rb:22:13:22:18 | self | instance_fields.rb:21:9:23:11 | use |
880+
| instance_fields.rb:22:13:22:25 | call to target | instance_fields.rb:21:9:23:11 | use |
855881
| private.rb:84:7:84:32 | call to puts | private.rb:83:11:85:5 | m1 |
856882
| private.rb:84:7:84:32 | self | private.rb:83:11:85:5 | m1 |
857883
| private.rb:84:12:84:32 | "PrivateOverride1#m1" | private.rb:83:11:85:5 | m1 |

ruby/ql/test/library-tests/modules/modules.expected

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ getModule
4040
| hello.rb:1:1:8:3 | EnglishWords |
4141
| hello.rb:11:1:16:3 | Greeting |
4242
| hello.rb:18:1:22:3 | HelloWorld |
43+
| instance_fields.rb:11:1:14:3 | A_target |
44+
| instance_fields.rb:26:1:29:3 | B_target |
4345
| modules.rb:1:1:2:3 | Empty |
4446
| modules.rb:4:1:24:3 | Foo |
4547
| modules.rb:5:3:14:5 | Foo::Bar |
@@ -87,15 +89,18 @@ getADeclaration
8789
| calls.rb:115:1:118:3 | Object | calls.rb:1:1:550:40 | calls.rb |
8890
| calls.rb:115:1:118:3 | Object | calls.rb:115:1:118:3 | Object |
8991
| calls.rb:115:1:118:3 | Object | hello.rb:1:1:22:3 | hello.rb |
92+
| calls.rb:115:1:118:3 | Object | instance_fields.rb:1:1:29:4 | instance_fields.rb |
9093
| calls.rb:115:1:118:3 | Object | modules.rb:1:1:129:4 | modules.rb |
9194
| calls.rb:115:1:118:3 | Object | modules_rec.rb:1:1:11:26 | modules_rec.rb |
9295
| calls.rb:115:1:118:3 | Object | private.rb:1:1:105:40 | private.rb |
9396
| calls.rb:120:1:123:3 | Hash | calls.rb:120:1:123:3 | Hash |
9497
| calls.rb:125:1:138:3 | Array | calls.rb:125:1:138:3 | Array |
9598
| calls.rb:165:1:169:3 | S | calls.rb:165:1:169:3 | S |
9699
| calls.rb:171:1:174:3 | A | calls.rb:171:1:174:3 | A |
100+
| calls.rb:171:1:174:3 | A | instance_fields.rb:1:1:10:3 | A |
97101
| calls.rb:171:1:174:3 | A | modules_rec.rb:7:1:9:3 | A |
98102
| calls.rb:176:1:179:3 | B | calls.rb:176:1:179:3 | B |
103+
| calls.rb:176:1:179:3 | B | instance_fields.rb:16:1:25:3 | B |
99104
| calls.rb:190:1:226:3 | Singletons | calls.rb:190:1:226:3 | Singletons |
100105
| calls.rb:310:1:321:3 | SelfNew | calls.rb:310:1:321:3 | SelfNew |
101106
| calls.rb:325:1:329:3 | C1 | calls.rb:325:1:329:3 | C1 |
@@ -113,6 +118,8 @@ getADeclaration
113118
| hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:8:3 | EnglishWords |
114119
| hello.rb:11:1:16:3 | Greeting | hello.rb:11:1:16:3 | Greeting |
115120
| hello.rb:18:1:22:3 | HelloWorld | hello.rb:18:1:22:3 | HelloWorld |
121+
| instance_fields.rb:11:1:14:3 | A_target | instance_fields.rb:11:1:14:3 | A_target |
122+
| instance_fields.rb:26:1:29:3 | B_target | instance_fields.rb:26:1:29:3 | B_target |
116123
| modules.rb:1:1:2:3 | Empty | modules.rb:1:1:2:3 | Empty |
117124
| modules.rb:4:1:24:3 | Foo | modules.rb:4:1:24:3 | Foo |
118125
| modules.rb:4:1:24:3 | Foo | modules.rb:26:1:35:3 | Foo |
@@ -185,6 +192,8 @@ getSuperClass
185192
| file://:0:0:0:0 | TrueClass | calls.rb:115:1:118:3 | Object |
186193
| hello.rb:11:1:16:3 | Greeting | calls.rb:115:1:118:3 | Object |
187194
| hello.rb:18:1:22:3 | HelloWorld | hello.rb:11:1:16:3 | Greeting |
195+
| instance_fields.rb:11:1:14:3 | A_target | calls.rb:115:1:118:3 | Object |
196+
| instance_fields.rb:26:1:29:3 | B_target | calls.rb:115:1:118:3 | Object |
188197
| modules.rb:6:5:7:7 | Foo::Bar::ClassInFooBar | calls.rb:115:1:118:3 | Object |
189198
| modules.rb:19:3:20:5 | Foo::ClassInFoo | calls.rb:115:1:118:3 | Object |
190199
| modules.rb:30:3:31:5 | Foo::ClassInAnotherDefinitionOfFoo | calls.rb:115:1:118:3 | Object |
@@ -299,6 +308,8 @@ resolveConstantReadAccess
299308
| calls.rb:550:1:550:13 | Array | Array |
300309
| hello.rb:12:13:12:24 | EnglishWords | EnglishWords |
301310
| hello.rb:18:20:18:27 | Greeting | Greeting |
311+
| instance_fields.rb:4:22:4:31 | A_target | A_target |
312+
| instance_fields.rb:19:22:19:31 | B_target | B_target |
302313
| modules.rb:48:8:48:10 | Foo | Foo |
303314
| modules.rb:66:11:66:14 | Foo1 | Test::Foo1 |
304315
| modules.rb:72:11:72:14 | Foo2 | Test::Foo2::Foo2 |
@@ -364,6 +375,10 @@ resolveConstantWriteAccess
364375
| hello.rb:1:1:8:3 | EnglishWords | EnglishWords |
365376
| hello.rb:11:1:16:3 | Greeting | Greeting |
366377
| hello.rb:18:1:22:3 | HelloWorld | HelloWorld |
378+
| instance_fields.rb:1:1:10:3 | A | A |
379+
| instance_fields.rb:11:1:14:3 | A_target | A_target |
380+
| instance_fields.rb:16:1:25:3 | B | B |
381+
| instance_fields.rb:26:1:29:3 | B_target | B_target |
367382
| modules.rb:1:1:2:3 | Empty | Empty |
368383
| modules.rb:4:1:24:3 | Foo | Foo |
369384
| modules.rb:5:3:14:5 | Bar | Foo::Bar |
@@ -1366,6 +1381,36 @@ enclosingModule
13661381
| hello.rb:20:30:20:34 | self | hello.rb:18:1:22:3 | HelloWorld |
13671382
| hello.rb:20:38:20:40 | "!" | hello.rb:18:1:22:3 | HelloWorld |
13681383
| hello.rb:20:39:20:39 | ! | hello.rb:18:1:22:3 | HelloWorld |
1384+
| instance_fields.rb:1:1:10:3 | A | instance_fields.rb:1:1:29:4 | instance_fields.rb |
1385+
| instance_fields.rb:2:5:9:7 | class << ... | instance_fields.rb:1:1:10:3 | A |
1386+
| instance_fields.rb:2:14:2:17 | self | instance_fields.rb:1:1:10:3 | A |
1387+
| instance_fields.rb:3:9:5:11 | create | instance_fields.rb:2:5:9:7 | class << ... |
1388+
| instance_fields.rb:4:13:4:18 | @field | instance_fields.rb:2:5:9:7 | class << ... |
1389+
| instance_fields.rb:4:13:4:18 | self | instance_fields.rb:2:5:9:7 | class << ... |
1390+
| instance_fields.rb:4:13:4:35 | ... = ... | instance_fields.rb:2:5:9:7 | class << ... |
1391+
| instance_fields.rb:4:22:4:31 | A_target | instance_fields.rb:2:5:9:7 | class << ... |
1392+
| instance_fields.rb:4:22:4:35 | call to new | instance_fields.rb:2:5:9:7 | class << ... |
1393+
| instance_fields.rb:6:9:8:11 | use | instance_fields.rb:2:5:9:7 | class << ... |
1394+
| instance_fields.rb:7:13:7:18 | @field | instance_fields.rb:2:5:9:7 | class << ... |
1395+
| instance_fields.rb:7:13:7:18 | self | instance_fields.rb:2:5:9:7 | class << ... |
1396+
| instance_fields.rb:7:13:7:25 | call to target | instance_fields.rb:2:5:9:7 | class << ... |
1397+
| instance_fields.rb:11:1:14:3 | A_target | instance_fields.rb:1:1:29:4 | instance_fields.rb |
1398+
| instance_fields.rb:12:5:13:7 | target | instance_fields.rb:11:1:14:3 | A_target |
1399+
| instance_fields.rb:16:1:25:3 | B | instance_fields.rb:1:1:29:4 | instance_fields.rb |
1400+
| instance_fields.rb:17:5:24:7 | class << ... | instance_fields.rb:16:1:25:3 | B |
1401+
| instance_fields.rb:17:14:17:17 | self | instance_fields.rb:16:1:25:3 | B |
1402+
| instance_fields.rb:18:9:20:11 | create | instance_fields.rb:17:5:24:7 | class << ... |
1403+
| instance_fields.rb:19:13:19:18 | @field | instance_fields.rb:17:5:24:7 | class << ... |
1404+
| instance_fields.rb:19:13:19:18 | self | instance_fields.rb:17:5:24:7 | class << ... |
1405+
| instance_fields.rb:19:13:19:35 | ... = ... | instance_fields.rb:17:5:24:7 | class << ... |
1406+
| instance_fields.rb:19:22:19:31 | B_target | instance_fields.rb:17:5:24:7 | class << ... |
1407+
| instance_fields.rb:19:22:19:35 | call to new | instance_fields.rb:17:5:24:7 | class << ... |
1408+
| instance_fields.rb:21:9:23:11 | use | instance_fields.rb:17:5:24:7 | class << ... |
1409+
| instance_fields.rb:22:13:22:18 | @field | instance_fields.rb:17:5:24:7 | class << ... |
1410+
| instance_fields.rb:22:13:22:18 | self | instance_fields.rb:17:5:24:7 | class << ... |
1411+
| instance_fields.rb:22:13:22:25 | call to target | instance_fields.rb:17:5:24:7 | class << ... |
1412+
| instance_fields.rb:26:1:29:3 | B_target | instance_fields.rb:1:1:29:4 | instance_fields.rb |
1413+
| instance_fields.rb:27:5:28:7 | target | instance_fields.rb:26:1:29:3 | B_target |
13691414
| modules.rb:1:1:2:3 | Empty | modules.rb:1:1:129:4 | modules.rb |
13701415
| modules.rb:4:1:24:3 | Foo | modules.rb:1:1:129:4 | modules.rb |
13711416
| modules.rb:5:3:14:5 | Bar | modules.rb:4:1:24:3 | Foo |

ruby/ql/test/library-tests/modules/superclasses.expected

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ hello.rb:
114114
# 18| HelloWorld
115115
#-----| -> Greeting
116116

117+
instance_fields.rb:
118+
# 11| A_target
119+
#-----| -> Object
120+
121+
# 26| B_target
122+
#-----| -> Object
123+
117124
modules.rb:
118125
# 1| Empty
119126

0 commit comments

Comments
 (0)