Skip to content

Commit f8b9929

Browse files
committed
Improve desugaring of setter assignments
1 parent abcabee commit f8b9929

4 files changed

Lines changed: 99 additions & 33 deletions

File tree

ql/src/codeql_ruby/ast/internal/Synthesis.qll

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -154,39 +154,73 @@ private module SetterDesugar {
154154
* desugars to
155155
*
156156
* ```rb
157-
* x.foo=(y)
157+
* x.foo=(__synth_0 = y);
158+
* __synth_0;
158159
* ```
159160
*/
160161
private class SetterMethodCallSynthesis extends Synthesis {
161162
final override predicate child(AstNode parent, int i, Child child, LocationOption l) {
162163
exists(AssignExpr ae, MethodCall mc | mc = ae.getLeftOperand() |
163164
parent = ae and
164165
i = -1 and
165-
child = SynthChild(getCallKind(mc)) and
166-
l = getSomeLocation(mc)
166+
child = SynthChild(StmtSequenceKind()) and
167+
l = NoneLocation()
167168
or
168-
parent = getSynthChild(ae, -1) and
169-
l = NoneLocation() and
170-
(
169+
exists(AstNode seq | seq = getSynthChild(ae, -1) |
170+
parent = seq and
171171
i = 0 and
172-
child = RealChild(mc.getReceiver())
173-
or
174-
child = RealChild(mc.getArgument(i - 1))
172+
child = SynthChild(getCallKind(mc)) and
173+
l = getSomeLocation(mc)
175174
or
176-
i = mc.getNumberOfArguments() + 1 and
177-
child = RealChild(ae.getRightOperand())
175+
exists(AstNode call | call = getSynthChild(seq, 0) |
176+
parent = call and
177+
i = 0 and
178+
child = RealChild(mc.getReceiver()) and
179+
l = NoneLocation()
180+
or
181+
parent = call and
182+
child = RealChild(mc.getArgument(i - 1)) and
183+
l = NoneLocation()
184+
or
185+
l = getSomeLocation(mc) and
186+
exists(int valueIndex | valueIndex = mc.getNumberOfArguments() + 1 |
187+
parent = call and
188+
i = valueIndex and
189+
child = SynthChild(AssignExprKind())
190+
or
191+
parent = getSynthChild(call, valueIndex) and
192+
(
193+
i = 0 and
194+
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(ae, 0)))
195+
or
196+
i = 1 and
197+
child = RealChild(ae.getRightOperand())
198+
)
199+
)
200+
or
201+
parent = call and
202+
// special "number of arguments argument"; required to avoid non-monotonic recursion
203+
i = -2 and
204+
child = SynthChild(IntegerLiteralKind(mc.getNumberOfArguments() + 1)) and
205+
l = NoneLocation()
206+
)
178207
or
179-
// special "number of arguments argument"; required to avoid non-monotonic recursion
180-
i = -2 and
181-
child = SynthChild(IntegerLiteralKind(mc.getNumberOfArguments() + 1)) and
182-
l = NoneLocation()
208+
parent = seq and
209+
i = 1 and
210+
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(ae, 0))) and
211+
l = getSomeLocation(mc)
183212
)
184213
)
185214
}
186215

187216
final override predicate excludeFromControlFlowTree(AstNode n) {
188217
n.(MethodCall) = any(AssignExpr ae).getLeftOperand()
189218
}
219+
220+
final override predicate localVariable(AstNode n, int i) {
221+
n.(AssignExpr).getLeftOperand() instanceof MethodCall and
222+
i = 0
223+
}
190224
}
191225
}
192226

ql/test/library-tests/ast/AstDesugar.expected

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,24 @@ calls/calls.rb:
1111
# 67| getAnOperand/getLeftOperand: [LocalVariableAccess] var1
1212
# 67| getAnOperand/getRightOperand: [MethodCall] call to bar
1313
# 67| getReceiver: [ConstantReadAccess] X
14-
# 314| [SetterMethodCall] call to foo=
15-
# 314| getReceiver: [Self] self
16-
# 314| getNumberOfArguments: [IntegerLiteral] 1
17-
# 314| getArgument: [IntegerLiteral] 10
18-
# 315| [ElementReference, SetterMethodCall] ...[...]
19-
# 315| getReceiver: [MethodCall] call to foo
20-
# 315| getReceiver: [Self] self
21-
# 315| getNumberOfArguments: [IntegerLiteral] 2
22-
# 315| getArgument: [IntegerLiteral] 0
23-
# 315| getArgument: [IntegerLiteral] 10
14+
# 314| [StmtSequence] ...
15+
# 314| getStmt: [SetterMethodCall] call to foo=
16+
# 314| getReceiver: [Self] self
17+
# 314| getNumberOfArguments: [IntegerLiteral] 1
18+
# 314| getArgument: [AssignExpr] ... = ...
19+
# 314| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
20+
# 314| getAnOperand/getRightOperand: [IntegerLiteral] 10
21+
# 314| getStmt: [LocalVariableAccess] __synth__0
22+
# 315| [StmtSequence] ...
23+
# 315| getStmt: [ElementReference, SetterMethodCall] ...[...]
24+
# 315| getReceiver: [MethodCall] call to foo
25+
# 315| getReceiver: [Self] self
26+
# 315| getNumberOfArguments: [IntegerLiteral] 2
27+
# 315| getArgument: [AssignExpr] ... = ...
28+
# 315| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
29+
# 315| getAnOperand/getRightOperand: [IntegerLiteral] 10
30+
# 315| getArgument: [IntegerLiteral] 0
31+
# 315| getStmt: [LocalVariableAccess] __synth__0
2432
# 318| [StmtSequence] ...
2533
# 318| getStmt: [SetterMethodCall] call to count=
2634
# 318| getNumberOfArguments: [IntegerLiteral] 2

ql/test/library-tests/ast/calls/calls.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ callsWithArguments
3131
| calls.rb:293:5:293:33 | call to super | super | 0 | calls.rb:293:11:293:11 | 6 |
3232
| calls.rb:293:5:293:33 | call to super | super | 1 | calls.rb:293:14:293:14 | 7 |
3333
| calls.rb:311:1:311:7 | call to call | call | 0 | calls.rb:311:6:311:6 | 1 |
34-
| calls.rb:314:1:314:8 | call to foo= | foo= | 0 | calls.rb:314:12:314:13 | 10 |
34+
| calls.rb:314:1:314:8 | call to foo= | foo= | 0 | calls.rb:314:1:314:8 | ... = ... |
3535
| calls.rb:315:1:315:6 | ...[...] | []= | 0 | calls.rb:315:5:315:5 | 0 |
3636
| calls.rb:315:1:315:6 | ...[...] | []= | 0 | calls.rb:315:5:315:5 | 0 |
37-
| calls.rb:315:1:315:6 | ...[...] | []= | 1 | calls.rb:315:10:315:11 | 10 |
37+
| calls.rb:315:1:315:6 | ...[...] | []= | 1 | calls.rb:315:1:315:6 | ... = ... |
3838
| calls.rb:316:22:316:27 | ...[...] | []= | 0 | calls.rb:316:26:316:26 | 4 |
3939
| calls.rb:317:5:317:10 | ...[...] | []= | 0 | calls.rb:317:9:317:9 | 5 |
4040
| calls.rb:318:1:318:10 | call to count= | count= | 1 | calls.rb:318:12:318:13 | __synth__1 |

ql/test/library-tests/controlflow/graph/Cfg.expected

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,17 +2127,29 @@ desugar.rb:
21272127
#-----| -> x
21282128

21292129
# 6| call to foo
2130-
#-----| -> 1
2130+
#-----| -> __synth__0
21312131

21322132
# 6| x
21332133
#-----| -> call to foo
21342134

2135-
# 6| call to count=
2135+
# 6| ...
21362136
#-----| -> exit m2 (normal)
21372137

2138-
# 6| 1
2138+
# 6| call to count=
2139+
#-----| -> __synth__0
2140+
2141+
# 6| __synth__0
2142+
#-----| -> ...
2143+
2144+
# 6| ... = ...
21392145
#-----| -> call to count=
21402146

2147+
# 6| __synth__0
2148+
#-----| -> 1
2149+
2150+
# 6| 1
2151+
#-----| -> ... = ...
2152+
21412153
# 9| enter m3
21422154
#-----| -> x
21432155

@@ -2158,14 +2170,26 @@ desugar.rb:
21582170
# 10| x
21592171
#-----| -> call to foo
21602172

2161-
# 10| ...[...]
2173+
# 10| ...
21622174
#-----| -> exit m3 (normal)
21632175

2164-
# 10| 0
2176+
# 10| ...[...]
2177+
#-----| -> __synth__0
2178+
2179+
# 10| __synth__0
2180+
#-----| -> ...
2181+
2182+
# 10| ... = ...
2183+
#-----| -> ...[...]
2184+
2185+
# 10| __synth__0
21652186
#-----| -> 1
21662187

2188+
# 10| 0
2189+
#-----| -> __synth__0
2190+
21672191
# 10| 1
2168-
#-----| -> ...[...]
2192+
#-----| -> ... = ...
21692193

21702194
# 13| enter m4
21712195
#-----| -> x

0 commit comments

Comments
 (0)