Skip to content

Commit fbab0f5

Browse files
committed
Ruby: Evaluate longer summary component stacks
1 parent 0000a7d commit fbab0f5

File tree

1 file changed

+81
-38
lines changed

1 file changed

+81
-38
lines changed

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

Lines changed: 81 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ class TypeTrackingNode = DataFlowPublic::LocalSourceNode;
1717

1818
class TypeTrackerContent = DataFlowPublic::ContentSet;
1919

20+
private module SCS = SummaryComponentStack;
21+
22+
private module SC = SummaryComponent;
23+
2024
/**
2125
* An optional content set, that is, a `ContentSet` or the special "no content set" value.
2226
*/
@@ -64,13 +68,13 @@ private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) {
6468
)
6569
or
6670
exists(
67-
SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponent input,
68-
SummaryComponent output
71+
SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponentStack input,
72+
SummaryComponentStack output
6973
|
70-
hasLevelSummary(callable, input, output) and
74+
callable.propagatesFlow(input, output, true) and
7175
call.asExpr().getExpr() = callable.getACallSimple() and
72-
nodeFrom = evaluateSummaryComponentLocal(call, input) and
73-
nodeTo = evaluateSummaryComponentLocal(call, output)
76+
nodeFrom = evaluateSummaryComponentStackLocal(call, input) and
77+
nodeTo = evaluateSummaryComponentStackLocal(call, output)
7478
)
7579
}
7680

@@ -181,13 +185,13 @@ predicate basicStoreStep(Node nodeFrom, Node nodeTo, DataFlow::ContentSet conten
181185
postUpdateStoreStep(nodeFrom, nodeTo, contents)
182186
or
183187
exists(
184-
SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponent input,
185-
SummaryComponent output
188+
SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponentStack input,
189+
SummaryComponentStack output
186190
|
187191
hasStoreSummary(callable, contents, input, output) and
188192
call.asExpr().getExpr() = callable.getACallSimple() and
189-
nodeFrom = evaluateSummaryComponentLocal(call, input) and
190-
nodeTo = evaluateSummaryComponentLocal(call, output)
193+
nodeFrom = evaluateSummaryComponentStackLocal(call, input) and
194+
nodeTo = evaluateSummaryComponentStackLocal(call, output)
191195
)
192196
}
193197

@@ -221,13 +225,13 @@ predicate basicLoadStep(Node nodeFrom, Node nodeTo, DataFlow::ContentSet content
221225
)
222226
or
223227
exists(
224-
SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponent input,
225-
SummaryComponent output
228+
SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponentStack input,
229+
SummaryComponentStack output
226230
|
227231
hasLoadSummary(callable, contents, input, output) and
228232
call.asExpr().getExpr() = callable.getACallSimple() and
229-
nodeFrom = evaluateSummaryComponentLocal(call, input) and
230-
nodeTo = evaluateSummaryComponentLocal(call, output)
233+
nodeFrom = evaluateSummaryComponentStackLocal(call, input) and
234+
nodeTo = evaluateSummaryComponentStackLocal(call, output)
231235
)
232236
}
233237

@@ -238,13 +242,13 @@ predicate basicLoadStoreStep(
238242
Node nodeFrom, Node nodeTo, DataFlow::ContentSet loadContent, DataFlow::ContentSet storeContent
239243
) {
240244
exists(
241-
SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponent input,
242-
SummaryComponent output
245+
SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponentStack input,
246+
SummaryComponentStack output
243247
|
244248
hasLoadStoreSummary(callable, loadContent, storeContent, input, output) and
245249
call.asExpr().getExpr() = callable.getACallSimple() and
246-
nodeFrom = evaluateSummaryComponentLocal(call, input) and
247-
nodeTo = evaluateSummaryComponentLocal(call, output)
250+
nodeFrom = evaluateSummaryComponentStackLocal(call, input) and
251+
nodeTo = evaluateSummaryComponentStackLocal(call, output)
248252
)
249253
}
250254

@@ -257,46 +261,39 @@ class Boolean extends boolean {
257261

258262
private import SummaryComponentStack
259263

260-
private predicate hasLevelSummary(
261-
SummarizedCallable callable, SummaryComponent input, SummaryComponent output
262-
) {
263-
callable.propagatesFlow(singleton(input), singleton(output), true)
264-
}
265-
264+
pragma[nomagic]
266265
private predicate hasStoreSummary(
267-
SummarizedCallable callable, DataFlow::ContentSet contents, SummaryComponent input,
268-
SummaryComponent output
266+
SummarizedCallable callable, DataFlow::ContentSet contents, SummaryComponentStack input,
267+
SummaryComponentStack output
269268
) {
270-
callable
271-
.propagatesFlow(singleton(input),
272-
push(SummaryComponent::content(contents), singleton(output)), true)
269+
callable.propagatesFlow(input, push(SummaryComponent::content(contents), output), true)
273270
}
274271

272+
pragma[nomagic]
275273
private predicate hasLoadSummary(
276-
SummarizedCallable callable, DataFlow::ContentSet contents, SummaryComponent input,
277-
SummaryComponent output
274+
SummarizedCallable callable, DataFlow::ContentSet contents, SummaryComponentStack input,
275+
SummaryComponentStack output
278276
) {
279-
callable
280-
.propagatesFlow(push(SummaryComponent::content(contents), singleton(input)),
281-
singleton(output), true)
277+
callable.propagatesFlow(push(SummaryComponent::content(contents), input), output, true)
282278
}
283279

280+
pragma[nomagic]
284281
private predicate hasLoadStoreSummary(
285282
SummarizedCallable callable, DataFlow::ContentSet loadContents,
286-
DataFlow::ContentSet storeContents, SummaryComponent input, SummaryComponent output
283+
DataFlow::ContentSet storeContents, SummaryComponentStack input, SummaryComponentStack output
287284
) {
288285
callable
289-
.propagatesFlow(push(SummaryComponent::content(loadContents), singleton(input)),
290-
push(SummaryComponent::content(storeContents), singleton(output)), true)
286+
.propagatesFlow(push(SummaryComponent::content(loadContents), input),
287+
push(SummaryComponent::content(storeContents), output), true)
291288
}
292289

293290
/**
294291
* Gets a data flow node corresponding an argument or return value of `call`,
295292
* as specified by `component`.
296293
*/
297294
bindingset[call, component]
298-
private DataFlowPublic::Node evaluateSummaryComponentLocal(
299-
DataFlowPublic::CallNode call, SummaryComponent component
295+
private DataFlow::Node evaluateSummaryComponentLocal(
296+
DataFlow::CallNode call, SummaryComponent component
300297
) {
301298
exists(DataFlowDispatch::ParameterPosition pos |
302299
component = SummaryComponent::argument(pos) and
@@ -306,3 +303,49 @@ private DataFlowPublic::Node evaluateSummaryComponentLocal(
306303
component = SummaryComponent::return() and
307304
result = call
308305
}
306+
307+
/**
308+
* Holds if `callable` is relevant for type-tracking and we therefore want `stack` to
309+
* be evaluated locally at its call sites.
310+
*/
311+
private predicate dependsOnSummaryComponentStack(
312+
SummarizedCallable callable, SummaryComponentStack stack
313+
) {
314+
exists(callable.getACallSimple()) and
315+
(
316+
callable.propagatesFlow(stack, _, true)
317+
or
318+
callable.propagatesFlow(_, stack, true)
319+
)
320+
or
321+
dependsOnSummaryComponentStack(callable, SCS::push(_, stack))
322+
}
323+
324+
/**
325+
* Gets a data flow node corresponding to the local input or output of `call`
326+
* identified by `stack`, if possible.
327+
*/
328+
private DataFlow::Node evaluateSummaryComponentStackLocal(
329+
DataFlow::CallNode call, SummaryComponentStack stack
330+
) {
331+
exists(SummarizedCallable callable, SummaryComponent component |
332+
dependsOnSummaryComponentStack(callable, stack) and
333+
stack = SCS::singleton(component) and
334+
call.asExpr().getExpr() = callable.getACallSimple() and
335+
result = evaluateSummaryComponentLocal(call, component)
336+
)
337+
or
338+
exists(DataFlow::Node prev, SummaryComponent head, SummaryComponentStack tail |
339+
stack = SCS::push(head, tail) and
340+
prev = evaluateSummaryComponentStackLocal(call, tail)
341+
|
342+
exists(DataFlowDispatch::ArgumentPosition apos, DataFlowDispatch::ParameterPosition ppos |
343+
head = SummaryComponent::parameter(apos) and
344+
DataFlowDispatch::parameterMatch(ppos, apos) and
345+
result.(DataFlowPrivate::ParameterNodeImpl).isSourceParameterOf(prev.asExpr().getExpr(), ppos)
346+
)
347+
or
348+
head = SummaryComponent::return() and
349+
result.(DataFlowPrivate::SynthReturnNode).getCfgScope() = prev.asExpr().getExpr()
350+
)
351+
}

0 commit comments

Comments
 (0)