Ruby: TypeTracker: add smallstep for functions that return their arguments

This commit is contained in:
Arthur Baars
2022-03-01 17:42:07 +01:00
parent 9c4c35141a
commit 95027e746c

View File

@@ -11,12 +11,31 @@ class Node = DataFlowPublic::Node;
class TypeTrackingNode = DataFlowPublic::LocalSourceNode;
/** Holds if there is a simple local flow step from `nodeFrom` to `nodeTo` */
predicate simpleLocalFlowStep = DataFlowPrivate::localFlowStepTypeTracker/2;
/**
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
predicate jumpStep = DataFlowPrivate::jumpStep/2;
/** Holds if there is a level step from `pred` to `succ`. */
predicate levelStep(Node pred, Node succ) { none() }
/**
* Holds if there is a summarized local flow step from `nodeFrom` to `nodeTo`,
* because there is direct flow from a parameter to a return. That is, summarized
* steps are not applied recursively.
*/
pragma[nomagic]
private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) {
exists(DataFlowPublic::ParameterNode param, DataFlowPrivate::ReturningNode returnNode |
DataFlowPrivate::LocalFlow::getParameterDefNode(param.getParameter())
.(TypeTrackingNode)
.flowsTo(returnNode) and
callStep(nodeTo.asExpr(), nodeFrom, param)
)
}
/** Holds if there is a level step from `nodeFrom` to `nodeTo`. */
predicate levelStep(Node nodeFrom, Node nodeTo) { summarizedLocalStep(nodeFrom, nodeTo) }
/**
* Gets the name of a possible piece of content. This will usually include things like
@@ -48,6 +67,13 @@ private predicate viableParam(
)
}
private predicate callStep(ExprNodes::CallCfgNode call, Node nodeFrom, Node nodeTo) {
exists(DataFlowDispatch::ParameterPosition pos |
argumentPositionMatch(call, nodeFrom, pos) and
viableParam(call, nodeTo, pos)
)
}
/**
* Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call.
*
@@ -56,10 +82,7 @@ private predicate viableParam(
* methods is done using API graphs (which uses type tracking).
*/
predicate callStep(Node nodeFrom, Node nodeTo) {
exists(ExprNodes::CallCfgNode call, DataFlowDispatch::ParameterPosition pos |
argumentPositionMatch(call, nodeFrom, pos) and
viableParam(call, nodeTo, pos)
)
callStep(_, nodeFrom, nodeTo)
or
// In normal data-flow, this will be a local flow step. But for type tracking
// we model it as a call step, in order to avoid computing a potential