Skip to content

Commit 8195ebf

Browse files
authored
Merge pull request #7059 from hvitved/ruby/basic-store-step-postupdate
Ruby: Fix `basicStoreStep`
2 parents 40e47c0 + 3544c85 commit 8195ebf

File tree

4 files changed

+170
-2
lines changed

4 files changed

+170
-2
lines changed

ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ predicate returnStep(Node nodeFrom, Node nodeTo) {
9999
* to `z` inside `bar`, even though this content write happens _after_ `bar` is
100100
* called.
101101
*/
102-
predicate basicStoreStep(Node nodeFrom, DataFlowPublic::LocalSourceNode nodeTo, string content) {
102+
predicate basicStoreStep(Node nodeFrom, Node nodeTo, string content) {
103103
// TODO: support SetterMethodCall inside TuplePattern
104104
exists(ExprNodes::MethodCallCfgNode call |
105105
content = getSetterCallAttributeName(call.getExpr()) and
106-
nodeTo.(DataFlowPublic::ExprNode).getExprNode() = call.getReceiver() and
106+
nodeTo.(DataFlowPrivate::PostUpdateNode).getPreUpdateNode().asExpr() = call.getReceiver() and
107107
call.getExpr() instanceof AST::SetterMethodCall and
108108
call.getArgument(call.getNumberOfArguments() - 1) =
109109
nodeFrom.(DataFlowPublic::ExprNode).getExprNode()
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
track
2+
| type_tracker.rb:2:5:5:7 | &block | type tracker without call steps | type_tracker.rb:2:5:5:7 | &block |
3+
| type_tracker.rb:2:5:5:7 | field= | type tracker without call steps | type_tracker.rb:2:5:5:7 | field= |
4+
| type_tracker.rb:2:5:5:7 | return return in field= | type tracker without call steps | type_tracker.rb:2:5:5:7 | return return in field= |
5+
| type_tracker.rb:2:5:5:7 | return return in field= | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
6+
| type_tracker.rb:2:5:5:7 | self (field=) | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
7+
| type_tracker.rb:2:5:5:7 | self (field=) | type tracker without call steps | type_tracker.rb:2:5:5:7 | self (field=) |
8+
| type_tracker.rb:2:5:5:7 | self in field= | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
9+
| type_tracker.rb:2:5:5:7 | self in field= | type tracker without call steps | type_tracker.rb:2:5:5:7 | self in field= |
10+
| type_tracker.rb:2:16:2:18 | val | type tracker with call steps | type_tracker.rb:2:16:2:18 | val |
11+
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:2:5:5:7 | return return in field= |
12+
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:2:16:2:18 | val |
13+
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:2:16:2:18 | val |
14+
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:2:16:2:18 | val |
15+
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
16+
| type_tracker.rb:3:9:3:23 | [post] self | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
17+
| type_tracker.rb:3:9:3:23 | [post] self | type tracker without call steps | type_tracker.rb:3:9:3:23 | [post] self |
18+
| type_tracker.rb:3:9:3:23 | call to puts | type tracker without call steps | type_tracker.rb:3:9:3:23 | call to puts |
19+
| type_tracker.rb:3:9:3:23 | self | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
20+
| type_tracker.rb:3:9:3:23 | self | type tracker without call steps | type_tracker.rb:3:9:3:23 | self |
21+
| type_tracker.rb:3:14:3:17 | [post] self | type tracker without call steps | type_tracker.rb:3:14:3:17 | [post] self |
22+
| type_tracker.rb:3:14:3:17 | self | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
23+
| type_tracker.rb:3:14:3:17 | self | type tracker without call steps | type_tracker.rb:3:14:3:17 | self |
24+
| type_tracker.rb:3:14:3:23 | [post] call to field | type tracker without call steps | type_tracker.rb:3:14:3:23 | [post] call to field |
25+
| type_tracker.rb:3:14:3:23 | call to field | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
26+
| type_tracker.rb:4:9:4:14 | @field | type tracker without call steps | type_tracker.rb:4:9:4:14 | @field |
27+
| type_tracker.rb:4:18:4:20 | val | type tracker without call steps | type_tracker.rb:2:5:5:7 | return return in field= |
28+
| type_tracker.rb:4:18:4:20 | val | type tracker without call steps | type_tracker.rb:4:18:4:20 | val |
29+
| type_tracker.rb:4:18:4:20 | val | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
30+
| type_tracker.rb:7:5:9:7 | &block | type tracker without call steps | type_tracker.rb:7:5:9:7 | &block |
31+
| type_tracker.rb:7:5:9:7 | field | type tracker without call steps | type_tracker.rb:7:5:9:7 | field |
32+
| type_tracker.rb:7:5:9:7 | return return in field | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
33+
| type_tracker.rb:7:5:9:7 | return return in field | type tracker without call steps | type_tracker.rb:7:5:9:7 | return return in field |
34+
| type_tracker.rb:7:5:9:7 | return return in field | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
35+
| type_tracker.rb:7:5:9:7 | self in field | type tracker without call steps | type_tracker.rb:7:5:9:7 | self in field |
36+
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
37+
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:7:5:9:7 | return return in field |
38+
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:8:9:8:14 | @field |
39+
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
40+
| type_tracker.rb:12:1:16:3 | &block | type tracker without call steps | type_tracker.rb:12:1:16:3 | &block |
41+
| type_tracker.rb:12:1:16:3 | m | type tracker without call steps | type_tracker.rb:12:1:16:3 | m |
42+
| type_tracker.rb:12:1:16:3 | return return in m | type tracker without call steps | type_tracker.rb:12:1:16:3 | return return in m |
43+
| type_tracker.rb:12:1:16:3 | self (m) | type tracker without call steps | type_tracker.rb:12:1:16:3 | self (m) |
44+
| type_tracker.rb:12:1:16:3 | self in m | type tracker without call steps | type_tracker.rb:12:1:16:3 | self in m |
45+
| type_tracker.rb:13:5:13:7 | var | type tracker without call steps | type_tracker.rb:13:5:13:7 | var |
46+
| type_tracker.rb:13:11:13:19 | Container | type tracker without call steps | type_tracker.rb:13:11:13:19 | Container |
47+
| type_tracker.rb:13:11:13:19 | [post] Container | type tracker without call steps | type_tracker.rb:13:11:13:19 | [post] Container |
48+
| type_tracker.rb:13:11:13:23 | call to new | type tracker with call steps | type_tracker.rb:2:5:5:7 | self in field= |
49+
| type_tracker.rb:13:11:13:23 | call to new | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
50+
| type_tracker.rb:13:11:13:23 | call to new | type tracker without call steps | type_tracker.rb:13:11:13:23 | call to new |
51+
| type_tracker.rb:14:5:14:7 | [post] var | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
52+
| type_tracker.rb:14:5:14:7 | [post] var | type tracker without call steps | type_tracker.rb:14:5:14:7 | [post] var |
53+
| type_tracker.rb:14:5:14:13 | [post] ... = ... | type tracker without call steps | type_tracker.rb:14:5:14:13 | [post] ... = ... |
54+
| type_tracker.rb:14:5:14:13 | __synth__0 | type tracker without call steps | type_tracker.rb:14:5:14:13 | __synth__0 |
55+
| type_tracker.rb:14:5:14:13 | call to field= | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
56+
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps | type_tracker.rb:2:16:2:18 | val |
57+
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps | type_tracker.rb:2:16:2:18 | val |
58+
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps with content field | type_tracker.rb:7:5:9:7 | self in field |
59+
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:14:17:14:23 | "hello" |
60+
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
61+
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps with content field | type_tracker.rb:14:5:14:7 | [post] var |
62+
| type_tracker.rb:15:5:15:18 | [post] self | type tracker without call steps | type_tracker.rb:15:5:15:18 | [post] self |
63+
| type_tracker.rb:15:5:15:18 | call to puts | type tracker without call steps | type_tracker.rb:12:1:16:3 | return return in m |
64+
| type_tracker.rb:15:5:15:18 | call to puts | type tracker without call steps | type_tracker.rb:15:5:15:18 | call to puts |
65+
| type_tracker.rb:15:5:15:18 | self | type tracker without call steps | type_tracker.rb:15:5:15:18 | self |
66+
| type_tracker.rb:15:10:15:12 | [post] var | type tracker without call steps | type_tracker.rb:15:10:15:12 | [post] var |
67+
| type_tracker.rb:15:10:15:18 | [post] call to field | type tracker without call steps | type_tracker.rb:15:10:15:18 | [post] call to field |
68+
| type_tracker.rb:15:10:15:18 | call to field | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
69+
trackEnd
70+
| type_tracker.rb:2:5:5:7 | &block | type_tracker.rb:2:5:5:7 | &block |
71+
| type_tracker.rb:2:5:5:7 | field= | type_tracker.rb:2:5:5:7 | field= |
72+
| type_tracker.rb:2:5:5:7 | return return in field= | type_tracker.rb:2:5:5:7 | return return in field= |
73+
| type_tracker.rb:2:5:5:7 | return return in field= | type_tracker.rb:14:5:14:13 | call to field= |
74+
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:2:5:5:7 | self (field=) |
75+
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:7:5:9:7 | self in field |
76+
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:2:5:5:7 | self in field= |
77+
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:7:5:9:7 | self in field |
78+
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:5:5:7 | return return in field= |
79+
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
80+
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
81+
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
82+
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
83+
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:14:5:14:13 | call to field= |
84+
| type_tracker.rb:3:9:3:23 | [post] self | type_tracker.rb:3:9:3:23 | [post] self |
85+
| type_tracker.rb:3:9:3:23 | [post] self | type_tracker.rb:7:5:9:7 | self in field |
86+
| type_tracker.rb:3:9:3:23 | call to puts | type_tracker.rb:3:9:3:23 | call to puts |
87+
| type_tracker.rb:3:9:3:23 | self | type_tracker.rb:3:9:3:23 | self |
88+
| type_tracker.rb:3:9:3:23 | self | type_tracker.rb:7:5:9:7 | self in field |
89+
| type_tracker.rb:3:14:3:17 | [post] self | type_tracker.rb:3:14:3:17 | [post] self |
90+
| type_tracker.rb:3:14:3:17 | self | type_tracker.rb:3:14:3:17 | self |
91+
| type_tracker.rb:3:14:3:17 | self | type_tracker.rb:7:5:9:7 | self in field |
92+
| type_tracker.rb:3:14:3:23 | [post] call to field | type_tracker.rb:3:14:3:23 | [post] call to field |
93+
| type_tracker.rb:3:14:3:23 | call to field | type_tracker.rb:3:14:3:23 | call to field |
94+
| type_tracker.rb:4:9:4:14 | @field | type_tracker.rb:4:9:4:14 | @field |
95+
| type_tracker.rb:4:18:4:20 | val | type_tracker.rb:2:5:5:7 | return return in field= |
96+
| type_tracker.rb:4:18:4:20 | val | type_tracker.rb:4:18:4:20 | val |
97+
| type_tracker.rb:4:18:4:20 | val | type_tracker.rb:14:5:14:13 | call to field= |
98+
| type_tracker.rb:7:5:9:7 | &block | type_tracker.rb:7:5:9:7 | &block |
99+
| type_tracker.rb:7:5:9:7 | field | type_tracker.rb:7:5:9:7 | field |
100+
| type_tracker.rb:7:5:9:7 | return return in field | type_tracker.rb:3:14:3:23 | call to field |
101+
| type_tracker.rb:7:5:9:7 | return return in field | type_tracker.rb:7:5:9:7 | return return in field |
102+
| type_tracker.rb:7:5:9:7 | return return in field | type_tracker.rb:15:10:15:18 | call to field |
103+
| type_tracker.rb:7:5:9:7 | self in field | type_tracker.rb:7:5:9:7 | self in field |
104+
| type_tracker.rb:8:9:8:14 | @field | type_tracker.rb:3:14:3:23 | call to field |
105+
| type_tracker.rb:8:9:8:14 | @field | type_tracker.rb:7:5:9:7 | return return in field |
106+
| type_tracker.rb:8:9:8:14 | @field | type_tracker.rb:8:9:8:14 | @field |
107+
| type_tracker.rb:8:9:8:14 | @field | type_tracker.rb:15:10:15:18 | call to field |
108+
| type_tracker.rb:12:1:16:3 | &block | type_tracker.rb:12:1:16:3 | &block |
109+
| type_tracker.rb:12:1:16:3 | m | type_tracker.rb:12:1:16:3 | m |
110+
| type_tracker.rb:12:1:16:3 | return return in m | type_tracker.rb:12:1:16:3 | return return in m |
111+
| type_tracker.rb:12:1:16:3 | self (m) | type_tracker.rb:12:1:16:3 | self (m) |
112+
| type_tracker.rb:12:1:16:3 | self in m | type_tracker.rb:12:1:16:3 | self in m |
113+
| type_tracker.rb:13:5:13:7 | var | type_tracker.rb:13:5:13:7 | var |
114+
| type_tracker.rb:13:11:13:19 | Container | type_tracker.rb:13:11:13:19 | Container |
115+
| type_tracker.rb:13:11:13:19 | [post] Container | type_tracker.rb:13:11:13:19 | [post] Container |
116+
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:2:5:5:7 | self in field= |
117+
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:7:5:9:7 | self in field |
118+
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:13:11:13:23 | call to new |
119+
| type_tracker.rb:14:5:14:7 | [post] var | type_tracker.rb:7:5:9:7 | self in field |
120+
| type_tracker.rb:14:5:14:7 | [post] var | type_tracker.rb:14:5:14:7 | [post] var |
121+
| type_tracker.rb:14:5:14:13 | [post] ... = ... | type_tracker.rb:14:5:14:13 | [post] ... = ... |
122+
| type_tracker.rb:14:5:14:13 | __synth__0 | type_tracker.rb:14:5:14:13 | __synth__0 |
123+
| type_tracker.rb:14:5:14:13 | call to field= | type_tracker.rb:14:5:14:13 | call to field= |
124+
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:2:16:2:18 | val |
125+
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:2:16:2:18 | val |
126+
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:17:14:23 | "hello" |
127+
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:15:10:15:18 | call to field |
128+
| type_tracker.rb:15:5:15:18 | [post] self | type_tracker.rb:15:5:15:18 | [post] self |
129+
| type_tracker.rb:15:5:15:18 | call to puts | type_tracker.rb:12:1:16:3 | return return in m |
130+
| type_tracker.rb:15:5:15:18 | call to puts | type_tracker.rb:15:5:15:18 | call to puts |
131+
| type_tracker.rb:15:5:15:18 | self | type_tracker.rb:15:5:15:18 | self |
132+
| type_tracker.rb:15:10:15:12 | [post] var | type_tracker.rb:15:10:15:12 | [post] var |
133+
| type_tracker.rb:15:10:15:18 | [post] call to field | type_tracker.rb:15:10:15:18 | [post] call to field |
134+
| type_tracker.rb:15:10:15:18 | call to field | type_tracker.rb:15:10:15:18 | call to field |
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import ruby
2+
import codeql.ruby.DataFlow
3+
import codeql.ruby.typetracking.TypeTracker
4+
5+
class LocalSourceNode extends DataFlow::LocalSourceNode {
6+
LocalSourceNode() { this.getLocation().getFile().getExtension() = "rb" }
7+
}
8+
9+
query predicate track(LocalSourceNode src, TypeTracker t, LocalSourceNode dst) {
10+
t.start() and
11+
dst = src
12+
or
13+
exists(TypeTracker t2, LocalSourceNode mid | track(src, t2, mid) and dst = mid.track(t2, t))
14+
}
15+
16+
query predicate trackEnd(LocalSourceNode src, LocalSourceNode dst) {
17+
track(src, TypeTracker::end(), dst)
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Container
2+
def field=(val)
3+
puts self.field
4+
@field = val
5+
end
6+
7+
def field
8+
@field
9+
end
10+
end
11+
12+
def m()
13+
var = Container.new
14+
var.field = "hello"
15+
puts var.field
16+
end

0 commit comments

Comments
 (0)