Ruby: Avoid using toString where possible

This commit is contained in:
Koen Vlaswinkel
2024-02-02 14:18:09 +01:00
parent ac1ebf27a7
commit f83d2a7d55
4 changed files with 84 additions and 32 deletions

View File

@@ -7,9 +7,38 @@
*/
private import ruby
private import codeql.ruby.AST
private import codeql.ruby.ApiGraphs
private import queries.modeling.internal.Util as Util
string parameterDetails(DataFlow::ParameterNode paramNode) {
exists(DataFlow::MethodNode methodNode | methodNode.getParameter(_) = paramNode |
result = paramNode.getName()
)
or
exists(DataFlow::MethodNode methodNode, string name |
methodNode.getKeywordParameter(name) = paramNode
|
result = name + ":"
)
or
exists(DataFlow::MethodNode methodNode | methodNode.getBlockParameter() = paramNode |
result = "&" + paramNode.getName()
or
not exists(paramNode.getName()) and result = "&"
)
or
exists(DataFlow::MethodNode methodNode | methodNode.getSelfParameter() = paramNode |
result = "self"
)
or
exists(DataFlow::MethodNode methodNode | methodNode.getHashSplatParameter() = paramNode |
result = "**" + paramNode.getName()
or
not exists(paramNode.getName()) and result = "**"
)
}
predicate simpleParameters(string type, string path, string value, string details) {
exists(DataFlow::MethodNode methodNode, DataFlow::ParameterNode paramNode |
methodNode.getLocation().getFile() instanceof Util::RelevantFile and
@@ -23,7 +52,7 @@ predicate simpleParameters(string type, string path, string value, string detail
|
Util::pathToMethod(methodNode, type, path) and
value = Util::getArgumentPath(paramNode) and
details = paramNode.toString()
details = parameterDetails(paramNode)
)
}
@@ -33,9 +62,11 @@ predicate blockArguments(string type, string path, string value, string details)
callNode = methodNode.getABlockCall()
|
(
exists(DataFlow::ExprNode argNode, int i | argNode = callNode.getPositionalArgument(i) |
exists(DataFlow::VariableAccessNode argNode, int i |
argNode = callNode.getPositionalArgument(i)
|
value = "Argument[block].Parameter[" + i + "]" and
details = argNode.toString()
details = argNode.asVariableAccessAstNode().getVariable().getName()
)
or
exists(DataFlow::ExprNode argNode, string keyword |
@@ -45,7 +76,14 @@ predicate blockArguments(string type, string path, string value, string details)
details = ":" + keyword
)
or
value = "Argument[block]" and details = callNode.toString()
value = "Argument[block]" and
(
details = callNode.getMethodName()
or
not exists(callNode.getMethodName()) and
callNode.getExprNode().getExpr() instanceof YieldCall and
details = "yield ..."
)
) and
Util::pathToMethod(methodNode, type, path)
)

View File

@@ -1,58 +1,69 @@
input
| A | Method[bar] | Argument[0] | x | parameter |
| A | Method[bar] | Argument[self] | self in bar | parameter |
| A | Method[bar] | Argument[self] | self | parameter |
| A | Method[foo] | Argument[0] | x | parameter |
| A | Method[foo] | Argument[1] | y | parameter |
| A | Method[foo] | Argument[2] | key1 | parameter |
| A | Method[foo] | Argument[key1:] | key1 | parameter |
| A | Method[foo] | Argument[self] | self in foo | parameter |
| A | Method[foo] | Argument[2] | key1: | parameter |
| A | Method[foo] | Argument[block] | call | parameter |
| A | Method[foo] | Argument[block] | yield ... | parameter |
| A | Method[foo] | Argument[block].Parameter[0] | x | parameter |
| A | Method[foo] | Argument[block].Parameter[1] | y | parameter |
| A | Method[foo] | Argument[block].Parameter[key2:] | :key2 | parameter |
| A | Method[foo] | Argument[key1:] | key1: | parameter |
| A | Method[foo] | Argument[self] | self | parameter |
| A! | Method[new] | Argument[0] | x | parameter |
| A! | Method[new] | Argument[1] | y | parameter |
| A! | Method[new] | Argument[self] | self in initialize | parameter |
| A! | Method[new] | Argument[self] | self | parameter |
| A! | Method[self_foo] | Argument[0] | x | parameter |
| A! | Method[self_foo] | Argument[1] | y | parameter |
| A! | Method[self_foo] | Argument[self] | self in self_foo | parameter |
| A! | Method[self_foo] | Argument[self] | self | parameter |
| A::ANested | Method[foo] | Argument[0] | x | parameter |
| A::ANested | Method[foo] | Argument[1] | y | parameter |
| A::ANested | Method[foo] | Argument[self] | self in foo | parameter |
| A::ANested | Method[foo] | Argument[self] | self | parameter |
| B | Method[foo] | Argument[0] | x | parameter |
| B | Method[foo] | Argument[1] | y | parameter |
| B | Method[foo] | Argument[self] | self in foo | parameter |
| B | Method[foo] | Argument[self] | self | parameter |
| M1 | Method[foo] | Argument[0] | x | parameter |
| M1 | Method[foo] | Argument[1] | y | parameter |
| M1 | Method[foo] | Argument[self] | self in foo | parameter |
| M1 | Method[foo] | Argument[self] | self | parameter |
| M1! | Method[self_foo] | Argument[0] | x | parameter |
| M1! | Method[self_foo] | Argument[1] | y | parameter |
| M1! | Method[self_foo] | Argument[self] | self in self_foo | parameter |
| M1! | Method[self_foo] | Argument[self] | self | parameter |
| OtherLib::A | Method[foo] | Argument[0] | x | parameter |
| OtherLib::A | Method[foo] | Argument[1] | y | parameter |
| OtherLib::A | Method[foo] | Argument[self] | self in foo | parameter |
| OtherLib::A | Method[foo] | Argument[self] | self | parameter |
output
| A | Method[bar] | Argument[0] | x | parameter |
| A | Method[bar] | Argument[self] | self in bar | parameter |
| A | Method[bar] | Argument[self] | self | parameter |
| A | Method[foo] | Argument[0] | x | parameter |
| A | Method[foo] | Argument[1] | y | parameter |
| A | Method[foo] | Argument[2] | key1 | parameter |
| A | Method[foo] | Argument[key1:] | key1 | parameter |
| A | Method[foo] | Argument[self] | self in foo | parameter |
| A | Method[foo] | Argument[2] | key1: | parameter |
| A | Method[foo] | Argument[block] | call | parameter |
| A | Method[foo] | Argument[block] | yield ... | parameter |
| A | Method[foo] | Argument[block].Parameter[0] | x | parameter |
| A | Method[foo] | Argument[block].Parameter[1] | y | parameter |
| A | Method[foo] | Argument[block].Parameter[key2:] | :key2 | parameter |
| A | Method[foo] | Argument[key1:] | key1: | parameter |
| A | Method[foo] | Argument[self] | self | parameter |
| A | Method[foo] | ReturnValue | yield ... | return |
| A! | Method[new] | Argument[0] | x | parameter |
| A! | Method[new] | Argument[1] | y | parameter |
| A! | Method[new] | Argument[self] | self in initialize | parameter |
| A! | Method[new] | Argument[self] | self | parameter |
| A! | Method[self_foo] | Argument[0] | x | parameter |
| A! | Method[self_foo] | Argument[1] | y | parameter |
| A! | Method[self_foo] | Argument[self] | self in self_foo | parameter |
| A! | Method[self_foo] | Argument[self] | self | parameter |
| A::ANested | Method[foo] | Argument[0] | x | parameter |
| A::ANested | Method[foo] | Argument[1] | y | parameter |
| A::ANested | Method[foo] | Argument[self] | self in foo | parameter |
| A::ANested | Method[foo] | Argument[self] | self | parameter |
| B | Method[foo] | Argument[0] | x | parameter |
| B | Method[foo] | Argument[1] | y | parameter |
| B | Method[foo] | Argument[self] | self in foo | parameter |
| B | Method[foo] | Argument[self] | self | parameter |
| M1 | Method[foo] | Argument[0] | x | parameter |
| M1 | Method[foo] | Argument[1] | y | parameter |
| M1 | Method[foo] | Argument[self] | self in foo | parameter |
| M1 | Method[foo] | Argument[self] | self | parameter |
| M1! | Method[self_foo] | Argument[0] | x | parameter |
| M1! | Method[self_foo] | Argument[1] | y | parameter |
| M1! | Method[self_foo] | Argument[self] | self in self_foo | parameter |
| M1! | Method[self_foo] | Argument[self] | self | parameter |
| OtherLib::A | Method[foo] | Argument[0] | x | parameter |
| OtherLib::A | Method[foo] | Argument[1] | y | parameter |
| OtherLib::A | Method[foo] | Argument[self] | self in foo | parameter |
| OtherLib::A | Method[foo] | Argument[self] | self | parameter |

View File

@@ -1,13 +1,13 @@
| lib/module.rb:1:1:7:3 | M1 | mylib | M1 | | | false | module.rb | |
| lib/module.rb:2:3:3:5 | foo | mylib | M1 | foo | (x,y) | false | module.rb | |
| lib/module.rb:5:3:6:5 | self_foo | mylib | M1! | self_foo | (x,y) | false | module.rb | |
| lib/mylib.rb:3:1:30:3 | A | mylib | A | | | false | mylib.rb | |
| lib/mylib.rb:3:1:33:3 | A | mylib | A | | | false | mylib.rb | |
| lib/mylib.rb:4:3:5:5 | initialize | mylib | A! | new | (x,y) | false | mylib.rb | |
| lib/mylib.rb:7:3:8:5 | foo | mylib | A | foo | (x,y,key1:) | false | mylib.rb | |
| lib/mylib.rb:10:3:11:5 | bar | mylib | A | bar | (x) | false | mylib.rb | |
| lib/mylib.rb:13:3:14:5 | self_foo | mylib | A! | self_foo | (x,y) | false | mylib.rb | |
| lib/mylib.rb:21:3:29:5 | ANested | mylib | A::ANested | | | false | mylib.rb | |
| lib/mylib.rb:22:5:23:7 | foo | mylib | A::ANested | foo | (x,y) | false | mylib.rb | |
| lib/mylib.rb:7:3:11:5 | foo | mylib | A | foo | (x,y,key1:) | false | mylib.rb | |
| lib/mylib.rb:13:3:14:5 | bar | mylib | A | bar | (x) | false | mylib.rb | |
| lib/mylib.rb:16:3:17:5 | self_foo | mylib | A! | self_foo | (x,y) | false | mylib.rb | |
| lib/mylib.rb:24:3:32:5 | ANested | mylib | A::ANested | | | false | mylib.rb | |
| lib/mylib.rb:25:5:26:7 | foo | mylib | A::ANested | foo | (x,y) | false | mylib.rb | |
| lib/other.rb:3:1:8:3 | B | mylib | B | | | false | other.rb | |
| lib/other.rb:6:3:7:5 | foo | mylib | B | foo | (x,y) | false | other.rb | |
| lib/other.rb:10:1:12:3 | C | mylib | C | | | false | other.rb | |

View File

@@ -5,6 +5,9 @@ class A
end
def foo(x, y, key1:, **kwargs, &block)
block.call(x, y, key2: key1)
yield x, y, key2: key1
end
def bar(x, *args)