Merge pull request #11718 from hvitved/ruby/self-allocate

Ruby: Recognize custom `self.new` methods that return `self.allocate`
This commit is contained in:
Tom Hvitved 2022-12-16 14:46:08 +01:00 коммит произвёл GitHub
Родитель b2856c1f5a accf4ca364
Коммит 5fba5e4895
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 720 добавлений и 604 удалений

Просмотреть файл

@ -473,9 +473,12 @@ private DataFlow::LocalSourceNode trackModuleAccess(Module m) {
}
pragma[nomagic]
private predicate hasUserDefinedSelf(Module m) {
// cannot use `lookupSingletonMethod` due to negative recursion
singletonMethodOnModule(_, "new", m.getSuperClass*()) // not `getAnAncestor` because singleton methods cannot be included
private predicate hasUserDefinedNew(Module m) {
exists(DataFlow::MethodNode method |
// not `getAnAncestor` because singleton methods cannot be included
singletonMethodOnModule(method.asCallableAstNode(), "new", m.getSuperClass*()) and
not method.getSelfParameter().getAMethodCall("allocate").flowsTo(method.getAReturningNode())
)
}
/** Holds if `n` is an instance of type `tp`. */
@ -536,7 +539,7 @@ private predicate isInstance(DataFlow::Node n, Module tp, boolean exact) {
flowsToMethodCallReceiver(call, sourceNode, "new") and
n.asExpr() = call and
// `tp` should not have a user-defined `self.new` method
not hasUserDefinedSelf(tp)
not hasUserDefinedNew(tp)
|
// `C.new`
sourceNode = trackModuleAccess(tp) and

Просмотреть файл

@ -142,6 +142,12 @@ calls.rb:
#-----| super -> Object
#-----| include -> Included
# 633| CustomNew1
#-----| super -> Object
# 641| CustomNew2
#-----| super -> Object
hello.rb:
# 1| EnglishWords

Просмотреть файл

@ -237,6 +237,14 @@ getTarget
| calls.rb:620:9:620:16 | call to bar | calls.rb:628:5:630:7 | bar |
| calls.rb:627:5:627:20 | call to include | calls.rb:108:5:110:7 | include |
| calls.rb:629:9:629:13 | call to super | calls.rb:622:5:623:7 | bar |
| calls.rb:635:9:635:14 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:639:1:639:14 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:639:1:639:14 | call to new | calls.rb:634:5:636:7 | new |
| calls.rb:639:1:639:23 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:647:9:647:34 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:651:1:651:14 | call to new | calls.rb:117:5:117:16 | new |
| calls.rb:651:1:651:14 | call to new | calls.rb:642:5:644:7 | new |
| calls.rb:651:1:651:23 | call to instance | calls.rb:646:5:648:7 | instance |
| hello.rb:12:5:12:24 | call to include | calls.rb:108:5:110:7 | include |
| hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello |
| hello.rb:20:16:20:20 | call to super | hello.rb:13:5:15:7 | message |
@ -361,6 +369,7 @@ unresolvedCall
| calls.rb:562:1:562:13 | call to [] |
| calls.rb:562:1:562:39 | call to each |
| calls.rb:570:5:570:14 | call to singleton2 |
| calls.rb:643:9:643:21 | call to allocate |
| hello.rb:20:16:20:26 | ... + ... |
| hello.rb:20:16:20:34 | ... + ... |
| hello.rb:20:16:20:40 | ... + ... |
@ -483,6 +492,9 @@ publicMethod
| calls.rb:619:5:621:7 | foo |
| calls.rb:622:5:623:7 | bar |
| calls.rb:628:5:630:7 | bar |
| calls.rb:634:5:636:7 | new |
| calls.rb:642:5:644:7 | new |
| calls.rb:646:5:648:7 | instance |
| hello.rb:2:5:4:7 | hello |
| hello.rb:5:5:7:7 | world |
| hello.rb:13:5:15:7 | message |

Просмотреть файл

@ -630,3 +630,22 @@ class IncludesIncluded
end
end
class CustomNew1
def self.new
C1.new
end
end
CustomNew1.new.instance
class CustomNew2
def self.new
self.allocate
end
def instance
puts "CustomNew2#instance"
end
end
CustomNew2.new.instance

Просмотреть файл

@ -48,6 +48,7 @@ getMethod
| calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar |
| calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo |
| calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar |
| calls.rb:641:1:649:3 | CustomNew2 | instance | calls.rb:646:5:648:7 | instance |
| hello.rb:1:1:8:3 | EnglishWords | hello | hello.rb:2:5:4:7 | hello |
| hello.rb:1:1:8:3 | EnglishWords | world | hello.rb:5:5:7:7 | world |
| hello.rb:11:1:16:3 | Greeting | message | hello.rb:13:5:15:7 | message |
@ -497,6 +498,35 @@ lookupMethod
| calls.rb:626:1:631:3 | IncludesIncluded | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:626:1:631:3 | IncludesIncluded | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:626:1:631:3 | IncludesIncluded | to_s | calls.rb:172:5:173:7 | to_s |
| calls.rb:633:1:637:3 | CustomNew1 | add_singleton | calls.rb:367:1:371:3 | add_singleton |
| calls.rb:633:1:637:3 | CustomNew1 | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:633:1:637:3 | CustomNew1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
| calls.rb:633:1:637:3 | CustomNew1 | create | calls.rb:278:1:286:3 | create |
| calls.rb:633:1:637:3 | CustomNew1 | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:633:1:637:3 | CustomNew1 | foo | calls.rb:85:1:89:3 | foo |
| calls.rb:633:1:637:3 | CustomNew1 | funny | calls.rb:140:1:142:3 | funny |
| calls.rb:633:1:637:3 | CustomNew1 | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:633:1:637:3 | CustomNew1 | new | calls.rb:117:5:117:16 | new |
| calls.rb:633:1:637:3 | CustomNew1 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
| calls.rb:633:1:637:3 | CustomNew1 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
| calls.rb:633:1:637:3 | CustomNew1 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:633:1:637:3 | CustomNew1 | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:633:1:637:3 | CustomNew1 | to_s | calls.rb:172:5:173:7 | to_s |
| calls.rb:641:1:649:3 | CustomNew2 | add_singleton | calls.rb:367:1:371:3 | add_singleton |
| calls.rb:641:1:649:3 | CustomNew2 | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:641:1:649:3 | CustomNew2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
| calls.rb:641:1:649:3 | CustomNew2 | create | calls.rb:278:1:286:3 | create |
| calls.rb:641:1:649:3 | CustomNew2 | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:641:1:649:3 | CustomNew2 | foo | calls.rb:85:1:89:3 | foo |
| calls.rb:641:1:649:3 | CustomNew2 | funny | calls.rb:140:1:142:3 | funny |
| calls.rb:641:1:649:3 | CustomNew2 | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:641:1:649:3 | CustomNew2 | instance | calls.rb:646:5:648:7 | instance |
| calls.rb:641:1:649:3 | CustomNew2 | new | calls.rb:117:5:117:16 | new |
| calls.rb:641:1:649:3 | CustomNew2 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
| calls.rb:641:1:649:3 | CustomNew2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
| calls.rb:641:1:649:3 | CustomNew2 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:641:1:649:3 | CustomNew2 | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:641:1:649:3 | CustomNew2 | to_s | calls.rb:172:5:173:7 | to_s |
| file://:0:0:0:0 | Class | include | calls.rb:108:5:110:7 | include |
| file://:0:0:0:0 | Class | module_eval | calls.rb:107:5:107:24 | module_eval |
| file://:0:0:0:0 | Class | new | calls.rb:117:5:117:16 | new |
@ -987,6 +1017,14 @@ enclosingMethod
| calls.rb:620:9:620:12 | self | calls.rb:619:5:621:7 | foo |
| calls.rb:620:9:620:16 | call to bar | calls.rb:619:5:621:7 | foo |
| calls.rb:629:9:629:13 | call to super | calls.rb:628:5:630:7 | bar |
| calls.rb:635:9:635:10 | C1 | calls.rb:634:5:636:7 | new |
| calls.rb:635:9:635:14 | call to new | calls.rb:634:5:636:7 | new |
| calls.rb:643:9:643:12 | self | calls.rb:642:5:644:7 | new |
| calls.rb:643:9:643:21 | call to allocate | calls.rb:642:5:644:7 | new |
| calls.rb:647:9:647:34 | call to puts | calls.rb:646:5:648:7 | instance |
| calls.rb:647:9:647:34 | self | calls.rb:646:5:648:7 | instance |
| calls.rb:647:14:647:34 | "CustomNew2#instance" | calls.rb:646:5:648:7 | instance |
| calls.rb:647:15:647:33 | CustomNew2#instance | calls.rb:646:5:648:7 | instance |
| hello.rb:3:9:3:22 | return | hello.rb:2:5:4:7 | hello |
| hello.rb:3:16:3:22 | "hello" | hello.rb:2:5:4:7 | hello |
| hello.rb:3:17:3:21 | hello | hello.rb:2:5:4:7 | hello |

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -136,6 +136,12 @@ calls.rb:
# 626| IncludesIncluded
#-----| -> Object
# 633| CustomNew1
#-----| -> Object
# 641| CustomNew2
#-----| -> Object
hello.rb:
# 1| EnglishWords