Skip to content

Commit a1036c8

Browse files
authored
Merge pull request github#15273 from hvitved/ruby/captured-yield
Ruby: Handle captured `yield` calls
2 parents 2f01688 + ad75562 commit a1036c8

File tree

14 files changed

+96
-11
lines changed

14 files changed

+96
-11
lines changed

cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,4 @@ uniqueContentApprox
166166
identityLocalStep
167167
missingArgumentCall
168168
multipleArgumentCall
169+
lambdaCallEnclosingCallableMismatch

cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ uniqueContentApprox
3131
identityLocalStep
3232
missingArgumentCall
3333
multipleArgumentCall
34+
lambdaCallEnclosingCallableMismatch

cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,4 @@ uniqueContentApprox
193193
identityLocalStep
194194
missingArgumentCall
195195
multipleArgumentCall
196+
lambdaCallEnclosingCallableMismatch

cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ uniqueContentApprox
2727
identityLocalStep
2828
missingArgumentCall
2929
multipleArgumentCall
30+
lambdaCallEnclosingCallableMismatch

cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,4 @@ uniqueContentApprox
9999
identityLocalStep
100100
missingArgumentCall
101101
multipleArgumentCall
102+
lambdaCallEnclosingCallableMismatch

cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ uniqueContentApprox
4242
identityLocalStep
4343
missingArgumentCall
4444
multipleArgumentCall
45+
lambdaCallEnclosingCallableMismatch

ruby/ql/consistency-queries/DataFlowConsistency.ql

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@ private module Input implements InputSig<RubyDataFlow> {
4343
arg.asExpr().getASuccessor(any(SuccessorTypes::ConditionalSuccessor c)).getASuccessor*() = n and
4444
n.getASplit() instanceof Split::ConditionalCompletionSplit
4545
)
46-
or
47-
// Synthetic block parameter nodes are passed directly as lambda-self reference
48-
// arguments to all `yield` calls
49-
arg instanceof ArgumentNodes::BlockParameterArgumentNode
5046
}
5147
}
5248

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,9 @@ private predicate moduleFlowsToMethodCallReceiver(RelevantCall call, Module m, s
208208
flowsToMethodCallReceiver(call, trackModuleAccess(m), method)
209209
}
210210

211-
private Block blockCall(RelevantCall call) { lambdaSourceCall(call, _, trackBlock(result)) }
211+
private Block blockCall(RelevantCall call) {
212+
lambdaSourceCall(call, _, trackBlock(result).(DataFlow::LocalSourceNode).getALocalUse())
213+
}
212214

213215
pragma[nomagic]
214216
private predicate superCall(RelevantCall call, Module cls, string method) {

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ module LocalFlow {
230230
or
231231
p.(KeywordParameter).getDefaultValue() = nodeFrom.asExpr().getExpr()
232232
)
233+
or
234+
nodeTo.(BlockArgumentNode).getParameterNode(true) = nodeFrom
233235
}
234236
}
235237

@@ -497,6 +499,9 @@ private module Cached {
497499
TSelfParameterNode(MethodBase m) or
498500
TLambdaSelfReferenceNode(Callable c) { lambdaCreationExpr(_, _, c) } or
499501
TBlockParameterNode(MethodBase m) or
502+
TBlockArgumentNode(CfgNodes::ExprNodes::CallCfgNode yield) {
503+
yield = any(BlockParameterNode b).getAYieldCall()
504+
} or
500505
TSynthHashSplatParameterNode(DataFlowCallable c) {
501506
isParameterNode(_, c, any(ParameterPosition p | p.isKeyword(_)))
502507
} or
@@ -645,6 +650,8 @@ private module Cached {
645650
isStoreTargetNode(n)
646651
or
647652
TypeTrackingInput::loadStep(_, n, _)
653+
or
654+
n instanceof BlockArgumentNode
648655
}
649656

650657
cached
@@ -770,6 +777,8 @@ predicate nodeIsHidden(Node n) {
770777
n instanceof LambdaSelfReferenceNode
771778
or
772779
n instanceof CaptureNode
780+
or
781+
n instanceof BlockArgumentNode
773782
}
774783

775784
/** An SSA definition, viewed as a node in a data flow graph. */
@@ -1277,18 +1286,36 @@ module ArgumentNodes {
12771286
}
12781287
}
12791288

1280-
class BlockParameterArgumentNode extends BlockParameterNode, ArgumentNode {
1281-
BlockParameterArgumentNode() { exists(this.getAYieldCall()) }
1289+
class BlockArgumentNode extends NodeImpl, ArgumentNode, TBlockArgumentNode {
1290+
CfgNodes::ExprNodes::CallCfgNode yield;
1291+
1292+
BlockArgumentNode() { this = TBlockArgumentNode(yield) }
1293+
1294+
CfgNodes::ExprNodes::CallCfgNode getYieldCall() { result = yield }
1295+
1296+
pragma[nomagic]
1297+
BlockParameterNode getParameterNode(boolean inSameScope) {
1298+
result.getAYieldCall() = yield and
1299+
if nodeGetEnclosingCallable(this) = nodeGetEnclosingCallable(result)
1300+
then inSameScope = true
1301+
else inSameScope = false
1302+
}
12821303

12831304
// needed for variable capture flow
12841305
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
1285-
call = this.getAYieldCall() and
1306+
call = yield and
12861307
pos.isLambdaSelf()
12871308
}
12881309

12891310
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
12901311
this.sourceArgumentOf(call.asCall(), pos)
12911312
}
1313+
1314+
override CfgScope getCfgScope() { result = yield.getScope() }
1315+
1316+
override Location getLocationImpl() { result = yield.getLocation() }
1317+
1318+
override string toStringImpl() { result = "yield block argument" }
12921319
}
12931320

12941321
private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
@@ -1699,6 +1726,8 @@ predicate jumpStep(Node pred, Node succ) {
16991726
succ.(FlowSummaryNode).getSummaryNode())
17001727
or
17011728
any(AdditionalJumpStep s).step(pred, succ)
1729+
or
1730+
succ.(BlockArgumentNode).getParameterNode(false) = pred
17021731
}
17031732

17041733
private ContentSet getArrayContent(int n) {
@@ -2037,7 +2066,7 @@ private predicate lambdaCallExpr(
20372066
*/
20382067
predicate lambdaSourceCall(CfgNodes::ExprNodes::CallCfgNode call, LambdaCallKind kind, Node receiver) {
20392068
kind = TYieldCallKind() and
2040-
call = receiver.(BlockParameterNode).getAYieldCall()
2069+
call = receiver.(BlockArgumentNode).getYieldCall()
20412070
or
20422071
kind = TLambdaCallKind() and
20432072
lambdaCallExpr(call, receiver.asExpr())

ruby/ql/test/library-tests/dataflow/call-sensitivity/call-sensitivity.expected

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,17 @@ edges
8181
| call_sensitivity.rb:178:11:178:19 | call to taint | call_sensitivity.rb:174:19:174:19 | x |
8282
| call_sensitivity.rb:187:11:187:20 | ( ... ) | call_sensitivity.rb:104:18:104:18 | x |
8383
| call_sensitivity.rb:187:12:187:19 | call to taint | call_sensitivity.rb:187:11:187:20 | ( ... ) |
84+
| call_sensitivity.rb:189:19:189:19 | x | call_sensitivity.rb:190:9:190:9 | x |
85+
| call_sensitivity.rb:190:9:190:9 | x | call_sensitivity.rb:194:23:194:23 | x |
86+
| call_sensitivity.rb:193:19:193:19 | x | call_sensitivity.rb:194:17:194:17 | x |
87+
| call_sensitivity.rb:194:17:194:17 | x | call_sensitivity.rb:189:19:189:19 | x |
88+
| call_sensitivity.rb:194:23:194:23 | x | call_sensitivity.rb:195:11:195:11 | x |
89+
| call_sensitivity.rb:195:11:195:11 | x | call_sensitivity.rb:199:30:199:30 | x |
90+
| call_sensitivity.rb:195:11:195:11 | x | call_sensitivity.rb:203:26:203:26 | x |
91+
| call_sensitivity.rb:199:15:199:24 | ( ... ) | call_sensitivity.rb:193:19:193:19 | x |
92+
| call_sensitivity.rb:199:16:199:23 | call to taint | call_sensitivity.rb:199:15:199:24 | ( ... ) |
93+
| call_sensitivity.rb:199:30:199:30 | x | call_sensitivity.rb:200:8:200:8 | x |
94+
| call_sensitivity.rb:203:26:203:26 | x | call_sensitivity.rb:204:8:204:8 | x |
8495
nodes
8596
| call_sensitivity.rb:9:6:9:14 | ( ... ) | semmle.label | ( ... ) |
8697
| call_sensitivity.rb:9:7:9:13 | call to taint | semmle.label | call to taint |
@@ -168,6 +179,18 @@ nodes
168179
| call_sensitivity.rb:178:11:178:19 | call to taint | semmle.label | call to taint |
169180
| call_sensitivity.rb:187:11:187:20 | ( ... ) | semmle.label | ( ... ) |
170181
| call_sensitivity.rb:187:12:187:19 | call to taint | semmle.label | call to taint |
182+
| call_sensitivity.rb:189:19:189:19 | x | semmle.label | x |
183+
| call_sensitivity.rb:190:9:190:9 | x | semmle.label | x |
184+
| call_sensitivity.rb:193:19:193:19 | x | semmle.label | x |
185+
| call_sensitivity.rb:194:17:194:17 | x | semmle.label | x |
186+
| call_sensitivity.rb:194:23:194:23 | x | semmle.label | x |
187+
| call_sensitivity.rb:195:11:195:11 | x | semmle.label | x |
188+
| call_sensitivity.rb:199:15:199:24 | ( ... ) | semmle.label | ( ... ) |
189+
| call_sensitivity.rb:199:16:199:23 | call to taint | semmle.label | call to taint |
190+
| call_sensitivity.rb:199:30:199:30 | x | semmle.label | x |
191+
| call_sensitivity.rb:200:8:200:8 | x | semmle.label | x |
192+
| call_sensitivity.rb:203:26:203:26 | x | semmle.label | x |
193+
| call_sensitivity.rb:204:8:204:8 | x | semmle.label | x |
171194
subpaths
172195
#select
173196
| call_sensitivity.rb:9:6:9:14 | ( ... ) | call_sensitivity.rb:9:7:9:13 | call to taint | call_sensitivity.rb:9:6:9:14 | ( ... ) | $@ | call_sensitivity.rb:9:7:9:13 | call to taint | call to taint |
@@ -193,6 +216,8 @@ subpaths
193216
| call_sensitivity.rb:105:10:105:10 | x | call_sensitivity.rb:125:12:125:19 | call to taint | call_sensitivity.rb:105:10:105:10 | x | $@ | call_sensitivity.rb:125:12:125:19 | call to taint | call to taint |
194217
| call_sensitivity.rb:105:10:105:10 | x | call_sensitivity.rb:178:11:178:19 | call to taint | call_sensitivity.rb:105:10:105:10 | x | $@ | call_sensitivity.rb:178:11:178:19 | call to taint | call to taint |
195218
| call_sensitivity.rb:105:10:105:10 | x | call_sensitivity.rb:187:12:187:19 | call to taint | call_sensitivity.rb:105:10:105:10 | x | $@ | call_sensitivity.rb:187:12:187:19 | call to taint | call to taint |
219+
| call_sensitivity.rb:200:8:200:8 | x | call_sensitivity.rb:199:16:199:23 | call to taint | call_sensitivity.rb:200:8:200:8 | x | $@ | call_sensitivity.rb:199:16:199:23 | call to taint | call to taint |
220+
| call_sensitivity.rb:204:8:204:8 | x | call_sensitivity.rb:199:16:199:23 | call to taint | call_sensitivity.rb:204:8:204:8 | x | $@ | call_sensitivity.rb:199:16:199:23 | call to taint | call to taint |
196221
mayBenefitFromCallContext
197222
| call_sensitivity.rb:51:5:51:10 | call to sink |
198223
| call_sensitivity.rb:55:5:55:13 | call to method1 |
@@ -212,6 +237,7 @@ mayBenefitFromCallContext
212237
| call_sensitivity.rb:149:5:149:28 | call to singleton_method2 |
213238
| call_sensitivity.rb:153:5:153:35 | call to singleton_method3 |
214239
| call_sensitivity.rb:175:3:175:12 | call to new |
240+
| call_sensitivity.rb:194:3:196:5 | call to invoke_block1 |
215241
viableImplInCallContext
216242
| call_sensitivity.rb:51:5:51:10 | call to sink | call_sensitivity.rb:55:5:55:13 | call to method1 | call_sensitivity.rb:5:1:7:3 | sink |
217243
| call_sensitivity.rb:51:5:51:10 | call to sink | call_sensitivity.rb:63:5:63:16 | call to method1 | call_sensitivity.rb:5:1:7:3 | sink |
@@ -267,3 +293,5 @@ viableImplInCallContext
267293
| call_sensitivity.rb:153:5:153:35 | call to singleton_method3 | call_sensitivity.rb:171:1:171:34 | call to call_singleton_method3 | call_sensitivity.rb:96:3:98:5 | singleton_method3 |
268294
| call_sensitivity.rb:175:3:175:12 | call to new | call_sensitivity.rb:178:1:178:20 | call to create | call_sensitivity.rb:104:3:107:5 | initialize |
269295
| call_sensitivity.rb:175:3:175:12 | call to new | call_sensitivity.rb:179:1:179:20 | call to create | call_sensitivity.rb:156:3:158:5 | initialize |
296+
| call_sensitivity.rb:194:3:196:5 | call to invoke_block1 | call_sensitivity.rb:199:1:201:3 | call to invoke_block2 | call_sensitivity.rb:189:1:191:3 | invoke_block1 |
297+
| call_sensitivity.rb:194:3:196:5 | call to invoke_block1 | call_sensitivity.rb:203:1:205:3 | call to invoke_block2 | call_sensitivity.rb:189:1:191:3 | invoke_block1 |

0 commit comments

Comments
 (0)