@@ -285,6 +285,50 @@ private module Exceptions {
285285 )
286286 }
287287
288+ /**
289+ * Holds if a catch clause of `try` catches checked exceptions of type
290+ * `caught`, and that `call` is contained within the try block.
291+ */
292+ private predicate checkedExceptionFromCatchCandidate ( TryStmt try , RefType caught , Call call ) {
293+ (
294+ call .getEnclosingStmt ( ) .getEnclosingStmt + ( ) = try .getBlock ( ) or
295+ call .( Expr ) .getParent * ( ) = try .getAResource ( )
296+ ) and
297+ try .getACatchClause ( ) .getACaughtType ( ) = caught and
298+ not caught instanceof UncheckedThrowableSuperType
299+ }
300+
301+ /**
302+ * Holds if a catch clause of `try` catches checked exceptions of type
303+ * `caught`, and that there is a call within the try block that declares that
304+ * it may throw `caught` or a subtype thereof.
305+ */
306+ private predicate declaredCheckedExceptionFromCatchCandidate ( TryStmt try , RefType caught ) {
307+ exists ( Call call |
308+ checkedExceptionFromCatchCandidate ( try , caught , call ) and
309+ call .getCallee ( ) .getAThrownExceptionType ( ) .getASourceSupertype * ( ) = caught
310+ )
311+ }
312+
313+ /**
314+ * Holds if `call` is contained within a try block that has a catch clause
315+ * that catches a checked exception, but there is no call within the try
316+ * block that declares that it may throw that exception, and no throw
317+ * statement either. In this case, it is likely that the throws declaration
318+ * for some reason was not extracted, so we conseratively assume that `call`
319+ * may throw such an exception.
320+ */
321+ private predicate checkedExceptionFromCatchCandidate ( Call call ) {
322+ exists ( TryStmt try , RefType caught |
323+ checkedExceptionFromCatchCandidate ( try , caught , call ) and
324+ not declaredCheckedExceptionFromCatchCandidate ( try , caught ) and
325+ not exists ( ThrowStmt throwstmt |
326+ throwstmt .getEnclosingStmt + ( ) = try .getBlock ( ) and
327+ throwstmt .getThrownExceptionType ( ) .getASourceSupertype * ( ) = caught
328+ )
329+ )
330+ }
331+
288332 /**
289333 * Holds if `n` is expected to possibly throw an exception. This can either
290334 * be due to a declared (likely checked) exception on a call target
@@ -293,6 +337,8 @@ private module Exceptions {
293337 predicate mayThrow ( Ast:: AstNode n ) {
294338 exists ( n .( Call ) .getCallee ( ) .getAThrownExceptionType ( ) )
295339 or
340+ checkedExceptionFromCatchCandidate ( n )
341+ or
296342 uncheckedExceptionFromMethod ( n )
297343 or
298344 uncheckedExceptionFromFinally ( n )
0 commit comments