Skip to content

Commit 898a400

Browse files
authored
Merge pull request github#10747 from aibaars/ruby-more-flow
Ruby: also treat included/prepended modules as subclasses
2 parents 9f9a516 + 889eea9 commit 898a400

File tree

9 files changed

+685
-608
lines changed

9 files changed

+685
-608
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* When resolving a method call, the analysis now also searches in sub-classes of the receiver's type.

ruby/ql/lib/codeql/ruby/ast/internal/Module.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private module Cached {
165165
*/
166166
cached
167167
Method lookupMethodInSubClasses(Module m, string name) {
168-
exists(Module sub | sub.getSuperClass() = m |
168+
exists(Module sub | sub.getAnImmediateAncestor() = m |
169169
TMethod(result) = lookupMethodOrConst0(sub, name) or
170170
result = lookupMethodInSubClasses(sub, name)
171171
)

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

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,10 @@ private Block yieldCall(RelevantCall call) {
190190
}
191191

192192
pragma[nomagic]
193-
private predicate superCall(RelevantCall call, Module superClass, string method) {
193+
private predicate superCall(RelevantCall call, Module cls, string method) {
194194
call.getExpr() instanceof SuperCall and
195-
exists(Module tp |
196-
tp = call.getExpr().getEnclosingModule().getModule() and
197-
superClass = tp.getSuperClass() and
198-
method = call.getExpr().getEnclosingMethod().getName()
199-
)
195+
cls = call.getExpr().getEnclosingModule().getModule() and
196+
method = call.getExpr().getEnclosingMethod().getName()
200197
}
201198

202199
/** Holds if `self` belongs to module `m`. */
@@ -464,9 +461,9 @@ private module Cached {
464461
)
465462
)
466463
or
467-
exists(Module superClass, string method |
468-
superCall(call, superClass, method) and
469-
result = lookupMethod(superClass, method)
464+
exists(Module cls, string method |
465+
superCall(call, cls, method) and
466+
result = lookupMethod(cls.getAnImmediateAncestor(), method)
470467
)
471468
or
472469
result = yieldCall(call)

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ calls.rb:
136136
# 605| SingletonC
137137
#-----| super -> SingletonA
138138

139+
# 618| Included
140+
141+
# 626| IncludesIncluded
142+
#-----| super -> Object
143+
#-----| include -> Included
144+
139145
hello.rb:
140146
# 1| EnglishWords
141147

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ getTarget
233233
| calls.rb:614:1:614:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
234234
| calls.rb:615:1:615:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
235235
| calls.rb:616:1:616:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
236+
| calls.rb:620:9:620:16 | call to bar | calls.rb:622:5:623:7 | bar |
237+
| calls.rb:620:9:620:16 | call to bar | calls.rb:628:5:630:7 | bar |
238+
| calls.rb:627:5:627:20 | call to include | calls.rb:108:5:110:7 | include |
239+
| calls.rb:629:9:629:13 | call to super | calls.rb:622:5:623:7 | bar |
236240
| hello.rb:12:5:12:24 | call to include | calls.rb:108:5:110:7 | include |
237241
| hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello |
238242
| hello.rb:20:16:20:20 | call to super | hello.rb:13:5:15:7 | message |
@@ -476,6 +480,9 @@ publicMethod
476480
| calls.rb:600:5:602:7 | call_singleton1 |
477481
| calls.rb:606:5:607:7 | singleton1 |
478482
| calls.rb:609:5:611:7 | call_singleton1 |
483+
| calls.rb:619:5:621:7 | foo |
484+
| calls.rb:622:5:623:7 | bar |
485+
| calls.rb:628:5:630:7 | bar |
479486
| hello.rb:2:5:4:7 | hello |
480487
| hello.rb:5:5:7:7 | world |
481488
| hello.rb:13:5:15:7 | message |

ruby/ql/test/library-tests/modules/calls.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,3 +614,19 @@ def self.call_singleton1
614614
SingletonA.call_call_singleton1
615615
SingletonB.call_call_singleton1
616616
SingletonC.call_call_singleton1
617+
618+
module Included
619+
def foo
620+
self.bar
621+
end
622+
def bar
623+
end
624+
end
625+
626+
class IncludesIncluded
627+
include Included
628+
def bar
629+
super
630+
end
631+
end
632+

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ getMethod
4545
| calls.rb:531:1:544:3 | ProtectedMethods | bar | calls.rb:534:15:536:7 | bar |
4646
| calls.rb:531:1:544:3 | ProtectedMethods | baz | calls.rb:538:5:543:7 | baz |
4747
| calls.rb:550:1:555:3 | ProtectedMethodsSub | baz | calls.rb:551:5:554:7 | baz |
48+
| calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar |
49+
| calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo |
50+
| calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar |
4851
| hello.rb:1:1:8:3 | EnglishWords | hello | hello.rb:2:5:4:7 | hello |
4952
| hello.rb:1:1:8:3 | EnglishWords | world | hello.rb:5:5:7:7 | world |
5053
| hello.rb:11:1:16:3 | Greeting | message | hello.rb:13:5:15:7 | message |
@@ -478,6 +481,22 @@ lookupMethod
478481
| calls.rb:605:1:612:3 | SingletonC | private_on_main | calls.rb:185:1:186:3 | private_on_main |
479482
| calls.rb:605:1:612:3 | SingletonC | puts | calls.rb:102:5:102:30 | puts |
480483
| calls.rb:605:1:612:3 | SingletonC | to_s | calls.rb:172:5:173:7 | to_s |
484+
| calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar |
485+
| calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo |
486+
| calls.rb:626:1:631:3 | IncludesIncluded | add_singleton | calls.rb:367:1:371:3 | add_singleton |
487+
| calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar |
488+
| calls.rb:626:1:631:3 | IncludesIncluded | call_block | calls.rb:81:1:83:3 | call_block |
489+
| calls.rb:626:1:631:3 | IncludesIncluded | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
490+
| calls.rb:626:1:631:3 | IncludesIncluded | create | calls.rb:278:1:286:3 | create |
491+
| calls.rb:626:1:631:3 | IncludesIncluded | foo | calls.rb:619:5:621:7 | foo |
492+
| calls.rb:626:1:631:3 | IncludesIncluded | funny | calls.rb:140:1:142:3 | funny |
493+
| calls.rb:626:1:631:3 | IncludesIncluded | indirect | calls.rb:158:1:160:3 | indirect |
494+
| calls.rb:626:1:631:3 | IncludesIncluded | new | calls.rb:117:5:117:16 | new |
495+
| calls.rb:626:1:631:3 | IncludesIncluded | optional_arg | calls.rb:76:1:79:3 | optional_arg |
496+
| calls.rb:626:1:631:3 | IncludesIncluded | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
497+
| calls.rb:626:1:631:3 | IncludesIncluded | private_on_main | calls.rb:185:1:186:3 | private_on_main |
498+
| calls.rb:626:1:631:3 | IncludesIncluded | puts | calls.rb:102:5:102:30 | puts |
499+
| calls.rb:626:1:631:3 | IncludesIncluded | to_s | calls.rb:172:5:173:7 | to_s |
481500
| file://:0:0:0:0 | Class | include | calls.rb:108:5:110:7 | include |
482501
| file://:0:0:0:0 | Class | module_eval | calls.rb:107:5:107:24 | module_eval |
483502
| file://:0:0:0:0 | Class | new | calls.rb:117:5:117:16 | new |
@@ -965,6 +984,9 @@ enclosingMethod
965984
| calls.rb:601:9:601:18 | self | calls.rb:600:5:602:7 | call_singleton1 |
966985
| calls.rb:610:9:610:18 | call to singleton1 | calls.rb:609:5:611:7 | call_singleton1 |
967986
| calls.rb:610:9:610:18 | self | calls.rb:609:5:611:7 | call_singleton1 |
987+
| calls.rb:620:9:620:12 | self | calls.rb:619:5:621:7 | foo |
988+
| calls.rb:620:9:620:16 | call to bar | calls.rb:619:5:621:7 | foo |
989+
| calls.rb:629:9:629:13 | call to super | calls.rb:628:5:630:7 | bar |
968990
| hello.rb:3:9:3:22 | return | hello.rb:2:5:4:7 | hello |
969991
| hello.rb:3:16:3:22 | "hello" | hello.rb:2:5:4:7 | hello |
970992
| hello.rb:3:17:3:21 | hello | hello.rb:2:5:4:7 | hello |

0 commit comments

Comments
 (0)