Skip to content

Commit 862a996

Browse files
committed
Python: Extend ExceptionTypes API
Adds support for finding instances, and adds a `BaseException` convenience class.
1 parent 94a0e02 commit 862a996

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,12 +2199,27 @@ module ExceptionTypes {
21992199
/** Gets a string representation of this exception type. */
22002200
string toString() { result = this.getName() }
22012201

2202-
/** Holds if this exception type may be raised at control flow node `r`. */
2203-
predicate isRaisedAt(ControlFlowNode r) {
2204-
exists(Expr raised |
2205-
raised = r.getNode().(Raise).getRaised() and
2202+
/** Gets a data-flow node that refers to an instance of this exception type. */
2203+
DataFlow::Node getAnInstance() { none() }
2204+
2205+
/** Holds if this is a legal exception type (a subclass of `BaseException`). */
2206+
predicate isLegalExceptionType() { this.getADirectSuperclass*() instanceof BaseException }
2207+
2208+
/**
2209+
* Holds if this exception type is raised by `r`, either as a class reference
2210+
* (e.g. `raise ValueError`) or as an instantiation (e.g. `raise ValueError("msg")`).
2211+
*/
2212+
predicate isRaisedBy(Raise r) {
2213+
exists(Expr raised | raised = r.getRaised() |
22062214
this.getAUse().asExpr() in [raised, raised.(Call).getFunc()]
2215+
or
2216+
this.getAnInstance().asExpr() = raised
22072217
)
2218+
}
2219+
2220+
/** Holds if this exception type may be raised at control flow node `r`. */
2221+
predicate isRaisedAt(ControlFlowNode r) {
2222+
this.isRaisedBy(r.getNode())
22082223
or
22092224
exists(Function callee |
22102225
resolveCall(r, callee, _) and
@@ -2231,7 +2246,7 @@ module ExceptionTypes {
22312246
or
22322247
// A bare `except:` handles everything
22332248
not exists(handler.getNode().(ExceptStmt).getType()) and
2234-
this.(BuiltinExceptType).getName() = "BaseException"
2249+
this instanceof BaseException
22352250
}
22362251

22372252
/**
@@ -2261,6 +2276,8 @@ module ExceptionTypes {
22612276

22622277
override DataFlow::Node getAUse() { result = classTracker(cls) }
22632278

2279+
override DataFlow::Node getAnInstance() { result = classInstanceTracker(cls) }
2280+
22642281
override ExceptType getADirectSuperclass() {
22652282
result.(UserExceptType).asClass() = getADirectSuperclass(cls)
22662283
or
@@ -2285,7 +2302,11 @@ module ExceptionTypes {
22852302

22862303
override string getName() { result = name }
22872304

2288-
override DataFlow::Node getAUse() { API::builtin(name).asSource().flowsTo(result) }
2305+
override DataFlow::Node getAUse() { result = API::builtin(name).getAValueReachableFromSource() }
2306+
2307+
override DataFlow::Node getAnInstance() {
2308+
result = API::builtin(name).getAnInstance().getAValueReachableFromSource()
2309+
}
22892310

22902311
override ExceptType getADirectSuperclass() {
22912312
builtinExceptionSubclass(result.(BuiltinExceptType).asBuiltinName(), name) and
@@ -2303,6 +2324,11 @@ module ExceptionTypes {
23032324
}
23042325
}
23052326

2327+
/** The builtin `BaseException` type. */
2328+
class BaseException extends BuiltinExceptType {
2329+
BaseException() { name = "BaseException" }
2330+
}
2331+
23062332
/**
23072333
* Holds if the exception edge from `r` to `handler` is unlikely because
23082334
* none of the exception types that `r` may raise are handled by `handler`.

0 commit comments

Comments
 (0)