Skip to content

Commit 95027e7

Browse files
committed
Ruby: TypeTracker: add smallstep for functions that return their arguments
1 parent 9c4c351 commit 95027e7

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

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

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,31 @@ class Node = DataFlowPublic::Node;
1111

1212
class TypeTrackingNode = DataFlowPublic::LocalSourceNode;
1313

14+
/** Holds if there is a simple local flow step from `nodeFrom` to `nodeTo` */
1415
predicate simpleLocalFlowStep = DataFlowPrivate::localFlowStepTypeTracker/2;
1516

17+
/**
18+
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
19+
*/
1620
predicate jumpStep = DataFlowPrivate::jumpStep/2;
1721

18-
/** Holds if there is a level step from `pred` to `succ`. */
19-
predicate levelStep(Node pred, Node succ) { none() }
22+
/**
23+
* Holds if there is a summarized local flow step from `nodeFrom` to `nodeTo`,
24+
* because there is direct flow from a parameter to a return. That is, summarized
25+
* steps are not applied recursively.
26+
*/
27+
pragma[nomagic]
28+
private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) {
29+
exists(DataFlowPublic::ParameterNode param, DataFlowPrivate::ReturningNode returnNode |
30+
DataFlowPrivate::LocalFlow::getParameterDefNode(param.getParameter())
31+
.(TypeTrackingNode)
32+
.flowsTo(returnNode) and
33+
callStep(nodeTo.asExpr(), nodeFrom, param)
34+
)
35+
}
36+
37+
/** Holds if there is a level step from `nodeFrom` to `nodeTo`. */
38+
predicate levelStep(Node nodeFrom, Node nodeTo) { summarizedLocalStep(nodeFrom, nodeTo) }
2039

2140
/**
2241
* Gets the name of a possible piece of content. This will usually include things like
@@ -48,6 +67,13 @@ private predicate viableParam(
4867
)
4968
}
5069

70+
private predicate callStep(ExprNodes::CallCfgNode call, Node nodeFrom, Node nodeTo) {
71+
exists(DataFlowDispatch::ParameterPosition pos |
72+
argumentPositionMatch(call, nodeFrom, pos) and
73+
viableParam(call, nodeTo, pos)
74+
)
75+
}
76+
5177
/**
5278
* Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call.
5379
*
@@ -56,10 +82,7 @@ private predicate viableParam(
5682
* methods is done using API graphs (which uses type tracking).
5783
*/
5884
predicate callStep(Node nodeFrom, Node nodeTo) {
59-
exists(ExprNodes::CallCfgNode call, DataFlowDispatch::ParameterPosition pos |
60-
argumentPositionMatch(call, nodeFrom, pos) and
61-
viableParam(call, nodeTo, pos)
62-
)
85+
callStep(_, nodeFrom, nodeTo)
6386
or
6487
// In normal data-flow, this will be a local flow step. But for type tracking
6588
// we model it as a call step, in order to avoid computing a potential

0 commit comments

Comments
 (0)