diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll index 2994a910888..898cd566ab9 100644 --- a/python/ql/lib/semmle/python/Flow.qll +++ b/python/ql/lib/semmle/python/Flow.qll @@ -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 | diff --git a/python/ql/lib/semmle/python/essa/Essa.qll b/python/ql/lib/semmle/python/essa/Essa.qll index 1b83f8df6ac..384bfd2f91f 100644 --- a/python/ql/lib/semmle/python/essa/Essa.qll +++ b/python/ql/lib/semmle/python/essa/Essa.qll @@ -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`. */ diff --git a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll index b263287d05d..6c87af102fa 100644 --- a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll +++ b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll @@ -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) { diff --git a/python/ql/lib/semmle/python/types/Exceptions.qll b/python/ql/lib/semmle/python/types/Exceptions.qll index 5e982aa0134..dd9ee1703a6 100644 --- a/python/ql/lib/semmle/python/types/Exceptions.qll +++ b/python/ql/lib/semmle/python/types/Exceptions.qll @@ -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()) } diff --git a/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql b/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql index b5446dccbfc..dc1c3f2fa35 100644 --- a/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql +++ b/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql @@ -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 ( diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql index 60989ff8645..a8bc92db331 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql @@ -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() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql index 60989ff8645..a8bc92db331 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql @@ -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() diff --git a/python/ql/test/library-tests/exceptions/Handles.ql b/python/ql/test/library-tests/exceptions/Handles.ql index 60989ff8645..a8bc92db331 100644 --- a/python/ql/test/library-tests/exceptions/Handles.ql +++ b/python/ql/test/library-tests/exceptions/Handles.ql @@ -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() diff --git a/python/ql/test/library-tests/types/exceptions/Handles.ql b/python/ql/test/library-tests/types/exceptions/Handles.ql index e5a21724975..bec8767d6c5 100644 --- a/python/ql/test/library-tests/types/exceptions/Handles.ql +++ b/python/ql/test/library-tests/types/exceptions/Handles.ql @@ -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()