diff --git a/python/ql/src/Exceptions/IllegalRaise.ql b/python/ql/src/Exceptions/IllegalRaise.ql index 673289b9e975..da1bc56ae336 100644 --- a/python/ql/src/Exceptions/IllegalRaise.ql +++ b/python/ql/src/Exceptions/IllegalRaise.ql @@ -15,7 +15,7 @@ import python import Raising import Exceptions.NotImplemented -from Raise r, ClassObject t -where type_or_typeof(r, t, _) and not t.isLegalExceptionType() and not t.failedInference() and not use_of_not_implemented_in_raise(r, _) +from Raise r, ClassValue t +where type_or_typeof(r, t, _) and not t.isLegalExceptionType() and not t.failedInference(_) and not use_of_not_implemented_in_raise(r, _) select r, "Illegal class '" + t.getName() + "' raised; will result in a TypeError being raised instead." diff --git a/python/ql/src/Exceptions/Raising.qll b/python/ql/src/Exceptions/Raising.qll index b820bfa24e9c..7e53c0bbd271 100644 --- a/python/ql/src/Exceptions/Raising.qll +++ b/python/ql/src/Exceptions/Raising.qll @@ -1,14 +1,16 @@ import python /** Whether the raise statement 'r' raises 'type' from origin 'orig' */ -predicate type_or_typeof(Raise r, ClassObject type, AstNode orig) { +predicate type_or_typeof(Raise r, ClassValue type, AstNode orig) { exists(Expr exception | exception = r.getRaised() | - exception.refersTo(type, _, orig) + exception.pointsTo(type, orig) or - not exists(ClassObject exc_type | exception.refersTo(exc_type)) and - not type = theTypeType() and // First value is an unknown exception type - exception.refersTo(_, type, orig) + not exists(ClassValue exc_type | exception.pointsTo(exc_type)) and + not type = ClassValue::type() and // First value is an unknown exception type + exists(Value val | exception.pointsTo(val, orig) | + val.getClass() = type + ) ) } diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 1f1f7001da1c..49087648c523 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -481,6 +481,15 @@ class ClassValue extends Value { predicate declaresAttribute(string name) { this.(ClassObjectInternal).getClassDeclaration().declaresAttribute(name) } + + /** Whether this class is a legal exception class. + * What constitutes a legal exception class differs between major versions */ + predicate isLegalExceptionType() { + not this.isNewStyle() or + this.getASuperType() = ClassValue::baseException() + or + major_version() = 2 and this = ClassValue::tuple() + } }