Skip to content

Commit 87eb1ab

Browse files
committed
Ruby: Include ReturnValue and exclude self for constructors
1 parent 8646bff commit 87eb1ab

File tree

5 files changed

+69
-54
lines changed

5 files changed

+69
-54
lines changed

ruby/ql/src/utils/modeleditor/FrameworkModeAccessPaths.ql

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ predicate simpleParameters(string type, string path, string value, DataFlow::Nod
2020
// Block parameter explicitly excluded because it's already included
2121
// as part of the blockArguments predicate
2222
paramNode = Util::getAnyParameter(methodNode) and
23-
paramNode != methodNode.getBlockParameter()
23+
paramNode != methodNode.getBlockParameter() and
24+
// The self parameter of a constructor is not a parameter that can be used in any models
25+
(not isConstructor(methodNode) or paramNode != methodNode.getSelfParameter())
2426
)
2527
|
2628
Util::pathToMethod(methodNode, type, path) and
@@ -60,12 +62,24 @@ predicate returnValue(string type, string path, string value, DataFlow::Node nod
6062
exists(DataFlow::MethodNode methodNode, DataFlow::Node returnNode |
6163
methodNode.getLocation().getFile() instanceof Util::RelevantFile and
6264
returnNode = methodNode.getAReturnNode() and
63-
not isConstructor(methodNode) // A constructor doesn't have a return value
65+
not isConstructor(methodNode)
6466
|
6567
Util::pathToMethod(methodNode, type, path) and
6668
value = "ReturnValue" and
6769
node = returnNode
6870
)
71+
or
72+
// A constructor has a return node for every statement, but we always want
73+
// to return 1 node for the ReturnValue, so we return the self parameter
74+
// instead.
75+
exists(DataFlow::MethodNode methodNode |
76+
methodNode.getLocation().getFile() instanceof Util::RelevantFile and
77+
isConstructor(methodNode)
78+
|
79+
Util::pathToMethod(methodNode, type, path) and
80+
value = "ReturnValue" and
81+
node = methodNode.getSelfParameter()
82+
)
6983
}
7084

7185
predicate inputAccessPaths(

ruby/ql/test/query-tests/utils/modeleditor/FrameworkModeAccessPaths.expected

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
input
2-
| A | Method[bar] | Argument[0] | lib/mylib.rb:13:11:13:11 | x | parameter |
3-
| A | Method[bar] | Argument[self] | lib/mylib.rb:13:3:14:5 | self in bar | parameter |
4-
| A | Method[foo] | Argument[0] | lib/mylib.rb:7:11:7:11 | x | parameter |
5-
| A | Method[foo] | Argument[1] | lib/mylib.rb:7:14:7:14 | y | parameter |
6-
| A | Method[foo] | Argument[2] | lib/mylib.rb:7:17:7:20 | key1 | parameter |
7-
| A | Method[foo] | Argument[block] | lib/mylib.rb:8:5:8:32 | call to call | parameter |
8-
| A | Method[foo] | Argument[block] | lib/mylib.rb:10:5:10:26 | yield ... | parameter |
9-
| A | Method[foo] | Argument[block].Parameter[0] | lib/mylib.rb:8:16:8:16 | x | parameter |
10-
| A | Method[foo] | Argument[block].Parameter[0] | lib/mylib.rb:10:11:10:11 | x | parameter |
11-
| A | Method[foo] | Argument[block].Parameter[1] | lib/mylib.rb:8:19:8:19 | y | parameter |
12-
| A | Method[foo] | Argument[block].Parameter[1] | lib/mylib.rb:10:14:10:14 | y | parameter |
13-
| A | Method[foo] | Argument[block].Parameter[key2:] | lib/mylib.rb:8:28:8:31 | key1 | parameter |
14-
| A | Method[foo] | Argument[block].Parameter[key2:] | lib/mylib.rb:10:23:10:26 | key1 | parameter |
15-
| A | Method[foo] | Argument[key1:] | lib/mylib.rb:7:17:7:20 | key1 | parameter |
16-
| A | Method[foo] | Argument[self] | lib/mylib.rb:7:3:11:5 | self in foo | parameter |
2+
| A | Method[bar] | Argument[0] | lib/mylib.rb:14:11:14:11 | x | parameter |
3+
| A | Method[bar] | Argument[self] | lib/mylib.rb:14:3:15:5 | self in bar | parameter |
4+
| A | Method[foo] | Argument[0] | lib/mylib.rb:8:11:8:11 | x | parameter |
5+
| A | Method[foo] | Argument[1] | lib/mylib.rb:8:14:8:14 | y | parameter |
6+
| A | Method[foo] | Argument[2] | lib/mylib.rb:8:17:8:20 | key1 | parameter |
7+
| A | Method[foo] | Argument[block] | lib/mylib.rb:9:5:9:32 | call to call | parameter |
8+
| A | Method[foo] | Argument[block] | lib/mylib.rb:11:5:11:26 | yield ... | parameter |
9+
| A | Method[foo] | Argument[block].Parameter[0] | lib/mylib.rb:9:16:9:16 | x | parameter |
10+
| A | Method[foo] | Argument[block].Parameter[0] | lib/mylib.rb:11:11:11:11 | x | parameter |
11+
| A | Method[foo] | Argument[block].Parameter[1] | lib/mylib.rb:9:19:9:19 | y | parameter |
12+
| A | Method[foo] | Argument[block].Parameter[1] | lib/mylib.rb:11:14:11:14 | y | parameter |
13+
| A | Method[foo] | Argument[block].Parameter[key2:] | lib/mylib.rb:9:28:9:31 | key1 | parameter |
14+
| A | Method[foo] | Argument[block].Parameter[key2:] | lib/mylib.rb:11:23:11:26 | key1 | parameter |
15+
| A | Method[foo] | Argument[key1:] | lib/mylib.rb:8:17:8:20 | key1 | parameter |
16+
| A | Method[foo] | Argument[self] | lib/mylib.rb:8:3:12:5 | self in foo | parameter |
1717
| A! | Method[new] | Argument[0] | lib/mylib.rb:4:18:4:18 | x | parameter |
1818
| A! | Method[new] | Argument[1] | lib/mylib.rb:4:21:4:21 | y | parameter |
19-
| A! | Method[new] | Argument[self] | lib/mylib.rb:4:3:5:5 | self in initialize | parameter |
20-
| A! | Method[self_foo] | Argument[0] | lib/mylib.rb:16:21:16:21 | x | parameter |
21-
| A! | Method[self_foo] | Argument[1] | lib/mylib.rb:16:24:16:24 | y | parameter |
22-
| A! | Method[self_foo] | Argument[self] | lib/mylib.rb:16:3:17:5 | self in self_foo | parameter |
23-
| A::ANested | Method[foo] | Argument[0] | lib/mylib.rb:25:13:25:13 | x | parameter |
24-
| A::ANested | Method[foo] | Argument[1] | lib/mylib.rb:25:16:25:16 | y | parameter |
25-
| A::ANested | Method[foo] | Argument[self] | lib/mylib.rb:25:5:26:7 | self in foo | parameter |
19+
| A! | Method[self_foo] | Argument[0] | lib/mylib.rb:17:21:17:21 | x | parameter |
20+
| A! | Method[self_foo] | Argument[1] | lib/mylib.rb:17:24:17:24 | y | parameter |
21+
| A! | Method[self_foo] | Argument[self] | lib/mylib.rb:17:3:18:5 | self in self_foo | parameter |
22+
| A::ANested | Method[foo] | Argument[0] | lib/mylib.rb:26:13:26:13 | x | parameter |
23+
| A::ANested | Method[foo] | Argument[1] | lib/mylib.rb:26:16:26:16 | y | parameter |
24+
| A::ANested | Method[foo] | Argument[self] | lib/mylib.rb:26:5:27:7 | self in foo | parameter |
2625
| B | Method[foo] | Argument[0] | lib/other.rb:6:11:6:11 | x | parameter |
2726
| B | Method[foo] | Argument[1] | lib/other.rb:6:14:6:14 | y | parameter |
2827
| B | Method[foo] | Argument[self] | lib/other.rb:6:3:7:5 | self in foo | parameter |
@@ -36,31 +35,31 @@ input
3635
| OtherLib::A | Method[foo] | Argument[1] | other_lib/lib/other_gem.rb:3:20:3:20 | y | parameter |
3736
| OtherLib::A | Method[foo] | Argument[self] | other_lib/lib/other_gem.rb:3:9:4:11 | self in foo | parameter |
3837
output
39-
| A | Method[bar] | Argument[0] | lib/mylib.rb:13:11:13:11 | x | parameter |
40-
| A | Method[bar] | Argument[self] | lib/mylib.rb:13:3:14:5 | self in bar | parameter |
41-
| A | Method[foo] | Argument[0] | lib/mylib.rb:7:11:7:11 | x | parameter |
42-
| A | Method[foo] | Argument[1] | lib/mylib.rb:7:14:7:14 | y | parameter |
43-
| A | Method[foo] | Argument[2] | lib/mylib.rb:7:17:7:20 | key1 | parameter |
44-
| A | Method[foo] | Argument[block] | lib/mylib.rb:8:5:8:32 | call to call | parameter |
45-
| A | Method[foo] | Argument[block] | lib/mylib.rb:10:5:10:26 | yield ... | parameter |
46-
| A | Method[foo] | Argument[block].Parameter[0] | lib/mylib.rb:8:16:8:16 | x | parameter |
47-
| A | Method[foo] | Argument[block].Parameter[0] | lib/mylib.rb:10:11:10:11 | x | parameter |
48-
| A | Method[foo] | Argument[block].Parameter[1] | lib/mylib.rb:8:19:8:19 | y | parameter |
49-
| A | Method[foo] | Argument[block].Parameter[1] | lib/mylib.rb:10:14:10:14 | y | parameter |
50-
| A | Method[foo] | Argument[block].Parameter[key2:] | lib/mylib.rb:8:28:8:31 | key1 | parameter |
51-
| A | Method[foo] | Argument[block].Parameter[key2:] | lib/mylib.rb:10:23:10:26 | key1 | parameter |
52-
| A | Method[foo] | Argument[key1:] | lib/mylib.rb:7:17:7:20 | key1 | parameter |
53-
| A | Method[foo] | Argument[self] | lib/mylib.rb:7:3:11:5 | self in foo | parameter |
54-
| A | Method[foo] | ReturnValue | lib/mylib.rb:10:5:10:26 | yield ... | return |
38+
| A | Method[bar] | Argument[0] | lib/mylib.rb:14:11:14:11 | x | parameter |
39+
| A | Method[bar] | Argument[self] | lib/mylib.rb:14:3:15:5 | self in bar | parameter |
40+
| A | Method[foo] | Argument[0] | lib/mylib.rb:8:11:8:11 | x | parameter |
41+
| A | Method[foo] | Argument[1] | lib/mylib.rb:8:14:8:14 | y | parameter |
42+
| A | Method[foo] | Argument[2] | lib/mylib.rb:8:17:8:20 | key1 | parameter |
43+
| A | Method[foo] | Argument[block] | lib/mylib.rb:9:5:9:32 | call to call | parameter |
44+
| A | Method[foo] | Argument[block] | lib/mylib.rb:11:5:11:26 | yield ... | parameter |
45+
| A | Method[foo] | Argument[block].Parameter[0] | lib/mylib.rb:9:16:9:16 | x | parameter |
46+
| A | Method[foo] | Argument[block].Parameter[0] | lib/mylib.rb:11:11:11:11 | x | parameter |
47+
| A | Method[foo] | Argument[block].Parameter[1] | lib/mylib.rb:9:19:9:19 | y | parameter |
48+
| A | Method[foo] | Argument[block].Parameter[1] | lib/mylib.rb:11:14:11:14 | y | parameter |
49+
| A | Method[foo] | Argument[block].Parameter[key2:] | lib/mylib.rb:9:28:9:31 | key1 | parameter |
50+
| A | Method[foo] | Argument[block].Parameter[key2:] | lib/mylib.rb:11:23:11:26 | key1 | parameter |
51+
| A | Method[foo] | Argument[key1:] | lib/mylib.rb:8:17:8:20 | key1 | parameter |
52+
| A | Method[foo] | Argument[self] | lib/mylib.rb:8:3:12:5 | self in foo | parameter |
53+
| A | Method[foo] | ReturnValue | lib/mylib.rb:11:5:11:26 | yield ... | return |
5554
| A! | Method[new] | Argument[0] | lib/mylib.rb:4:18:4:18 | x | parameter |
5655
| A! | Method[new] | Argument[1] | lib/mylib.rb:4:21:4:21 | y | parameter |
57-
| A! | Method[new] | Argument[self] | lib/mylib.rb:4:3:5:5 | self in initialize | parameter |
58-
| A! | Method[self_foo] | Argument[0] | lib/mylib.rb:16:21:16:21 | x | parameter |
59-
| A! | Method[self_foo] | Argument[1] | lib/mylib.rb:16:24:16:24 | y | parameter |
60-
| A! | Method[self_foo] | Argument[self] | lib/mylib.rb:16:3:17:5 | self in self_foo | parameter |
61-
| A::ANested | Method[foo] | Argument[0] | lib/mylib.rb:25:13:25:13 | x | parameter |
62-
| A::ANested | Method[foo] | Argument[1] | lib/mylib.rb:25:16:25:16 | y | parameter |
63-
| A::ANested | Method[foo] | Argument[self] | lib/mylib.rb:25:5:26:7 | self in foo | parameter |
56+
| A! | Method[new] | ReturnValue | lib/mylib.rb:4:3:6:5 | self in initialize | return |
57+
| A! | Method[self_foo] | Argument[0] | lib/mylib.rb:17:21:17:21 | x | parameter |
58+
| A! | Method[self_foo] | Argument[1] | lib/mylib.rb:17:24:17:24 | y | parameter |
59+
| A! | Method[self_foo] | Argument[self] | lib/mylib.rb:17:3:18:5 | self in self_foo | parameter |
60+
| A::ANested | Method[foo] | Argument[0] | lib/mylib.rb:26:13:26:13 | x | parameter |
61+
| A::ANested | Method[foo] | Argument[1] | lib/mylib.rb:26:16:26:16 | y | parameter |
62+
| A::ANested | Method[foo] | Argument[self] | lib/mylib.rb:26:5:27:7 | self in foo | parameter |
6463
| B | Method[foo] | Argument[0] | lib/other.rb:6:11:6:11 | x | parameter |
6564
| B | Method[foo] | Argument[1] | lib/other.rb:6:14:6:14 | y | parameter |
6665
| B | Method[foo] | Argument[self] | lib/other.rb:6:3:7:5 | self in foo | parameter |

ruby/ql/test/query-tests/utils/modeleditor/FrameworkModeEndpoints.expected

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
| lib/module.rb:1:1:7:3 | M1 | mylib | M1 | | | false | module.rb | |
22
| lib/module.rb:2:3:3:5 | foo | mylib | M1 | foo | (x,y) | false | module.rb | |
33
| lib/module.rb:5:3:6:5 | self_foo | mylib | M1! | self_foo | (x,y) | false | module.rb | |
4-
| lib/mylib.rb:3:1:33:3 | A | mylib | A | | | false | mylib.rb | |
5-
| lib/mylib.rb:4:3:5:5 | initialize | mylib | A! | new | (x,y) | false | mylib.rb | |
6-
| lib/mylib.rb:7:3:11:5 | foo | mylib | A | foo | (x,y,key1:) | false | mylib.rb | |
7-
| lib/mylib.rb:13:3:14:5 | bar | mylib | A | bar | (x) | false | mylib.rb | |
8-
| lib/mylib.rb:16:3:17:5 | self_foo | mylib | A! | self_foo | (x,y) | false | mylib.rb | |
9-
| lib/mylib.rb:24:3:32:5 | ANested | mylib | A::ANested | | | false | mylib.rb | |
10-
| lib/mylib.rb:25:5:26:7 | foo | mylib | A::ANested | foo | (x,y) | false | mylib.rb | |
4+
| lib/mylib.rb:3:1:34:3 | A | mylib | A | | | false | mylib.rb | |
5+
| lib/mylib.rb:4:3:6:5 | initialize | mylib | A! | new | (x,y) | false | mylib.rb | |
6+
| lib/mylib.rb:8:3:12:5 | foo | mylib | A | foo | (x,y,key1:) | false | mylib.rb | |
7+
| lib/mylib.rb:14:3:15:5 | bar | mylib | A | bar | (x) | false | mylib.rb | |
8+
| lib/mylib.rb:17:3:18:5 | self_foo | mylib | A! | self_foo | (x,y) | false | mylib.rb | |
9+
| lib/mylib.rb:25:3:33:5 | ANested | mylib | A::ANested | | | false | mylib.rb | |
10+
| lib/mylib.rb:26:5:27:7 | foo | mylib | A::ANested | foo | (x,y) | false | mylib.rb | |
1111
| lib/other.rb:3:1:8:3 | B | mylib | B | | | false | other.rb | |
1212
| lib/other.rb:6:3:7:5 | foo | mylib | B | foo | (x,y) | false | other.rb | |
1313
| lib/other.rb:10:1:12:3 | C | mylib | C | | | false | other.rb | |

ruby/ql/test/query-tests/utils/modeleditor/GenerateModel.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ typeVariableModel
44
typeModel
55
| M1 | B | |
66
summaryModel
7+
| A! | Method[new] | Argument[0] | ReturnValue | value |

ruby/ql/test/query-tests/utils/modeleditor/lib/mylib.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
class A
44
def initialize(x, y)
5+
@x = x
56
end
67

78
def foo(x, y, key1:, **kwargs, &block)

0 commit comments

Comments
 (0)