Ruby: More filter flow steps

Add a jump step from the last self post-update node in a method to the self parameter of the
next method.
This commit is contained in:
Harry Maclean
2023-02-13 16:12:34 +13:00
parent fae5320c3a
commit 0a02b45ad7
3 changed files with 80 additions and 1 deletions

View File

@@ -428,6 +428,32 @@ module Filters {
)
}
/**
* Holds if `n` is a post-update node for `self` in method `m`.
*/
predicate selfPostUpdate(DataFlow::PostUpdateNode n, Method m) {
n.getPreUpdateNode().asExpr() instanceof SelfVariableAccessCfgNode and
m = n.getPreUpdateNode().asExpr().getExpr().getEnclosingCallable()
}
/**
* Holds if `n` is the syntactically last dataflow node in `m` that satisfies `selfPostUpdate`.
* In the example below, `n` is the post-update node for `bar`.
* ```rb
* def m
* foo
* bar
* end
* ```
*/
predicate lastSelfPostUpdate(DataFlow::PostUpdateNode n, Method m) {
selfPostUpdate(n, m) and
not exists(DataFlow::PostUpdateNode n2 |
selfPostUpdate(n2, m) and
n.getPreUpdateNode().asExpr().getASuccessor+() = n2.getPreUpdateNode().asExpr()
)
}
/**
* Holds if `a` is the syntactically last access of the self variable `v` in method `m`.
*/
@@ -468,7 +494,8 @@ module Filters {
exists(Method predMethod, Method succMethod |
next(predMethod, succMethod) and
(
// Flow from an update of self in `pred` to the self parameter of `succ`
// Flow from an update of self (due to an instance variable write) in
// `pred` to the self parameter of `succ`
//
// def a
// @x = 1 ---+
@@ -480,6 +507,18 @@ module Filters {
lastVariableAccessPostUpdate(pred, predMethod) and
selfParameter(succ, succMethod)
or
// Flow from an update of self in `pred` to the self parameter of `succ`
//
// def a
// @x = 1 ---+
// end |
// |
// def b <----+
// ...
//
lastSelfPostUpdate(pred, predMethod) and
selfParameter(succ, succMethod)
or
// When there is no update of self in `pred`, flow from the last access to self to the self parameter of `succ`
//
// def a