Finalizer References Object
ID |
go.finalizer_references_object |
Severity |
low |
Remediation Complexity |
simple |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Go |
Tags |
CWE:401, correctness, reliability |
Description
Reports a runtime.SetFinalizer(x, fn) call whose finalizer function literal closes over x, the
object being finalized. Holding a reference to the object inside its own finalizer keeps the object
reachable, so it is never garbage-collected and the finalizer never runs.
Rationale
A finalizer runs only after the garbage collector proves the object is unreachable. If the finalizer function captures the object, that capture is itself a live reference, so the object can never become unreachable while the finalizer is registered — the object leaks and the cleanup code never executes. Finalizers should operate only on their parameter (the object passed to them by the runtime), never on a captured copy of it.
To stay free of false positives the rule fires only when the first argument is a bare identifier,
the second is an inline function literal, and that identifier is referenced inside the literal
without being shadowed by one of its parameters. A finalizer that uses only its parameter, or a
nil finalizer, is never reported.
runtime.SetFinalizer(x, func(_ *int) { // FLAW — closes over x; x is never collected
fmt.Println(x)
})
runtime.SetFinalizer(x, func(p *int) { // OK — uses only the parameter
fmt.Println(p)
})