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() } 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 module Scopes {
private predicate fast_local(NameNode n) { private predicate fast_local(NameNode n) {
exists(FastLocalVariable v | exists(FastLocalVariable v |

View File

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

View File

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

View File

@@ -80,7 +80,7 @@ class RaisingNode extends ControlFlowNode {
or or
this.getNode() instanceof Print and result = theIOErrorType() this.getNode() instanceof Print and result = theIOErrorType()
or or
exists(ExceptFlowNode except | exists(ExceptFlowNodeWithPointsTo except |
except = this.getAnExceptionalSuccessor() and except = this.getAnExceptionalSuccessor() and
except.handles_objectapi(result) and except.handles_objectapi(result) and
result = this.innateException_objectapi() result = this.innateException_objectapi()
@@ -107,7 +107,7 @@ class RaisingNode extends ControlFlowNode {
or or
this.getNode() instanceof Print and result = ClassValue::ioError() this.getNode() instanceof Print and result = ClassValue::ioError()
or or
exists(ExceptFlowNode except | exists(ExceptFlowNodeWithPointsTo except |
except = this.getAnExceptionalSuccessor() and except = this.getAnExceptionalSuccessor() and
except.handles(result) and except.handles(result) and
result = this.innateException() result = this.innateException()
@@ -200,8 +200,8 @@ class RaisingNode extends ControlFlowNode {
succ = this.getAnExceptionalSuccessor() and succ = this.getAnExceptionalSuccessor() and
( (
/* An 'except' that handles raised and there is no more previous handler */ /* An 'except' that handles raised and there is no more previous handler */
succ.(ExceptFlowNode).handles_objectapi(raised) and succ.(ExceptFlowNodeWithPointsTo).handles_objectapi(raised) and
not exists(ExceptFlowNode other, StmtList s, int i, int j | not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j |
not other = succ and not other = succ and
other.handles_objectapi(raised) and other.handles_objectapi(raised) and
s.getItem(i) = succ.getNode() and s.getItem(i) = succ.getNode() and
@@ -211,7 +211,7 @@ class RaisingNode extends ControlFlowNode {
) )
or or
/* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */ /* 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 not succ instanceof ExceptFlowNode
) )
} }
@@ -223,8 +223,8 @@ class RaisingNode extends ControlFlowNode {
succ = this.getAnExceptionalSuccessor() and succ = this.getAnExceptionalSuccessor() and
( (
/* An 'except' that handles raised and there is no more previous handler */ /* An 'except' that handles raised and there is no more previous handler */
succ.(ExceptFlowNode).handles(raised) and succ.(ExceptFlowNodeWithPointsTo).handles(raised) and
not exists(ExceptFlowNode other, StmtList s, int i, int j | not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j |
not other = succ and not other = succ and
other.handles(raised) and other.handles(raised) and
s.getItem(i) = succ.getNode() and s.getItem(i) = succ.getNode() and
@@ -234,7 +234,7 @@ class RaisingNode extends ControlFlowNode {
) )
or or
/* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */ /* 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 not succ instanceof ExceptFlowNode
) )
} }
@@ -248,7 +248,7 @@ class RaisingNode extends ControlFlowNode {
raised.isLegalExceptionType() and raised.isLegalExceptionType() and
raised = this.getARaisedType_objectapi() and raised = this.getARaisedType_objectapi() and
this.isExceptionalExit(s) 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.isLegalExceptionType() and
raised = this.getARaisedType() and raised = this.getARaisedType() and
this.isExceptionalExit(s) 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 ExceptFlowNodeWithPointsTo extends ExceptFlowNode {
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()
)
}
private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) { private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) {
this.getType().refersTo(obj, cls, origin) this.getType().(ControlFlowNodeWithPointsTo).refersTo(obj, cls, origin)
or or
exists(Object tup | this.handledObject_objectapi(tup, theTupleType(), _) | exists(Object tup | this.handledObject_objectapi(tup, theTupleType(), _) |
element_from_tuple_objectapi(tup).refersTo(obj, cls, origin) 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) { private predicate handledObject(Value val, ClassValue cls, ControlFlowNode origin) {
val.getClass() = cls and val.getClass() = cls and
( (
this.getType().pointsTo(val, origin) this.getType().(ControlFlowNodeWithPointsTo).pointsTo(val, origin)
or or
exists(TupleValue tup | this.handledObject(tup, ClassValue::tuple(), _) | exists(TupleValue tup | this.handledObject(tup, ClassValue::tuple(), _) |
val = tup.getItem(_) and origin = val.getOrigin() 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) { private ControlFlowNodeWithPointsTo element_from_tuple_objectapi(Object tuple) {
exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode()) exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode())
} }

View File

@@ -14,7 +14,7 @@
import python import python
private import LegacyPointsTo 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 where
ex.handledException(t, c, origin) and ex.handledException(t, c, origin) and
( (

View File

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

View File

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

View File

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

View File

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