Skip to content

Commit f5361f4

Browse files
committed
Python: Move exception modelling to DataFlowDispatch.qll
This analysis will is needed for the reachability modelling (which tracks things like which exceptions are caught by which handles), so it makes more sense for it to move to `DataFlowDispatch` for now.
1 parent f6cd63f commit f5361f4

File tree

2 files changed

+111
-68
lines changed

2 files changed

+111
-68
lines changed

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

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,3 +2135,113 @@ module DuckTyping {
21352135
f.getADecorator().(Name).getId() = "property"
21362136
}
21372137
}
2138+
2139+
/**
2140+
* Provides a class hierarchy for exception types, covering both builtin
2141+
* exceptions (from typeshed models) and user-defined exception classes.
2142+
*/
2143+
module ExceptionTypes {
2144+
private import semmle.python.ApiGraphs
2145+
private import semmle.python.frameworks.data.internal.ApiGraphModels
2146+
2147+
/** Holds if `name` is a builtin exception class name. */
2148+
predicate builtinException(string name) {
2149+
typeModel("builtins.BaseException~Subclass", "builtins." + name, "")
2150+
}
2151+
2152+
/** Holds if builtin exception `sub` is a direct subclass of builtin exception `base`. */
2153+
private predicate builtinExceptionSubclass(string base, string sub) {
2154+
typeModel("builtins." + base + "~Subclass", "builtins." + sub, "")
2155+
}
2156+
2157+
/** An exception type, either a builtin exception or a user-defined exception class. */
2158+
newtype TExceptType =
2159+
/** A user-defined exception class. */
2160+
TUserExceptType(Class c) or
2161+
/** A builtin exception class, identified by name. */
2162+
TBuiltinExceptType(string name) { builtinException(name) }
2163+
2164+
/** An exception type, either a builtin exception or a user-defined exception class. */
2165+
class ExceptType extends TExceptType {
2166+
/** Gets the name of this exception type. */
2167+
string getName() { none() }
2168+
2169+
/** Gets a data-flow node that refers to this exception type. */
2170+
DataFlow::Node getAUse() { none() }
2171+
2172+
/** Gets a direct superclass of this exception type. */
2173+
ExceptType getADirectSuperclass() { none() }
2174+
2175+
/** Gets a string representation of this exception type. */
2176+
string toString() { result = this.getName() }
2177+
2178+
/**
2179+
* Holds if this element is at the specified location.
2180+
* The location spans column `startColumn` of line `startLine` to
2181+
* column `endColumn` of line `endLine` in file `filepath`.
2182+
* For more information, see
2183+
* [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
2184+
*/
2185+
predicate hasLocationInfo(
2186+
string filePath, int startLine, int startColumn, int endLine, int endColumn
2187+
) {
2188+
none()
2189+
}
2190+
}
2191+
2192+
/** A user-defined exception class. */
2193+
class UserExceptType extends ExceptType, TUserExceptType {
2194+
Class cls;
2195+
2196+
UserExceptType() { this = TUserExceptType(cls) }
2197+
2198+
/** Gets the underlying class. */
2199+
Class asClass() { result = cls }
2200+
2201+
override string getName() { result = cls.getName() }
2202+
2203+
override DataFlow::Node getAUse() { result = classTracker(cls) }
2204+
2205+
override ExceptType getADirectSuperclass() {
2206+
result.(UserExceptType).asClass() = getADirectSuperclass(cls)
2207+
or
2208+
result.(BuiltinExceptType).getAUse().asExpr() = cls.getABase()
2209+
}
2210+
2211+
override predicate hasLocationInfo(
2212+
string filePath, int startLine, int startColumn, int endLine, int endColumn
2213+
) {
2214+
cls.getLocation().hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn)
2215+
}
2216+
}
2217+
2218+
/** A builtin exception class, identified by name. */
2219+
class BuiltinExceptType extends ExceptType, TBuiltinExceptType {
2220+
string name;
2221+
2222+
BuiltinExceptType() { this = TBuiltinExceptType(name) }
2223+
2224+
/** Gets the builtin name. */
2225+
string asBuiltinName() { result = name }
2226+
2227+
override string getName() { result = name }
2228+
2229+
override DataFlow::Node getAUse() { API::builtin(name).asSource().flowsTo(result) }
2230+
2231+
override ExceptType getADirectSuperclass() {
2232+
builtinExceptionSubclass(result.(BuiltinExceptType).asBuiltinName(), name) and
2233+
result != this
2234+
}
2235+
2236+
override predicate hasLocationInfo(
2237+
string filePath, int startLine, int startColumn, int endLine, int endColumn
2238+
) {
2239+
filePath = "" and
2240+
startLine = 0 and
2241+
startColumn = 0 and
2242+
endLine = 0 and
2243+
endColumn = 0
2244+
}
2245+
}
2246+
}
2247+

python/ql/src/Exceptions/IncorrectExceptOrder.ql

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -15,74 +15,7 @@
1515

1616
import python
1717
import semmle.python.dataflow.new.internal.DataFlowDispatch
18-
import semmle.python.ApiGraphs
19-
import semmle.python.frameworks.data.internal.ApiGraphModels
20-
21-
predicate builtinException(string name) {
22-
typeModel("builtins.BaseException~Subclass", "builtins." + name, "")
23-
}
24-
25-
predicate builtinExceptionSubclass(string base, string sub) {
26-
typeModel("builtins." + base + "~Subclass", "builtins." + sub, "")
27-
}
28-
29-
newtype TExceptType =
30-
TClass(Class c) or
31-
TBuiltin(string name) { builtinException(name) }
32-
33-
class ExceptType extends TExceptType {
34-
Class asClass() { this = TClass(result) }
35-
36-
string asBuiltinName() { this = TBuiltin(result) }
37-
38-
predicate isBuiltin() { this = TBuiltin(_) }
39-
40-
string getName() {
41-
result = this.asClass().getName()
42-
or
43-
result = this.asBuiltinName()
44-
}
45-
46-
string toString() { result = this.getName() }
47-
48-
DataFlow::Node getAUse() {
49-
result = classTracker(this.asClass())
50-
or
51-
API::builtin(this.asBuiltinName()).asSource().flowsTo(result)
52-
}
53-
54-
ExceptType getADirectSuperclass() {
55-
result.asClass() = getADirectSuperclass(this.asClass())
56-
or
57-
result.isBuiltin() and
58-
result.getAUse().asExpr() = this.asClass().getABase()
59-
or
60-
builtinExceptionSubclass(result.asBuiltinName(), this.asBuiltinName()) and
61-
this != result
62-
}
63-
64-
/**
65-
* Holds if this element is at the specified location.
66-
* The location spans column `startColumn` of line `startLine` to
67-
* column `endColumn` of line `endLine` in file `filepath`.
68-
* For more information, see
69-
* [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
70-
*/
71-
predicate hasLocationInfo(
72-
string filePath, int startLine, int startColumn, int endLine, int endColumn
73-
) {
74-
this.asClass()
75-
.getLocation()
76-
.hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn)
77-
or
78-
this.isBuiltin() and
79-
filePath = "" and
80-
startLine = 0 and
81-
startColumn = 0 and
82-
endLine = 0 and
83-
endColumn = 0
84-
}
85-
}
18+
private import ExceptionTypes
8619

8720
predicate incorrectExceptOrder(ExceptStmt ex1, ExceptType cls1, ExceptStmt ex2, ExceptType cls2) {
8821
exists(int i, int j, Try t |

0 commit comments

Comments
 (0)