Java: Make non-returning methods use local to global.

This commit is contained in:
Alex Eyers-Taylor
2025-06-12 18:34:32 +01:00
parent a80fbf09a8
commit ea8c73428d

View File

@@ -430,6 +430,13 @@ private module ControlFlowGraphImpl {
inBooleanContext(b.(StmtExpr).getStmt())
}
/**
* Module containing a global non-returning method analysis. The result is injected back into
* a local predicate `nonReturningMethodCall()`, which is used in further local predicates
* within this file.
*/
overlay[global]
private module NonReturningAnalysis {
/**
* A virtual method with a unique implementation. That is, the method does not
* participate in overriding and there are no call targets that could dispatch
@@ -500,11 +507,20 @@ private module ControlFlowGraphImpl {
/**
* Gets a `MethodCall` that always throws an exception or calls `exit`.
*/
private MethodCall nonReturningMethodCall() {
private MethodCall nonReturningMethodCallGlobal() {
result.getMethod().getSourceDeclaration() = nonReturningMethod() or
result = likelyNonReturningMethod().getAnAccess()
}
/**
* Gets a `MethodCall` that always throws an exception or calls `exit`.
*
* This predicate is local so gives the local anaylyis for base and the global
* analyis for overlay cases.
*/
overlay[local]
MethodCall nonReturningMethodCall() = localToGlobal(nonReturningMethodCallGlobal/0)(result)
/**
* Gets a statement that always throws an exception or calls `exit`.
*/
@@ -530,7 +546,7 @@ private module ControlFlowGraphImpl {
* Gets an expression that always throws an exception or calls `exit`.
*/
private Expr nonReturningExpr() {
result = nonReturningMethodCall()
result = nonReturningMethodCallGlobal()
or
result.(StmtExpr).getStmt() = nonReturningStmt()
or
@@ -541,6 +557,7 @@ private module ControlFlowGraphImpl {
)
)
}
}
// Join order engineering -- first determine the switch block and the case indices required, then retrieve them.
bindingset[switch, i]
@@ -766,7 +783,7 @@ private module ControlFlowGraphImpl {
not this instanceof BooleanLiteral and
not this instanceof ReturnStmt and
not this instanceof ThrowStmt and
not this = nonReturningMethodCall()
not this = NonReturningAnalysis::nonReturningMethodCall()
}
}