Skip to content

nil pointer dereference due to HelpFlag when running in parallel #2176

@G-Rath

Description

@G-Rath

My urfave/cli version is

v3.3.8

Checklist

  • Are you running the latest v3 release? The list of releases is here.
  • Did you check the manual for your release? The v3 manual is here
  • Did you perform a search about this problem? Here's the GitHub guide about searching.

Dependency Management

  • My project is using go modules.
  • My project is automatically downloading updating to the latest version.

Describe the bug

The HelpFlag has a self-described hack using a global which can result in a nil pointer dereference if run in parallel

cli/command_setup.go

Lines 203 to 211 in c185573

// TODO need to remove hack
if hf, ok := HelpFlag.(*BoolFlag); ok {
hf.applied = false
hf.hasBeenSet = false
hf.Value = false
hf.value = nil
}
tracef("appending HelpFlag (cmd=%[1]q)", cmd.Name)
cmd.appendFlag(HelpFlag)

To reproduce

// debug_test.go
package debug_test

import (
	"context"
	"fmt"
	"os"
	"testing"

	"github.com/urfave/cli/v3"
)

func RunCli(args []string) {
	cmd := &cli.Command{
		Name:     "debug",
		Usage:    "make an explosive entrance",
		Action: func(_ context.Context, cmd *cli.Command) error {
			return nil
		},
	}

	if err := cmd.Run(context.Background(), args); err != nil {
		fmt.Printf("%s\n", err)
	}
}

type Case struct {
	Name string
	Args []string
	Exit int
}

func Test_run(t *testing.T) {
	t.Parallel()

	tests := []Case{
		{
			Name: "hello_world",
			Exit: 0,
		},
		{
			Name: "hello_sunshine",
			Exit: 0,
		},
	}
	for _, tt := range tests {
		t.Run(tt.Name, func(t *testing.T) {
			t.Parallel()

			defer func() {
				if r := recover(); r != nil {
					t.Errorf("unexpected panic - '%s' passing %s", r, tt.Args)
				}
			}()

			RunCli(tt.Args)
		})
	}
}
❯ go test ./cmd/osv-scanner/debug/... -count 100000 -failfast
--- FAIL: Test_run (0.00s)
    --- FAIL: Test_run/hello_world (0.00s)
        debug_test.go:59: unexpected panic - 'runtime error: invalid memory address or nil pointer dereference' passing []
FAIL
FAIL    github.com/google/osv-scanner/v2/cmd/osv-scanner/debug  3.111s
FAIL

Observed behavior

A nil pointer dereference

Expected behavior

No error

Additional context

We found this in osv-scanner and our understanding is that it only impacts our test suite since CLI users will only run through this code path once; it's also uncommon, but still common enough that we do have CI failures from it maybe about once a week and it can be more common when running the test suite locally (likely because dev machines tend to have more CPU cores and threads available).

Setting HideHelp: false does avoid the issue which we might be able to use as a workaround, but I figured since there's a "TODO" about this already in the code might as well open an official issue for it either way

Want to fix this yourself?

I'm happy to help, though not sure if I'll be able to tackle this one by myself

Run go version and paste its output here

go version go1.24.4 linux/amd64

Run go env and paste its output here

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/jones/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/jones/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3604199268=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/jones/workspace/projects-oss/osv-scanner/go.mod'
GOMODCACHE='/home/jones/go/1.24.2/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/jones/go/1.24.2'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/jones/go/1.24.2/pkg/mod/golang.org/[email protected]'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/jones/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/jones/go/1.24.2/pkg/mod/golang.org/[email protected]/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.4'
GOWORK=''
PKG_CONFIG='pkg-config'

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/v3relates to / is being considered for v3kind/bugdescribes or fixes a bugstatus/triagemaintainers still need to look into this

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions