Skip to content

Commit ca26fee

Browse files
authored
Merge pull request github#2978 from BekaValentine/python-objectapi-to-valueapi-illegalexceptionhandlertype
Python: ObjectAPI to ValueAPI: IllegalExceptionHandlerType
2 parents 84a74f4 + a7a6495 commit ca26fee

File tree

6 files changed

+54
-25
lines changed

6 files changed

+54
-25
lines changed

python/ql/src/Exceptions/IllegalExceptionHandlerType.ql

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@
1313

1414
import python
1515

16-
from ExceptFlowNode ex, Object t, ClassObject c, ControlFlowNode origin, string what
17-
where ex.handledException(t, c, origin) and
18-
(
19-
exists(ClassObject x | x = t |
20-
not x.isLegalExceptionType() and
21-
not x.failedInference() and
22-
what = "class '" + x.getName() + "'"
23-
)
24-
or
25-
not t instanceof ClassObject and
26-
what = "instance of '" + c.getName() + "'"
27-
)
28-
29-
select ex.getNode(), "Non-exception $@ in exception handler which will never match raised exception.", origin, what
30-
16+
from ExceptFlowNode ex, Value t, ClassValue c, ControlFlowNode origin, string what
17+
where
18+
ex.handledException(t, c, origin) and
19+
(
20+
exists(ClassValue x | x = t |
21+
not x.isLegalExceptionType() and
22+
not x.failedInference(_) and
23+
what = "class '" + x.getName() + "'"
24+
)
25+
or
26+
not t instanceof ClassValue and
27+
what = "instance of '" + c.getName() + "'"
28+
)
29+
select ex.getNode(),
30+
"Non-exception $@ in exception handler which will never match raised exception.", origin, what

python/ql/src/semmle/python/objects/ObjectAPI.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ class Value extends TObject {
4444
PointsToInternal::pointsTo(result, _, this, _)
4545
}
4646

47+
/** Gets the origin CFG node for this value. */
48+
ControlFlowNode getOrigin() {
49+
result = this.(ObjectInternal).getOrigin()
50+
}
51+
52+
4753
/** Gets the class of this object.
4854
* Strictly, the `Value` representing the class of the objects
4955
* represented by this Value.

python/ql/src/semmle/python/types/Exceptions.qll

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -260,35 +260,58 @@ class ExceptFlowNode extends ControlFlowNode {
260260
)
261261
}
262262

263-
private predicate handledObject(Object obj, ClassObject cls, ControlFlowNode origin) {
263+
private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) {
264264
this.getType().refersTo(obj, cls, origin)
265265
or
266266
exists(Object tup |
267-
this.handledObject(tup, theTupleType(), _) |
268-
element_from_tuple(tup).refersTo(obj, cls, origin)
267+
this.handledObject_objectapi(tup, theTupleType(), _) |
268+
element_from_tuple_objectapi(tup).refersTo(obj, cls, origin)
269+
)
270+
}
271+
272+
private predicate handledObject(Value val, ClassValue cls, ControlFlowNode origin) {
273+
val.getClass() = cls and
274+
(
275+
this.getType().pointsTo(val, origin)
276+
or
277+
exists(TupleValue tup |
278+
this.handledObject(tup, ClassValue::tuple(), _) |
279+
val = tup.getItem(_) and origin = val.getOrigin()
280+
)
269281
)
270282
}
271283

272284
/** Gets the inferred type(s) that are handled by this node, splitting tuples if possible. */
273285
pragma [noinline]
274-
predicate handledException(Object obj, ClassObject cls, ControlFlowNode origin) {
275-
this.handledObject(obj, cls, origin) and not cls = theTupleType()
286+
predicate handledException_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) {
287+
this.handledObject_objectapi(obj, cls, origin) and not cls = theTupleType()
276288
or
277289
not exists(this.getNode().(ExceptStmt).getType()) and obj = theBaseExceptionType() and cls = theTypeType() and
278290
origin = this
279291
}
292+
293+
/** Gets the inferred type(s) that are handled by this node, splitting tuples if possible. */
294+
pragma [noinline]
295+
predicate handledException(Value val, ClassValue cls, ControlFlowNode origin) {
296+
this.handledObject(val, cls, origin) and not cls = ClassValue::tuple()
297+
or
298+
not exists(this.getNode().(ExceptStmt).getType()) and val = ClassValue::baseException() and cls = ClassValue::type() and
299+
origin = this
300+
}
301+
302+
280303

281304
/** Whether this `except` handles `cls` */
282305
predicate handles(ClassObject cls) {
283306
exists(ClassObject handled |
284-
this.handledException(handled, _, _) |
307+
this.handledException_objectapi(handled, _, _) |
285308
cls.getAnImproperSuperType() = handled
286309
)
287310
}
288311

289312
}
290313

291-
private ControlFlowNode element_from_tuple(Object tuple) {
314+
private ControlFlowNode element_from_tuple_objectapi(Object tuple) {
292315
exists(Tuple t |
293316
t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode()
294317
)

python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
import python
33

44
from ExceptFlowNode ex, Object obj
5-
where ex.handledException(obj, _, _)
5+
where ex.handledException_objectapi(obj, _, _)
66
select ex.getLocation().getStartLine(), ex.toString(), obj.toString()

python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
import python
33

44
from ExceptFlowNode ex, Object obj
5-
where ex.handledException(obj, _, _)
5+
where ex.handledException_objectapi(obj, _, _)
66
select ex.getLocation().getStartLine(), ex.toString(), obj.toString()
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import python
22

33
from ExceptFlowNode ex, Object t
4-
where ex.handledException(t, _, _)
4+
where ex.handledException_objectapi(t, _, _)
55
select ex.getLocation().getStartLine(), ex.toString(), t.toString()

0 commit comments

Comments
 (0)