Promote IncorrectExceptOrder.

However, we lose some results due to not considering builtin/stdlib types.
This commit is contained in:
Joe Farebrother
2025-07-17 11:08:56 +01:00
parent 963e028645
commit e42002e1d7
2 changed files with 19 additions and 14 deletions

View File

@@ -25,11 +25,11 @@ is a super class of <code>Error</code>.
<p>Reorganize the <code>except</code> blocks so that the more specific <code>except</code>
is defined first. Alternatively, if the more specific <code>except</code> block is
no longer required then it should be deleted.</p>
no longer required, then it should be deleted.</p>
</recommendation>
<example>
<p>In this example the <code>except Exception:</code> will handle <code>AttributeError</code> preventing the
<p>In the following example, the <code>except Exception:</code> will handle <code>AttributeError</code> preventing the
subsequent handler from ever executing.</p>
<sample src="IncorrectExceptOrder.py" />
@@ -37,8 +37,8 @@ subsequent handler from ever executing.</p>
</example>
<references>
<li>Python Language Reference: <a href="http://docs.python.org/2.7/reference/compound_stmts.html#try">The try statement</a>,
<a href="http://docs.python.org/2.7/reference/executionmodel.html#exceptions">Exceptions</a>.</li>
<li>Python Language Reference: <a href="http://docs.python.org/3/reference/compound_stmts.html#try">The try statement</a>,
<a href="http://docs.python.org/3/reference/executionmodel.html#exceptions">Exceptions</a>.</li>
</references>

View File

@@ -14,22 +14,27 @@
*/
import python
import semmle.python.dataflow.new.internal.DataFlowDispatch
predicate incorrect_except_order(ExceptStmt ex1, ClassValue cls1, ExceptStmt ex2, ClassValue cls2) {
predicate incorrectExceptOrder(ExceptStmt ex1, Class cls1, ExceptStmt ex2, Class cls2) {
exists(int i, int j, Try t |
ex1 = t.getHandler(i) and
ex2 = t.getHandler(j) and
i < j and
cls1 = except_class(ex1) and
cls2 = except_class(ex2) and
cls1 = cls2.getASuperType()
cls1 = exceptClass(ex1) and
cls2 = exceptClass(ex2) and
cls1 = getADirectSuperclass*(cls2)
)
}
ClassValue except_class(ExceptStmt ex) { ex.getType().pointsTo(result) }
Class exceptClass(ExceptStmt ex) { ex.getType() = classTracker(result).asExpr() }
from ExceptStmt ex1, ClassValue cls1, ExceptStmt ex2, ClassValue cls2
where incorrect_except_order(ex1, cls1, ex2, cls2)
select ex2,
"Except block for $@ is unreachable; the more general $@ for $@ will always be executed in preference.",
cls2, cls2.getName(), ex1, "except block", cls1, cls1.getName()
from ExceptStmt ex1, Class cls1, ExceptStmt ex2, Class cls2, string msg
where
incorrectExceptOrder(ex1, cls1, ex2, cls2) and
if cls1 = cls2
then msg = "This except block handling $@ is unreachable; as $@ also handles $@."
else
msg =
"This except block handling $@ is unreachable; as $@ for the more general $@ always subsumes it."
select ex2, msg, cls2, cls2.getName(), ex1, "this except block", cls1, cls1.getName()