mirror of
https://github.com/github/codeql.git
synced 2026-07-31 23:42:59 +02:00
Fix defer logic for panics
This commit is contained in:
@@ -933,6 +933,22 @@ module GoCfg {
|
||||
n.isAfter(fd.getBody())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is an exceptional-exit predecessor of `fd`: the in-order
|
||||
* node of a call that always panics or never returns normally. In Go,
|
||||
* deferred functions run on panic, so these nodes must also enter the
|
||||
* deferred-call chain.
|
||||
*/
|
||||
private predicate exceptionalExitPred(PreControlFlowNode n, Go::FuncDef fd) {
|
||||
exists(Go::CallExpr call |
|
||||
call.getEnclosingFunction() = fd and
|
||||
(call.getTarget().mustPanic() or call.getTarget().mustNotReturnNormally()) and
|
||||
not call = any(Go::DeferStmt s).getCall() and
|
||||
not call = any(Go::GoStmt s).getCall() and
|
||||
n.isIn(call)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if, after running its deferred calls, `fd` should continue at
|
||||
* `target` on a normal exit. For functions with result variables this is
|
||||
@@ -976,6 +992,15 @@ module GoCfg {
|
||||
deferInvoke(n1, firstD) and
|
||||
deferChainExitTarget(fd, n2)
|
||||
)
|
||||
or
|
||||
// (e) an unconditional panic with active defers flows to the last-registered active defer
|
||||
exists(Go::DeferStmt d, PreControlFlowNode reg |
|
||||
deferRegistration(reg, d) and
|
||||
d.getEnclosingFunction() = fd and
|
||||
exceptionalExitPred(n1, fd) and
|
||||
n1 = notDeferReach(reg) and
|
||||
deferInvoke(n2, d)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user