Defer/Go with Panic/Recover
ID |
go.defer_go_panic_recover |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Go |
Tags |
reliability, suspicious |
Description
Reports panic or recover used directly as the function of a defer or go statement:
defer panic(…), go recover(), defer recover() and go panic(…).
Rationale
recover only stops a panic when it is called directly by a deferred function; deferring it
or running it in a new goroutine means it executes in the wrong frame and always returns
nil, recovering nothing. A panic started in its own goroutine (go panic(…)) cannot be
recovered by the spawning goroutine and crashes the whole program, and a deferred panic
fires unconditionally as the function unwinds. Wrapping the builtin in a closure
(defer func(){ recover() }()) is the correct idiom and is not reported.
defer panic("boom") // FLAW — panic fires unconditionally on unwind
go recover() // FLAW — runs in another goroutine, recovers nothing
defer func() { // OK — recover called directly by the deferred function
if r := recover(); r != nil {
cleanup()
}
}()
Remediation
Recover inside a deferred function literal: defer func() { if r := recover(); r != nil { … } }().
Do not defer or go a bare panic/recover.