API graphs: Performance fixes

This commit is contained in:
Tom Hvitved
2021-09-01 15:32:49 +02:00
parent ae70af01cd
commit 03e91a22bc

View File

@@ -277,7 +277,7 @@ module API {
not exists(read.getScopeExpr()) not exists(read.getScopeExpr())
) )
or or
exists(DataFlow::LocalSourceNode src, DataFlow::LocalSourceNode pred | exists(ExprCfgNode node |
// First, we find a predecessor of the node `ref` that we want to determine. The predecessor // First, we find a predecessor of the node `ref` that we want to determine. The predecessor
// is any node that is a type-tracked use of a data flow node (`src`), which is itself a // is any node that is a type-tracked use of a data flow node (`src`), which is itself a
// reference to the API node `base`. Thus, `pred` and `src` both represent uses of `base`. // reference to the API node `base`. Thus, `pred` and `src` both represent uses of `base`.
@@ -285,25 +285,23 @@ module API {
// Once we have identified the predecessor, we define its relation to the successor `ref` as // Once we have identified the predecessor, we define its relation to the successor `ref` as
// well as the label on the edge from `pred` to `ref`. This label describes the nature of // well as the label on the edge from `pred` to `ref`. This label describes the nature of
// the relationship between `pred` and `ref`. // the relationship between `pred` and `ref`.
use(base, src) and pred = trackUseNode(src) useExpr(node, base)
| |
// // Referring to an attribute on a node that is a use of `base`: // // Referring to an attribute on a node that is a use of `base`:
// pred = `Rails` part of `Rails::Whatever` // pred = `Rails` part of `Rails::Whatever`
// lbl = `Whatever` // lbl = `Whatever`
// ref = `Rails::Whatever` // ref = `Rails::Whatever`
exists(ExprNodes::ConstantAccessCfgNode c, DataFlow::Node node, ConstantReadAccess read | exists(ExprNodes::ConstantAccessCfgNode c, ConstantReadAccess read |
not exists(resolveTopLevel(read)) and not exists(resolveTopLevel(read)) and
pred.flowsTo(node) and node = c.getScopeExpr() and
node.asExpr() = c.getScopeExpr() and
lbl = Label::member(read.getName()) and lbl = Label::member(read.getName()) and
ref.asExpr() = c and ref.asExpr() = c and
read = c.getExpr() read = c.getExpr()
) )
or or
// Calling a method on a node that is a use of `base` // Calling a method on a node that is a use of `base`
exists(ExprNodes::MethodCallCfgNode call, DataFlow::Node node, string name | exists(ExprNodes::MethodCallCfgNode call, string name |
pred.flowsTo(node) and node = call.getReceiver() and
node.asExpr() = call.getReceiver() and
name = call.getExpr().getMethodName() and name = call.getExpr().getMethodName() and
lbl = Label::return(name) and lbl = Label::return(name) and
name != "new" and name != "new" and
@@ -311,9 +309,8 @@ module API {
) )
or or
// Calling the `new` method on a node that is a use of `base`, which creates a new instance // Calling the `new` method on a node that is a use of `base`, which creates a new instance
exists(ExprNodes::MethodCallCfgNode call, DataFlow::Node node | exists(ExprNodes::MethodCallCfgNode call |
pred.flowsTo(node) and node = call.getReceiver() and
node.asExpr() = call.getReceiver() and
lbl = Label::instance() and lbl = Label::instance() and
call.getExpr().getMethodName() = "new" and call.getExpr().getMethodName() = "new" and
ref.asExpr() = call ref.asExpr() = call
@@ -321,6 +318,15 @@ module API {
) )
} }
pragma[nomagic]
private predicate useExpr(ExprCfgNode node, TApiNode base) {
exists(DataFlow::LocalSourceNode src, DataFlow::LocalSourceNode pred |
use(base, src) and
pred = trackUseNode(src) and
pred.flowsTo(any(DataFlow::ExprNode n | n.getExprNode() = node))
)
}
/** /**
* Holds if `ref` is a use of node `nd`. * Holds if `ref` is a use of node `nd`.
*/ */
@@ -332,7 +338,10 @@ module API {
* *
* The flow from `src` to that node may be inter-procedural. * The flow from `src` to that node may be inter-procedural.
*/ */
private DataFlow::LocalSourceNode trackUseNode(DataFlow::LocalSourceNode src, TypeTracker t) { private DataFlow::LocalSourceNode trackUseNode(DataFlow::Node src, TypeTracker t) {
// Declaring `src` to be a `SourceNode` currently causes a redundant check in the
// recursive case, so instead we check it explicitly here.
src instanceof DataFlow::LocalSourceNode and
t.start() and t.start() and
use(_, src) and use(_, src) and
result = src result = src