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)
})

Remediation

Make the finalizer operate on its parameter instead of the captured object, so it holds no live reference to the value it is meant to finalize.