Skip to content

Check errors that were discarded before use - #151

Merged
encodeous merged 1 commit into
encodeous:mainfrom
omlahore:fix/discarded-errors
Sep 4, 2026
Merged

Check errors that were discarded before use#151
encodeous merged 1 commit into
encodeous:mainfrom
omlahore:fix/discarded-errors

Conversation

@omlahore

@omlahore omlahore commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

staticcheck (SA4006) flags four places where an error is assigned and then discarded before anything tests it. One of them turns a handled startup failure into a panic.

InitUAPI panics instead of reporting why it failed

core/sys_linux.go:14 and core/sys_darwin.go:13 are identical:

fileUAPI, err := ipc.UAPIOpen(itfName)   // err discarded

uapi, err := ipc.UAPIListen(itfName, fileUAPI)

UAPIOpen returns (nil, err) on four paths in polyamide/ipc/uapi_unix.go: MkdirAll on the socket directory, ResolveUnixAddr, errors.New("unix socket in use"), and os.Remove of a stale socket. The nil *os.File reaches UAPIListen, which calls net.FileListener(file).

net.FileListener(nil) does not return an error, it panics. net/file.go:36 reads f.Name() to build the error message before anything checks the file:

net.FileListener(0x0)
	/usr/lib/go/src/net/file.go:36
os.(*File).Name(...)
	/usr/lib/go/src/os/file.go:63
panic: runtime error: invalid memory address or nil pointer dereference

So the two likeliest ways to start nylon wrong both end in a nil-pointer stack trace rather than the message already written for them: starting a second instance on an interface that already has a UAPI socket gives unix socket in use, and starting without root fails the MkdirAll. InitUAPI has one caller, core/sys_physical.go:55, on the startup path.

Worth noting the darwin one is invisible to a normal staticcheck ./..., since it analyses a single GOOS and the build-tagged file is not in the package otherwise. It only appears under GOOS=darwin.

The two smaller ones

  • cmd/utils.go:60pubKeyStr, err := privKey.Pubkey().MarshalText() is immediately followed by _, err = fmt.Fprintln(...), so the marshal error is overwritten before it is tested. The private key branch just above does check it. On a failure, nylon key prints an empty public key to stderr and exits 0.
  • state/distribution.go:80plainText, err := yaml.Marshal(cfg) goes straight into SignBundle(plainText, ...), so a marshal failure gets signed and sealed as empty bytes.

Not touched

polyamide/conn/bind_std.go:255 has the same SA4006 shape (numMsgs), but polyamide/ is a vendored wireguard-go fork, so it seemed better left to an upstream sync than changed here.

Verification

go build ./... and GOOS=darwin go build ./... both pass, go test ./core/... ./state/... is green before and after, gofmt -l is clean on all four files, and first-party SA4006 goes from 4 to 0.

I did not add a test. The UAPI path needs a real unix socket under the system socket directory, so a test would either need root or assert a failure that only reproduces without it, and would flip depending on how CI runs. If there is a pattern you use for the sys_* files, point me at it and I will add one.

InitUAPI ignored the error from UAPIOpen and passed the resulting nil
*os.File to UAPIListen, which hands it to net.FileListener. That panics
rather than returning an error, because net/file.go reads f.Name() for
the error message before checking the file. Starting a second instance on
an interface ("unix socket in use") or starting without root (MkdirAll on
the socket directory) both reach it, so the two likeliest startup
mistakes print a nil-pointer stack trace instead of the message that was
already written for them. Linux and darwin were identical here.

Two smaller ones of the same shape: the pubkey MarshalText error in the
key command was overwritten by the Fprintln error before it was tested,
so a failure there printed an empty public key and exited 0, and
BundleConfig dropped the yaml.Marshal error and went on to sign the
result.
@encodeous

Copy link
Copy Markdown
Owner

Thanks for this contribution

@encodeous
encodeous merged commit 66cc193 into encodeous:main Sep 4, 2026
7 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants