@@ -285,6 +285,45 @@ 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. In this case, it is
317+ * likely that the throws declaration for some reason was not extracted, so
318+ * we conseratively assume that `call` may throw such an exception.
319+ */
320+ private predicate checkedExceptionFromCatchCandidate ( Call call ) {
321+ exists ( TryStmt try , RefType caught |
322+ checkedExceptionFromCatchCandidate ( try , caught , call ) and
323+ not declaredCheckedExceptionFromCatchCandidate ( try , caught )
324+ )
325+ }
326+
288327 /**
289328 * Holds if `n` is expected to possibly throw an exception. This can either
290329 * be due to a declared (likely checked) exception on a call target
@@ -293,6 +332,8 @@ private module Exceptions {
293332 predicate mayThrow ( Ast:: AstNode n ) {
294333 exists ( n .( Call ) .getCallee ( ) .getAThrownExceptionType ( ) )
295334 or
335+ checkedExceptionFromCatchCandidate ( n )
336+ or
296337 uncheckedExceptionFromMethod ( n )
297338 or
298339 uncheckedExceptionFromFinally ( n )
0 commit comments