Skip to content

Commit 0ccca47

Browse files
committed
Dataflow for implicit self argument of methods
1 parent eb8b255 commit 0ccca47

3 files changed

Lines changed: 37 additions & 4 deletions

File tree

ql/src/codeql_ruby/dataflow/internal/DataFlowPrivate.qll

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,11 @@ private module Cached {
116116
TReturningNode(CfgNodes::ReturningCfgNode n) or
117117
TSsaDefinitionNode(Ssa::Definition def) or
118118
TNormalParameterNode(Parameter p) { not p instanceof BlockParameter } or
119+
TSelfParameterNode(MethodBase m) or
119120
TBlockParameterNode(MethodBase m) or
120121
TExprPostUpdateNode(CfgNodes::ExprCfgNode n) { n.getNode() instanceof Argument }
121122

122-
class TParameterNode = TNormalParameterNode or TBlockParameterNode;
123+
class TParameterNode = TNormalParameterNode or TBlockParameterNode or TSelfParameterNode;
123124

124125
/**
125126
* This is the local flow predicate that is used as a building block in global
@@ -137,6 +138,9 @@ private module Cached {
137138
nodeTo.(ParameterNode).getParameter().(KeywordParameter).getDefaultValue() =
138139
nodeFrom.asExpr().getExpr()
139140
or
141+
nodeFrom.(SelfParameterNode).getMethod() = nodeTo.asExpr().getExpr().getEnclosingMethod() and
142+
nodeTo.asExpr().getExpr() instanceof Self
143+
or
140144
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::AssignExprCfgNode).getRhs()
141145
or
142146
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::BlockArgumentCfgNode).getValue()
@@ -242,6 +246,26 @@ private module ParameterNodes {
242246
override string toStringImpl() { result = parameter.toString() }
243247
}
244248

249+
/**
250+
* The value of the `self` parameter at function entry, viewed as a node in a data
251+
* flow graph.
252+
*/
253+
class SelfParameterNode extends ParameterNodeImpl, TSelfParameterNode {
254+
private MethodBase method;
255+
256+
SelfParameterNode() { this = TSelfParameterNode(method) }
257+
258+
final MethodBase getMethod() { result = method }
259+
260+
override predicate isParameterOf(Callable c, int i) { method = c and i = -1 }
261+
262+
override CfgScope getCfgScope() { result = method }
263+
264+
override Location getLocationImpl() { result = method.getLocation() }
265+
266+
override string toStringImpl() { result = "self in " + method.toString() }
267+
}
268+
245269
/**
246270
* The value of a block parameter at function entry, viewed as a node in a data
247271
* flow graph.
@@ -295,11 +319,18 @@ private module ArgumentNodes {
295319
not this.asExpr().getExpr() instanceof BlockArgument
296320
}
297321

322+
override predicate argumentOf(DataFlowCall call, int pos) {
323+
this.asExpr() = call.getArgument(pos)
324+
}
325+
}
326+
327+
/** A data-flow node that represents the `self` argument of a call. */
328+
class SelfArgumentNode extends ArgumentNode {
329+
SelfArgumentNode() { this.asExpr() = any(CfgNodes::ExprNodes::CallCfgNode call).getReceiver() }
330+
298331
override predicate argumentOf(DataFlowCall call, int pos) {
299332
this.asExpr() = call.getReceiver() and
300333
pos = -1
301-
or
302-
this.asExpr() = call.getArgument(pos)
303334
}
304335
}
305336

ql/test/library-tests/dataflow/local/DataflowStep.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
| local_dataflow.rb:1:1:7:3 | self in foo | local_dataflow.rb:3:8:3:10 | self |
12
| local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:1:9:1:9 | a |
23
| local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:2:7:2:7 | a |
34
| local_dataflow.rb:2:3:2:7 | ... = ... | local_dataflow.rb:3:13:3:13 | b |

ql/test/library-tests/modules/callgraph.expected

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ getTarget
5252
| calls.rb:137:5:137:17 | call to call_block | calls.rb:67:1:69:3 | call_block |
5353
| calls.rb:140:1:140:28 | call to indirect | calls.rb:136:1:138:3 | indirect |
5454
| calls.rb:140:16:140:27 | call to bit_length | calls.rb:78:5:78:23 | bit_length |
55+
| calls.rb:145:9:145:17 | call to to_s | calls.rb:150:5:151:7 | to_s |
56+
| calls.rb:145:9:145:17 | call to to_s | calls.rb:155:5:156:7 | to_s |
5557
| calls.rb:159:1:159:5 | call to new | calls.rb:98:5:98:16 | new |
5658
| calls.rb:159:1:159:14 | call to s_method | calls.rb:144:5:146:7 | s_method |
5759
| calls.rb:160:1:160:5 | call to new | calls.rb:98:5:98:16 | new |
@@ -87,4 +89,3 @@ unresolvedCall
8789
| calls.rb:128:48:128:59 | call to capitalize |
8890
| calls.rb:132:28:132:39 | call to capitalize |
8991
| calls.rb:134:32:134:36 | call to abs |
90-
| calls.rb:145:9:145:17 | call to to_s |

0 commit comments

Comments
 (0)