Skip to content

Commit 30c8417

Browse files
committed
temp
1 parent 7e42f39 commit 30c8417

File tree

15 files changed

+344
-169
lines changed

15 files changed

+344
-169
lines changed

ruby/ql/lib/codeql/ruby/dataflow/SSA.qll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ module Ssa {
178178

179179
/** Gets the location of this SSA definition. */
180180
Location getLocation() { result = this.getControlFlowNode().getLocation() }
181+
182+
/** Gets the scope of this SSA definition. */
183+
CfgScope getScope() { result = this.getBasicBlock().getScope() }
181184
}
182185

183186
/**
@@ -289,7 +292,7 @@ module Ssa {
289292
)
290293
}
291294

292-
final override string toString() { result = "<captured> " + this.getSourceVariable() }
295+
final override string toString() { result = "<captured entry> " + this.getSourceVariable() }
293296

294297
override Location getLocation() { result = this.getBasicBlock().getLocation() }
295298
}
@@ -324,7 +327,7 @@ module Ssa {
324327
*/
325328
final Definition getPriorDefinition() { result = SsaImpl::uncertainWriteDefinitionInput(this) }
326329

327-
override string toString() { result = this.getControlFlowNode().toString() }
330+
override string toString() { result = "<captured exit> " + this.getSourceVariable() }
328331
}
329332

330333
/**

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

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@ private import FlowSummaryImpl as FlowSummaryImpl
88
private import FlowSummaryImplSpecific as FlowSummaryImplSpecific
99
private import codeql.ruby.dataflow.FlowSummary
1010
private import codeql.ruby.dataflow.SSA
11+
private import codeql.ruby.dataflow.internal.SsaImpl as SsaImpl
1112

1213
newtype TReturnKind =
1314
TNormalReturnKind() or
14-
TBreakReturnKind()
15+
TBreakReturnKind() or
16+
TCapturedReturnKind(LocalVariable v) {
17+
exists(Ssa::Definition def |
18+
SsaImpl::captureFlowOut(_, def, _) and
19+
v = def.getSourceVariable()
20+
)
21+
}
1522

1623
/**
1724
* Gets a node that can read the value returned from `call` with return kind
@@ -43,6 +50,19 @@ class BreakReturnKind extends ReturnKind, TBreakReturnKind {
4350
override string toString() { result = "break" }
4451
}
4552

53+
/**
54+
* A value implicitly returned from a capturing callable.
55+
*/
56+
class CapturedReturnKind extends ReturnKind, TCapturedReturnKind {
57+
LocalVariable v;
58+
59+
CapturedReturnKind() { this = TCapturedReturnKind(v) }
60+
61+
LocalVariable getVariable() { result = v }
62+
63+
override string toString() { result = "captured write to " + v }
64+
}
65+
4666
/** A callable defined in library code, identified by a unique string. */
4767
abstract class LibraryCallable extends string {
4868
bindingset[this]
@@ -151,6 +171,28 @@ private class NormalCall extends DataFlowCall, TNormalCall {
151171
override Location getLocation() { result = c.getLocation() }
152172
}
153173

174+
class CapturedCall extends DataFlowCall, TCapturedCall {
175+
private CfgNodes::ExprNodes::CallCfgNode c;
176+
177+
CapturedCall() { this = TCapturedCall(c) }
178+
179+
Callable getTarget() {
180+
exists(Ssa::Definition def | result = def.getScope() |
181+
SsaImpl::captureFlowIn(c, _, _, _, def)
182+
or
183+
SsaImpl::captureFlowOut(c, def, _)
184+
)
185+
}
186+
187+
override CfgNodes::ExprNodes::CallCfgNode asCall() { none() }
188+
189+
override DataFlowCallable getEnclosingCallable() { result = TCfgScope(c.getScope()) }
190+
191+
override string toString() { result = "<captured> " + c.toString() }
192+
193+
override Location getLocation() { result = c.getLocation() }
194+
}
195+
154196
/** A call for which we want to compute call targets. */
155197
private class RelevantCall extends CfgNodes::ExprNodes::CallCfgNode {
156198
pragma[nomagic]
@@ -341,6 +383,11 @@ private module Cached {
341383
TNormalCall(CfgNodes::ExprNodes::CallCfgNode c) or
342384
TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, DataFlow::Node receiver) {
343385
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
386+
} or
387+
TCapturedCall(CfgNodes::ExprNodes::CallCfgNode c) {
388+
SsaImpl::captureFlowIn(c, _, _, _, _)
389+
or
390+
SsaImpl::captureFlowOut(c, _, _)
344391
}
345392

346393
pragma[nomagic]
@@ -478,6 +525,8 @@ private module Cached {
478525
result = viableSourceCallable(call)
479526
or
480527
result = viableLibraryCallable(call)
528+
or
529+
result.asCallable() = call.(CapturedCall).getTarget()
481530
}
482531

483532
cached
@@ -499,7 +548,8 @@ private module Cached {
499548
THashSplatArgumentPosition() or
500549
TSplatAllArgumentPosition() or
501550
TAnyArgumentPosition() or
502-
TAnyKeywordArgumentPosition()
551+
TAnyKeywordArgumentPosition() or
552+
TCapturedArgumentPosition(LocalVariable v)
503553

504554
cached
505555
newtype TParameterPosition =
@@ -521,7 +571,8 @@ private module Cached {
521571
THashSplatParameterPosition() or
522572
TSplatAllParameterPosition() or
523573
TAnyParameterPosition() or
524-
TAnyKeywordParameterPosition()
574+
TAnyKeywordParameterPosition() or
575+
TCapturedParameterPosition(LocalVariable v)
525576
}
526577

527578
import Cached
@@ -921,7 +972,7 @@ private predicate paramReturnFlow(
921972
DataFlow::Node nodeFrom, DataFlow::PostUpdateNode nodeTo, StepSummary summary
922973
) {
923974
exists(RelevantCall call, DataFlow::Node arg, DataFlow::ParameterNode p, Expr nodeFromPreExpr |
924-
TypeTrackerSpecific::callStep(call, arg, p) and
975+
TypeTrackerSpecific::callStep(TNormalCall(call), arg, p) and
925976
nodeTo.getPreUpdateNode() = arg and
926977
summary.toString() = "return" and
927978
(
@@ -1151,6 +1202,8 @@ class ParameterPosition extends TParameterPosition {
11511202
/** Holds if this position represents any positional parameter. */
11521203
predicate isAnyNamed() { this = TAnyKeywordParameterPosition() }
11531204

1205+
predicate isCapturedVariable(LocalVariable v) { this = TCapturedParameterPosition(v) }
1206+
11541207
/** Gets a textual representation of this position. */
11551208
string toString() {
11561209
this.isSelf() and result = "self"
@@ -1170,6 +1223,8 @@ class ParameterPosition extends TParameterPosition {
11701223
this.isAny() and result = "any"
11711224
or
11721225
this.isAnyNamed() and result = "any-named"
1226+
or
1227+
exists(LocalVariable v | this.isCapturedVariable(v) and result = "captured " + v)
11731228
}
11741229
}
11751230

@@ -1196,6 +1251,8 @@ class ArgumentPosition extends TArgumentPosition {
11961251
/** Holds if this position represents any positional parameter. */
11971252
predicate isAnyNamed() { this = TAnyKeywordArgumentPosition() }
11981253

1254+
predicate isCapturedVariable(LocalVariable v) { this = TCapturedArgumentPosition(v) }
1255+
11991256
/**
12001257
* Holds if this position represents a synthesized argument containing all keyword
12011258
* arguments wrapped in a hash.
@@ -1221,6 +1278,8 @@ class ArgumentPosition extends TArgumentPosition {
12211278
this.isHashSplat() and result = "**"
12221279
or
12231280
this.isSplatAll() and result = "*"
1281+
or
1282+
exists(LocalVariable v | this.isCapturedVariable(v) and result = "captured " + v)
12241283
}
12251284
}
12261285

@@ -1256,4 +1315,6 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
12561315
ppos.isAnyNamed() and apos.isKeyword(_)
12571316
or
12581317
apos.isAnyNamed() and ppos.isKeyword(_)
1318+
or
1319+
exists(LocalVariable v | apos.isCapturedVariable(v) and ppos.isCapturedVariable(v))
12591320
}

0 commit comments

Comments
 (0)