diff --git a/ql/src/codeql_ruby/ast/internal/Call.qll b/ql/src/codeql_ruby/ast/internal/Call.qll index ca35a21e07c..595d25f5944 100644 --- a/ql/src/codeql_ruby/ast/internal/Call.qll +++ b/ql/src/codeql_ruby/ast/internal/Call.qll @@ -45,8 +45,7 @@ module Call { ScopeResolutionIdentifierCallRange() { identifier = generated.getName() and - vcall(this) and - not access(identifier, _) + not exists(Generated::Call c | c.getMethod() = this) } final override Expr getReceiver() { result = generated.getScope() } @@ -69,12 +68,20 @@ module Call { } final override string getMethodName() { - result = generated.getMethod().(Generated::Token).getValue() or + result = "call" and generated.getMethod() instanceof Generated::ArgumentList + or + result = generated.getMethod().(Generated::Token).getValue() + or result = generated.getMethod().(Generated::ScopeResolution).getName().(Generated::Token).getValue() } - final override Expr getArgument(int n) { result = generated.getArguments().getChild(n) } + final override Expr getArgument(int n) { + result = generated.getArguments().getChild(n) + or + not exists(generated.getArguments()) and + result = generated.getMethod().(Generated::ArgumentList).getChild(n) + } final override Block getBlock() { result = generated.getBlock() } } diff --git a/ql/test/library-tests/ast/calls/calls.expected b/ql/test/library-tests/ast/calls/calls.expected index ced558cc079..6ba250f77dc 100644 --- a/ql/test/library-tests/ast/calls/calls.expected +++ b/ql/test/library-tests/ast/calls/calls.expected @@ -75,6 +75,8 @@ callsWithNoReceiverArgumentsOrBlock | calls.rb:287:5:287:11 | call to super | super | | calls.rb:303:5:303:7 | call to foo | foo | | calls.rb:305:5:305:9 | call to super | super | +| calls.rb:310:1:310:3 | call to foo | foo | +| calls.rb:311:1:311:3 | call to foo | foo | callsWithArguments | calls.rb:14:1:14:11 | call to foo | foo | 0 | calls.rb:14:5:14:5 | 0 | | calls.rb:14:1:14:11 | call to foo | foo | 1 | calls.rb:14:8:14:8 | 1 | @@ -102,6 +104,7 @@ callsWithArguments | calls.rb:292:5:292:30 | call to super | super | 1 | calls.rb:292:14:292:14 | 5 | | calls.rb:293:5:293:33 | call to super | super | 0 | calls.rb:293:11:293:11 | 6 | | calls.rb:293:5:293:33 | call to super | super | 1 | calls.rb:293:14:293:14 | 7 | +| calls.rb:311:1:311:7 | call to call | call | 0 | calls.rb:311:6:311:6 | 1 | callsWithReceiver | calls.rb:5:1:5:10 | call to bar | calls.rb:5:1:5:3 | Foo | | calls.rb:11:1:11:7 | call to bar | calls.rb:11:1:11:3 | 123 | @@ -179,6 +182,8 @@ callsWithReceiver | calls.rb:303:5:303:13 | call to super | calls.rb:303:5:303:7 | call to foo | | calls.rb:304:5:304:14 | call to super | calls.rb:304:5:304:8 | self | | calls.rb:305:5:305:15 | call to super | calls.rb:305:5:305:9 | call to super | +| calls.rb:310:1:310:6 | call to call | calls.rb:310:1:310:3 | call to foo | +| calls.rb:311:1:311:7 | call to call | calls.rb:311:1:311:3 | call to foo | callsWithBlock | calls.rb:17:1:17:17 | call to foo | calls.rb:17:5:17:17 | { ... } | | calls.rb:20:1:22:3 | call to foo | calls.rb:20:5:22:3 | do ... end | diff --git a/ql/test/library-tests/ast/calls/calls.ql b/ql/test/library-tests/ast/calls/calls.ql index 93861bef7a1..f49874f8ed0 100644 --- a/ql/test/library-tests/ast/calls/calls.ql +++ b/ql/test/library-tests/ast/calls/calls.ql @@ -1,15 +1,21 @@ import ruby import codeql_ruby.ast.internal.TreeSitter +private string getMethodName(Call c) { + result = c.getMethodName() + or + not exists(c.getMethodName()) and result = "(none)" +} + query predicate callsWithNoReceiverArgumentsOrBlock(Call c, string name) { - name = c.getMethodName() and + name = getMethodName(c) and not exists(c.getReceiver()) and not exists(c.getAnArgument()) and not exists(c.getBlock()) } query predicate callsWithArguments(Call c, string name, int n, Expr argN) { - name = c.getMethodName() and + name = getMethodName(c) and argN = c.getArgument(n) } diff --git a/ql/test/library-tests/ast/calls/calls.rb b/ql/test/library-tests/ast/calls/calls.rb index fa44b5fad0b..9a49cc82059 100644 --- a/ql/test/library-tests/ast/calls/calls.rb +++ b/ql/test/library-tests/ast/calls/calls.rb @@ -305,3 +305,8 @@ class AnotherClass super.super # we expect the receiver to be a SuperCall, while the outer call should not (it's just a regular Call) end end + +# calls without method name +foo.() +foo.(1) +