Non Pointer Unmarshal

ID

go.non_pointer_unmarshal

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Go

Tags

reliability, suspicious

Description

Reports an Unmarshal or Decode call (json.Unmarshal, xml.Unmarshal, a decoder’s Decode, …​) whose destination argument is clearly not a pointer — a composite literal or a plain value variable passed without taking its address. These functions write the decoded data through the destination pointer; a non-pointer destination is passed by value, so the result is written into a copy and silently discarded.

Rationale

json.Unmarshal(data, v) where v is a value (not &v) returns an error at runtime (json: Unmarshal(non-pointer …​)), and decoder.Decode(v) behaves the same way. The mistake is easy to make when refactoring or copying examples, and because the value compiles, it only surfaces as an empty struct or a runtime error. Flagging the obvious non-pointer destinations catches the bug at build time.

json.Unmarshal(data, v)        // FLAW — v is a value; decode is discarded
json.Unmarshal(data, Config{}) // FLAW — composite literal can never receive the result

json.Unmarshal(data, &v)       // OK — address of the destination
json.Unmarshal(data, p)        // OK — p is already a pointer

Remediation

Pass the address of the destination: json.Unmarshal(data, &v). If the destination is already a pointer, no change is needed.