mirror of
https://github.com/github/codeql.git
synced 2025-12-16 08:43:11 +01:00
Python: Fully remove points-to from Flow.qll
Gets rid of a bunch of predicates relating to reachability (which depended on the modelling of exceptions, which uses points-to), moving them to `LegacyPointsTo`. In the process, we gained a new class `BasicBlockWithPointsTo`.
This commit is contained in:
@@ -106,6 +106,24 @@ class ControlFlowNodeWithPointsTo extends ControlFlowNode {
|
||||
// for that variable.
|
||||
exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v))
|
||||
}
|
||||
|
||||
/** Whether it is unlikely that this ControlFlowNode can be reached */
|
||||
predicate unlikelyReachable() {
|
||||
not start_bb_likely_reachable(this.getBasicBlock())
|
||||
or
|
||||
exists(BasicBlock b |
|
||||
start_bb_likely_reachable(b) and
|
||||
not end_bb_likely_reachable(b) and
|
||||
// If there is an unlikely successor edge earlier in the BB
|
||||
// than this node, then this node must be unreachable.
|
||||
exists(ControlFlowNode p, int i, int j |
|
||||
p.(RaisingNode).unlikelySuccessor(_) and
|
||||
p = b.getNode(i) and
|
||||
this = b.getNode(j) and
|
||||
i < j
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,6 +152,45 @@ private predicate varHasCompletePointsToSet(SsaVariable var) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate start_bb_likely_reachable(BasicBlock b) {
|
||||
exists(Scope s | s.getEntryNode() = b.getNode(_))
|
||||
or
|
||||
exists(BasicBlock pred |
|
||||
pred = b.getAPredecessor() and
|
||||
end_bb_likely_reachable(pred) and
|
||||
not pred.getLastNode().(RaisingNode).unlikelySuccessor(b)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate end_bb_likely_reachable(BasicBlock b) {
|
||||
start_bb_likely_reachable(b) and
|
||||
not exists(ControlFlowNode p, ControlFlowNode s |
|
||||
p.(RaisingNode).unlikelySuccessor(s) and
|
||||
p = b.getNode(_) and
|
||||
s = b.getNode(_) and
|
||||
not p = b.getLastNode()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of `BasicBlock` that provides points-to related methods.
|
||||
*/
|
||||
class BasicBlockWithPointsTo extends BasicBlock {
|
||||
/**
|
||||
* Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ.
|
||||
*/
|
||||
predicate unlikelySuccessor(BasicBlockWithPointsTo succ) {
|
||||
this.getLastNode().(RaisingNode).unlikelySuccessor(succ.firstNode())
|
||||
or
|
||||
not end_bb_likely_reachable(this) and succ = this.getASuccessor()
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether (as inferred by type inference) this basic block is likely to be reachable.
|
||||
*/
|
||||
predicate likelyReachable() { start_bb_likely_reachable(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of `Expr` that provides points-to predicates.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import python
|
||||
private import semmle.python.internal.CachedStages
|
||||
private import codeql.controlflow.BasicBlock as BB
|
||||
private import LegacyPointsTo
|
||||
|
||||
/*
|
||||
* Note about matching parent and child nodes and CFG splitting:
|
||||
@@ -191,24 +190,6 @@ class ControlFlowNode extends @py_flow_node {
|
||||
/** Whether this node is a normal (non-exceptional) exit */
|
||||
predicate isNormalExit() { py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) }
|
||||
|
||||
/** Whether it is unlikely that this ControlFlowNode can be reached */
|
||||
predicate unlikelyReachable() {
|
||||
not start_bb_likely_reachable(this.getBasicBlock())
|
||||
or
|
||||
exists(BasicBlock b |
|
||||
start_bb_likely_reachable(b) and
|
||||
not end_bb_likely_reachable(b) and
|
||||
// If there is an unlikely successor edge earlier in the BB
|
||||
// than this node, then this node must be unreachable.
|
||||
exists(ControlFlowNode p, int i, int j |
|
||||
p.(RaisingNode).unlikelySuccessor(_) and
|
||||
p = b.getNode(i) and
|
||||
this = b.getNode(j) and
|
||||
i < j
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Whether this strictly dominates other. */
|
||||
pragma[inline]
|
||||
predicate strictlyDominates(ControlFlowNode other) {
|
||||
@@ -1005,7 +986,8 @@ class BasicBlock extends @py_flow_node {
|
||||
)
|
||||
}
|
||||
|
||||
private ControlFlowNode firstNode() { result = this }
|
||||
/** Gets the first node in this basic block */
|
||||
ControlFlowNode firstNode() { result = this }
|
||||
|
||||
/** Gets the last node in this basic block */
|
||||
ControlFlowNode getLastNode() {
|
||||
@@ -1094,15 +1076,6 @@ class BasicBlock extends @py_flow_node {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ.
|
||||
*/
|
||||
predicate unlikelySuccessor(BasicBlock succ) {
|
||||
this.getLastNode().(RaisingNode).unlikelySuccessor(succ.firstNode())
|
||||
or
|
||||
not end_bb_likely_reachable(this) and succ = this.getASuccessor()
|
||||
}
|
||||
|
||||
/** Holds if this basic block strictly reaches the other. Is the start of other reachable from the end of this. */
|
||||
cached
|
||||
predicate strictlyReaches(BasicBlock other) {
|
||||
@@ -1113,11 +1086,6 @@ class BasicBlock extends @py_flow_node {
|
||||
/** Holds if this basic block reaches the other. Is the start of other reachable from the end of this. */
|
||||
predicate reaches(BasicBlock other) { this = other or this.strictlyReaches(other) }
|
||||
|
||||
/**
|
||||
* Whether (as inferred by type inference) this basic block is likely to be reachable.
|
||||
*/
|
||||
predicate likelyReachable() { start_bb_likely_reachable(this) }
|
||||
|
||||
/**
|
||||
* Gets the `ConditionBlock`, if any, that controls this block and
|
||||
* does not control any other `ConditionBlock`s that control this block.
|
||||
@@ -1145,26 +1113,6 @@ class BasicBlock extends @py_flow_node {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate start_bb_likely_reachable(BasicBlock b) {
|
||||
exists(Scope s | s.getEntryNode() = b.getNode(_))
|
||||
or
|
||||
exists(BasicBlock pred |
|
||||
pred = b.getAPredecessor() and
|
||||
end_bb_likely_reachable(pred) and
|
||||
not pred.getLastNode().(RaisingNode).unlikelySuccessor(b)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate end_bb_likely_reachable(BasicBlock b) {
|
||||
start_bb_likely_reachable(b) and
|
||||
not exists(ControlFlowNode p, ControlFlowNode s |
|
||||
p.(RaisingNode).unlikelySuccessor(s) and
|
||||
p = b.getNode(_) and
|
||||
s = b.getNode(_) and
|
||||
not p = b.getLastNode()
|
||||
)
|
||||
}
|
||||
|
||||
private class ControlFlowNodeAlias = ControlFlowNode;
|
||||
|
||||
final private class FinalBasicBlock = BasicBlock;
|
||||
|
||||
@@ -29,9 +29,9 @@ class FunctionMetrics extends Function {
|
||||
*/
|
||||
int getCyclomaticComplexity() {
|
||||
exists(int e, int n |
|
||||
n = count(BasicBlock b | b = this.getABasicBlock() and b.likelyReachable()) and
|
||||
n = count(BasicBlockWithPointsTo b | b = this.getABasicBlock() and b.likelyReachable()) and
|
||||
e =
|
||||
count(BasicBlock b1, BasicBlock b2 |
|
||||
count(BasicBlockWithPointsTo b1, BasicBlockWithPointsTo b2 |
|
||||
b1 = this.getABasicBlock() and
|
||||
b1.likelyReachable() and
|
||||
b2 = this.getABasicBlock() and
|
||||
|
||||
@@ -92,7 +92,7 @@ class SsaVariable extends @py_ssa_var {
|
||||
}
|
||||
|
||||
/** Gets the incoming edges for a Phi node, pruned of unlikely edges. */
|
||||
private BasicBlock getAPrunedPredecessorBlockForPhi() {
|
||||
private BasicBlockWithPointsTo getAPrunedPredecessorBlockForPhi() {
|
||||
result = this.getAPredecessorBlockForPhi() and
|
||||
not result.unlikelySuccessor(this.getDefinition().getBasicBlock())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user