Python: Remove points-to dependency from parts of SSA

For whatever reason, the CFG node for exceptions and exception groups
was placed with the points-to code. (Probably because a lot of the
predicates depended on points-to.)

However, as it turned out, two of the SSA modules only depended on
non-points-to properties of these nodes, and so it was fairly
straightforward to remove the imports of `LegacyPointsTo` for those
modules.

In the process, I moved the aforementioned CFG node types into
`Flow.qll`, and changed the classes in the `Exceptions` module to the
`...WithPointsTo` form that we introduced elsewhere.
This commit is contained in:
Taus
2025-10-31 15:52:53 +00:00
parent e09840426c
commit 9dc774aaa3
9 changed files with 70 additions and 70 deletions

View File

@@ -883,6 +883,58 @@ class StarredNode extends ControlFlowNode {
ControlFlowNode getValue() { toAst(result) = toAst(this).(Starred).getValue() }
}
/** The ControlFlowNode for an 'except' statement. */
class ExceptFlowNode extends ControlFlowNode {
ExceptFlowNode() { this.getNode() instanceof ExceptStmt }
/**
* Gets the type handled by this exception handler.
* `ExceptionType` in `except ExceptionType as e:`
*/
ControlFlowNode getType() {
exists(ExceptStmt ex |
this.getBasicBlock().dominates(result.getBasicBlock()) and
ex = this.getNode() and
result = ex.getType().getAFlowNode()
)
}
/**
* Gets the name assigned to the handled exception, if any.
* `e` in `except ExceptionType as e:`
*/
ControlFlowNode getName() {
exists(ExceptStmt ex |
this.getBasicBlock().dominates(result.getBasicBlock()) and
ex = this.getNode() and
result = ex.getName().getAFlowNode()
)
}
}
/** The ControlFlowNode for an 'except*' statement. */
class ExceptGroupFlowNode extends ControlFlowNode {
ExceptGroupFlowNode() { this.getNode() instanceof ExceptGroupStmt }
/**
* Gets the type handled by this exception handler.
* `ExceptionType` in `except* ExceptionType as e:`
*/
ControlFlowNode getType() {
this.getBasicBlock().dominates(result.getBasicBlock()) and
result = this.getNode().(ExceptGroupStmt).getType().getAFlowNode()
}
/**
* Gets the name assigned to the handled exception, if any.
* `e` in `except* ExceptionType as e:`
*/
ControlFlowNode getName() {
this.getBasicBlock().dominates(result.getBasicBlock()) and
result = this.getNode().(ExceptGroupStmt).getName().getAFlowNode()
}
}
private module Scopes {
private predicate fast_local(NameNode n) {
exists(FastLocalVariable v |

View File

@@ -6,7 +6,6 @@ import python
private import SsaCompute
import semmle.python.essa.Definitions
private import semmle.python.internal.CachedStages
private import LegacyPointsTo
private import semmle.python.essa.SsaDefinitions
/** An (enhanced) SSA variable derived from `SsaSourceVariable`. */

View File

@@ -5,7 +5,6 @@
import python
private import semmle.python.internal.CachedStages
private import LegacyPointsTo
/** Hold if `expr` is a test (a branch) and `use` is within that test */
predicate test_contains(ControlFlowNode expr, ControlFlowNode use) {

View File

@@ -80,7 +80,7 @@ class RaisingNode extends ControlFlowNode {
or
this.getNode() instanceof Print and result = theIOErrorType()
or
exists(ExceptFlowNode except |
exists(ExceptFlowNodeWithPointsTo except |
except = this.getAnExceptionalSuccessor() and
except.handles_objectapi(result) and
result = this.innateException_objectapi()
@@ -107,7 +107,7 @@ class RaisingNode extends ControlFlowNode {
or
this.getNode() instanceof Print and result = ClassValue::ioError()
or
exists(ExceptFlowNode except |
exists(ExceptFlowNodeWithPointsTo except |
except = this.getAnExceptionalSuccessor() and
except.handles(result) and
result = this.innateException()
@@ -200,8 +200,8 @@ class RaisingNode extends ControlFlowNode {
succ = this.getAnExceptionalSuccessor() and
(
/* An 'except' that handles raised and there is no more previous handler */
succ.(ExceptFlowNode).handles_objectapi(raised) and
not exists(ExceptFlowNode other, StmtList s, int i, int j |
succ.(ExceptFlowNodeWithPointsTo).handles_objectapi(raised) and
not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j |
not other = succ and
other.handles_objectapi(raised) and
s.getItem(i) = succ.getNode() and
@@ -211,7 +211,7 @@ class RaisingNode extends ControlFlowNode {
)
or
/* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */
not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles_objectapi(raised) and
not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles_objectapi(raised) and
not succ instanceof ExceptFlowNode
)
}
@@ -223,8 +223,8 @@ class RaisingNode extends ControlFlowNode {
succ = this.getAnExceptionalSuccessor() and
(
/* An 'except' that handles raised and there is no more previous handler */
succ.(ExceptFlowNode).handles(raised) and
not exists(ExceptFlowNode other, StmtList s, int i, int j |
succ.(ExceptFlowNodeWithPointsTo).handles(raised) and
not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j |
not other = succ and
other.handles(raised) and
s.getItem(i) = succ.getNode() and
@@ -234,7 +234,7 @@ class RaisingNode extends ControlFlowNode {
)
or
/* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */
not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised) and
not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles(raised) and
not succ instanceof ExceptFlowNode
)
}
@@ -248,7 +248,7 @@ class RaisingNode extends ControlFlowNode {
raised.isLegalExceptionType() and
raised = this.getARaisedType_objectapi() and
this.isExceptionalExit(s) and
not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles_objectapi(raised)
not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles_objectapi(raised)
}
/**
@@ -260,7 +260,7 @@ class RaisingNode extends ControlFlowNode {
raised.isLegalExceptionType() and
raised = this.getARaisedType() and
this.isExceptionalExit(s) and
not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised)
not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles(raised)
}
}
@@ -368,36 +368,9 @@ predicate scope_raises_unknown(Scope s) {
)
}
/** The ControlFlowNode for an 'except' statement. */
class ExceptFlowNode extends ControlFlowNode {
ExceptFlowNode() { this.getNode() instanceof ExceptStmt }
/**
* Gets the type handled by this exception handler.
* `ExceptionType` in `except ExceptionType as e:`
*/
ControlFlowNodeWithPointsTo getType() {
exists(ExceptStmt ex |
this.getBasicBlock().dominates(result.getBasicBlock()) and
ex = this.getNode() and
result = ex.getType().getAFlowNode()
)
}
/**
* Gets the name assigned to the handled exception, if any.
* `e` in `except ExceptionType as e:`
*/
ControlFlowNode getName() {
exists(ExceptStmt ex |
this.getBasicBlock().dominates(result.getBasicBlock()) and
ex = this.getNode() and
result = ex.getName().getAFlowNode()
)
}
class ExceptFlowNodeWithPointsTo extends ExceptFlowNode {
private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) {
this.getType().refersTo(obj, cls, origin)
this.getType().(ControlFlowNodeWithPointsTo).refersTo(obj, cls, origin)
or
exists(Object tup | this.handledObject_objectapi(tup, theTupleType(), _) |
element_from_tuple_objectapi(tup).refersTo(obj, cls, origin)
@@ -407,7 +380,7 @@ class ExceptFlowNode extends ControlFlowNode {
private predicate handledObject(Value val, ClassValue cls, ControlFlowNode origin) {
val.getClass() = cls and
(
this.getType().pointsTo(val, origin)
this.getType().(ControlFlowNodeWithPointsTo).pointsTo(val, origin)
or
exists(TupleValue tup | this.handledObject(tup, ClassValue::tuple(), _) |
val = tup.getItem(_) and origin = val.getOrigin()
@@ -452,29 +425,6 @@ class ExceptFlowNode extends ControlFlowNode {
}
}
/** The ControlFlowNode for an 'except*' statement. */
class ExceptGroupFlowNode extends ControlFlowNode {
ExceptGroupFlowNode() { this.getNode() instanceof ExceptGroupStmt }
/**
* Gets the type handled by this exception handler.
* `ExceptionType` in `except* ExceptionType as e:`
*/
ControlFlowNode getType() {
this.getBasicBlock().dominates(result.getBasicBlock()) and
result = this.getNode().(ExceptGroupStmt).getType().getAFlowNode()
}
/**
* Gets the name assigned to the handled exception, if any.
* `e` in `except* ExceptionType as e:`
*/
ControlFlowNode getName() {
this.getBasicBlock().dominates(result.getBasicBlock()) and
result = this.getNode().(ExceptGroupStmt).getName().getAFlowNode()
}
}
private ControlFlowNodeWithPointsTo element_from_tuple_objectapi(Object tuple) {
exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode())
}

View File

@@ -14,7 +14,7 @@
import python
private import LegacyPointsTo
from ExceptFlowNode ex, Value t, ClassValue c, ControlFlowNode origin, string what
from ExceptFlowNodeWithPointsTo ex, Value t, ClassValue c, ControlFlowNode origin, string what
where
ex.handledException(t, c, origin) and
(

View File

@@ -1,6 +1,6 @@
import python
private import LegacyPointsTo
from ExceptFlowNode ex, Value val
from ExceptFlowNodeWithPointsTo ex, Value val
where ex.handledException(val, _, _)
select ex.getLocation().getStartLine(), ex.toString(), val.toString()

View File

@@ -1,6 +1,6 @@
import python
private import LegacyPointsTo
from ExceptFlowNode ex, Value val
from ExceptFlowNodeWithPointsTo ex, Value val
where ex.handledException(val, _, _)
select ex.getLocation().getStartLine(), ex.toString(), val.toString()

View File

@@ -1,6 +1,6 @@
import python
private import LegacyPointsTo
from ExceptFlowNode ex, Value val
from ExceptFlowNodeWithPointsTo ex, Value val
where ex.handledException(val, _, _)
select ex.getLocation().getStartLine(), ex.toString(), val.toString()

View File

@@ -1,6 +1,6 @@
import python
private import LegacyPointsTo
from ExceptFlowNode n, ClassObject cls
from ExceptFlowNodeWithPointsTo n, ClassObject cls
where n.handles_objectapi(cls)
select n.getLocation().getStartLine(), cls.toString()