-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1
- Loading branch information
Showing
1 changed file
with
119 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
class FilterJumpStep extends TypeTrackingInput::AdditionalCapturedJumpStep { | ||
/** | ||
* Holds if data can flow from `pred` to `succ` via a callback chain. | ||
*/ | ||
|
||
predicate test(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { | ||
exists(Attribute attr, SelfAttributeStore store, DataFlow::Node objNode | | ||
attr.getObject() = objNode.asExpr() | ||
and attr.getName() = store.getName() | ||
and objNode.getALocalSource().asExpr() = store.getClass().getClassObject().getACall().getNode() | ||
and nodeFrom.asExpr() = attr | ||
and nodeTo.asExpr() = store.getAssignedValue() | ||
) | ||
} | ||
|
||
override predicate othercapturedjumpstep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { | ||
// Class Base: | ||
// var = expr | ||
// ... | ||
// def f(self): | ||
// ...self.var is used... | ||
// | ||
// Class Sub(Base): | ||
// def g(self): | ||
// ...self.var is used... | ||
// | ||
// nodeFrom is `expr` | ||
// nodeTo is entry node for `self.var` | ||
exists(SelfAttributeRead read, Class baseClass, Class subClass | | ||
baseClass.contains(nodeFrom.asExpr()) and | ||
( | ||
exists(ClassObject subClassObj | | ||
subClassObj.getABaseType*() = baseClass.getClassObject() and | ||
subClassObj = subClass.getClassObject() | ||
) | ||
or | ||
subClass = baseClass | ||
) | ||
and | ||
subClass.contains(read) and | ||
read.getName() = nodeFrom.asExpr().toString() and | ||
nodeTo.asCfgNode() = read.getAFlowNode() | ||
) | ||
// Class Base: | ||
// def __init__(self, expr=expr): | ||
// self.var = expr | ||
// | ||
// def f(self): | ||
// ...self.var is used... | ||
// | ||
// Class Sub(Base): | ||
// def g(self): | ||
// ...self.var is used... | ||
// | ||
// nodeFrom is `expr` | ||
// nodeTo is entry node for `self.var` | ||
or | ||
exists(SelfAttributeStore store, SelfAttributeRead read, Class subClass | | ||
nodeFrom.asExpr() = store.getAssignedValue() and | ||
( | ||
exists(Class baseClass, ClassObject subClassObj | | ||
baseClass = store.getClass() and | ||
subClassObj.getABaseType*() = baseClass.getClassObject() and | ||
subClassObj = subClass.getClassObject() | ||
) | ||
or | ||
subClass = store.getClass() | ||
) | ||
and | ||
subClass.contains(read) and | ||
read.getName() = store.getName() and | ||
nodeTo.asCfgNode() = read.getAFlowNode() | ||
) | ||
or | ||
exists(Attribute attr, SelfAttributeStore store, DataFlow::Node objNode | | ||
attr.getObject() = objNode.asExpr() | ||
and attr.getName() = store.getName() | ||
and objNode.getALocalSource().asExpr() = store.getClass().getClassObject().getACall().getNode() | ||
and nodeFrom.asExpr() = store.getAssignedValue() | ||
and nodeTo.asExpr() = attr | ||
) | ||
} | ||
} | ||
|
||
|
||
/** | ||
* A unit class for adding additional jump steps. | ||
* | ||
* Extend this class to add additional jump steps. | ||
*/ | ||
class AdditionalCapturedJumpStep extends Unit { | ||
/** | ||
* Holds if data can flow from `pred` to `succ` in a way that discards call contexts. | ||
*/ | ||
abstract predicate othercapturedjumpstep(Node pred, Node succ); | ||
} | ||
|
||
|
||
private predicate capturedJumpStep(Node nodeFrom, Node nodeTo) { | ||
// Jump into a capturing scope. | ||
// | ||
// var = expr | ||
// ... | ||
// def f(): | ||
// ..var is used.. | ||
// | ||
// nodeFrom is `expr` | ||
// nodeTo is entry node for `f` | ||
exists(ScopeEntryDefinition e, SsaSourceVariable var, DefinitionNode def | | ||
e.getSourceVariable() = var and | ||
var.hasDefiningNode(def) | ||
| | ||
nodeTo.(DataFlowPublic::ScopeEntryDefinitionNode).getDefinition() = e and | ||
nodeFrom.asCfgNode() = def.getValue() and | ||
var.getScope().getScope*() = nodeFrom.getScope() | ||
) | ||
or | ||
any(AdditionalCapturedJumpStep s).othercapturedjumpstep(nodeFrom, nodeTo) | ||
} |