Skip to content

Commit e2edef3

Browse files
committed
Java: Handle missing throws clauses.
1 parent 576a846 commit e2edef3

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

java/ql/lib/semmle/code/java/ControlFlowGraph.qll

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)