Skip to content

Commit 2e8f46d

Browse files
committed
Type tracking: Split up levelStep into levelStepNoCall and levelStepCall
To reduce non-linear recursion during call graph construction.
1 parent 0883b17 commit 2e8f46d

File tree

2 files changed

+21
-15
lines changed

2 files changed

+21
-15
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ private module Cached {
186186
jumpStep(nodeFrom, nodeTo) and
187187
summary = JumpStep()
188188
or
189-
levelStep(nodeFrom, nodeTo) and
189+
levelStepNoCall(nodeFrom, nodeTo) and
190190
summary = LevelStep()
191191
or
192192
exists(TypeTrackerContent content |
@@ -216,6 +216,9 @@ private module Cached {
216216
or
217217
returnStep(nodeFrom, nodeTo) and
218218
summary = ReturnStep()
219+
or
220+
levelStepCall(nodeFrom, nodeTo) and
221+
summary = LevelStep()
219222
}
220223
}
221224

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

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,28 @@ predicate simpleLocalFlowStep = DataFlowPrivate::localFlowStepTypeTracker/2;
7676
*/
7777
predicate jumpStep = DataFlowPrivate::jumpStep/2;
7878

79-
/**
80-
* Holds if there is a summarized local flow step from `nodeFrom` to `nodeTo`,
81-
* because there is direct flow from a parameter to a return. That is, summarized
82-
* steps are not applied recursively.
83-
*/
79+
/** Holds if there is direct flow from `param` to a return. */
8480
pragma[nomagic]
85-
private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) {
86-
exists(DataFlowPublic::ParameterNode param, DataFlowPrivate::ReturningNode returnNode |
81+
private predicate flowThrough(DataFlowPublic::ParameterNode param) {
82+
exists(DataFlowPrivate::ReturningNode returnNode |
8783
DataFlowPrivate::LocalFlow::getParameterDefNode(param.getParameter())
8884
.(TypeTrackingNode)
89-
.flowsTo(returnNode) and
85+
.flowsTo(returnNode)
86+
)
87+
}
88+
89+
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */
90+
pragma[nomagic]
91+
predicate levelStepCall(Node nodeFrom, Node nodeTo) {
92+
exists(DataFlowPublic::ParameterNode param |
93+
flowThrough(param) and
9094
callStep(nodeTo.asExpr(), nodeFrom, param)
9195
)
92-
or
96+
}
97+
98+
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which does not depend on the call graph. */
99+
pragma[nomagic]
100+
predicate levelStepNoCall(Node nodeFrom, Node nodeTo) {
93101
exists(
94102
SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponentStack input,
95103
SummaryComponentStack output
@@ -99,11 +107,6 @@ private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) {
99107
nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and
100108
nodeTo = evaluateSummaryComponentStackLocal(callable, call, output)
101109
)
102-
}
103-
104-
/** Holds if there is a level step from `nodeFrom` to `nodeTo`. */
105-
predicate levelStep(Node nodeFrom, Node nodeTo) {
106-
summarizedLocalStep(nodeFrom, nodeTo)
107110
or
108111
localFieldStep(nodeFrom, nodeTo)
109112
}

0 commit comments

Comments
 (0)