Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[staticcheck,SA5011] false positive with testing common.Errorf(…) #5748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
6 of 7 tasks
PlusMinus0 opened this issue Apr 18, 2025 · 3 comments
Closed
6 of 7 tasks
Labels
question Further information is requested

Comments

@PlusMinus0
Copy link

PlusMinus0 commented Apr 18, 2025

Welcome

  • Yes, I'm using a binary release within 2 latest releases. Only such installations are supported.
  • Yes, I've searched similar issues on GitHub and didn't find any.
  • Yes, I've read the typecheck section of the FAQ.
  • Yes, I've tried with the standalone linter if available (e.g., gocritic, go vet, etc.).
  • I agree to follow this project's Code of Conduct

How did you install golangci-lint?

AUR

Description of the problem

			if myObject == nil {
				t.Errorf("Commit is nil")
			}

			if myObject.Property != tt.myObject.Property {
				t.Errorf("Property is %s, want %s", myObject.Property, tt.myObject.Property)
			}

Results in a possible nil pointer dereference finding, event though it cannot be reached.

// Errorf is equivalent to Logf followed by Fail.

A return after t.Errorf(…) solves the false positive.

Version of golangci-lint

$ golangci-lint --version
golangci-lint has version 2.1.2 built with go1.24.2 from 00a561d9 on 2025-04-15T13:26:47Z

Configuration

golangci-lint run

Go environment

$ go version && go env
go version go1.24.2 linux/amd64
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/me/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/me/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1198222687=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/me/Projects/Private/my-project/go.mod'
GOMODCACHE='/home/me/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/me/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/me/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.2'
GOWORK=''
PKG_CONFIG='pkg-config'

Verbose output of running

$ golangci-lint cache clean
$ golangci-lint run -v
INFO golangci-lint has version 2.1.2 built with go1.24.2 from 00a561d9 on 2025-04-15T13:26:47Z
INFO [config_reader] Config search paths: [./ /home/me/Projects/Private/my-project /home/me/Projects/Private /home/me/Projects /home/me /home /]
INFO maxprocs: Leaving GOMAXPROCS=24: CPU quota undefined
INFO [goenv] Read go env for 2.225912ms: map[string]string{"GOCACHE":"/home/me/.cache/go-build", "GOROOT":"/usr/lib/go"}
INFO [lintersdb] Active 5 linters: [errcheck govet ineffassign staticcheck unused]
INFO [loader] Go packages loading at mode 8767 (deps|exports_file|files|name|compiled_files|imports|types_sizes) took 137.562801ms
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 780.138µs
INFO [linters_context/goanalysis] analyzers took 10.960488329s with top 10 stages: buildir: 8.156271004s, inspect: 756.195203ms, fact_deprecated: 484.077887ms, ctrlflow: 350.497698ms, printf: 269.983204ms, fact_purity: 197.25655ms, nilness: 136.225035ms, tokenfileanalyzer: 131.613618ms, SA5012: 120.441995ms, typedness: 106.799104ms
INFO [runner] Processors filtering stat (in/out): invalid_issue: 2/2, path_relativity: 2/2, exclusion_paths: 2/2, diff: 2/2, max_from_linter: 2/2, path_shortener: 2/2, exclusion_rules: 2/2, uniq_by_line: 2/2, path_absoluter: 2/2, cgo: 2/2, nolint_filter: 2/2, fixer: 2/2, filename_unadjuster: 2/2, generated_file_filter: 2/2, max_per_file_from_linter: 2/2, max_same_issues: 2/2, source_code: 2/2, severity-rules: 2/2, path_prettifier: 2/2, sort_results: 2/2
INFO [runner] processing took 193.472µs with stages: nolint_filter: 150.322µs, generated_file_filter: 17.74µs, source_code: 14.73µs, path_relativity: 2µs, uniq_by_line: 1.52µs, max_same_issues: 1.37µs, sort_results: 1.26µs, path_shortener: 630ns, cgo: 580ns, invalid_issue: 520ns, max_from_linter: 480ns, path_absoluter: 320ns, filename_unadjuster: 320ns, exclusion_rules: 310ns, max_per_file_from_linter: 290ns, exclusion_paths: 280ns, fixer: 270ns, path_prettifier: 250ns, diff: 210ns, severity-rules: 70ns
INFO [runner] linters took 1.799597061s with stages: goanalysis_metalinter: 1.799362349s
internal/conventional/parse_test.go:108:7: SA5011(related information): this check suggests that the pointer can be nil (staticcheck)
			if commit == nil {
			   ^
internal/conventional/parse_test.go:114:14: SA5011: possible nil pointer dereference (staticcheck)
			if commit.Type != tt.commit.Type {
			          ^
2 issues:
* staticcheck: 2
INFO File cache stats: 1 entries of total size 4.6KiB
INFO Memory: 21 samples, avg is 509.4MB, max is 834.8MB
INFO Execution took 1.940518007s

A minimal reproducible example or link to a public repository

https://gitlab.com/PlusMinus0/my-release-tools/-/blob/c0bf6b3734b0f146327dbb9a91f15bca6850eaa6/internal/conventional/parse_test.go

Validation

  • Yes, I've included all information above (version, config, etc.).

Supporter

@PlusMinus0 PlusMinus0 added the bug Something isn't working label Apr 18, 2025
Copy link

boring-cyborg bot commented Apr 18, 2025

Hey, thank you for opening your first Issue ! 🙂 If you would like to contribute we have a guide for contributors.

@ldez ldez added question Further information is requested and removed bug Something isn't working labels Apr 18, 2025
@ldez
Copy link
Member

ldez commented Apr 18, 2025

Hello,

  1. Your repository is private.
  2. This is not a false positive, because t.Errorf() doesn't stop the test, so a nil pointer can happen. You should use t.Fatal() instead.
    • // Fatal is equivalent to Log followed by FailNow.
    • // Error is equivalent to Log followed by Fail.
  3. Fail is not FailNow:
    • // FailNow marks the function as having failed and stops its execution
    • // Fail marks the function as having failed but continues execution.
package main

import (
	"testing"
)


type Foo struct {
	Property string
}

func TestPanic(t *testing.T) {
	testCases := []struct {
		desc     string
		myObject *Foo
	}{
		{desc: "example"},
	}

	for _, tt := range testCases {
		t.Run(tt.desc, func(t *testing.T) {
			var myObject *Foo

			if myObject == nil {
				t.Errorf("Commit is nil")
			}

			if myObject.Property != tt.myObject.Property { // <- Panic
				t.Errorf("Property is %s, want %s", myObject.Property, tt.myObject.Property)
			}
		})
	}
}

func TestNotPanic(t *testing.T) {
	testCases := []struct {
		desc     string
		myObject *Foo
	}{
		{desc: "example"},
	}

	for _, tt := range testCases {
		t.Run(tt.desc, func(t *testing.T) {
			var myObject *Foo

			if myObject == nil {
				t.Fatal("Commit is nil") // <- stop the test
			}

			if myObject.Property != tt.myObject.Property { 
				t.Errorf("Property is %s, want %s", myObject.Property, tt.myObject.Property)
			}
		})
	}
}

@ldez ldez closed this as completed Apr 18, 2025
@PlusMinus0
Copy link
Author

Whoops, sorry for wasting your time, and thank you for the details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants