While testing the library, I found a case where it crashes with a segfault.
In the argparse.go file, on line 619, the library reads data from a pointer that may be null - which is what happened in my case.
A scenario in which an error occurs:
package main
import (
"fmt"
"os"
"github.com/akamensky/argparse"
)
func parseArgs() {
parser := argparse.NewParser("fprinter", "Basic math function visualizer")
debug_level := parser.Selector("d", "debug-level", []string{"INFO", "DEBUG"}, nil)
fast := parser.Flag("f", "fast", nil)
if err := parser.Parse(os.Args); err != nil {
fmt.Print(parser.Usage(err))
os.Exit(1)
}
if debug_level != nil && *debug_level != "" {
fmt.Println(debug_level)
}
if fast != nil {
fmt.Print(*fast)
}
}
func main() {
parseArgs()
}
When you run the code with this flag, you get a segmentation fault:
[Michal@msi fprinter]$ ./main --help
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x4aa463]
goroutine 1 [running]:
github.com/akamensky/argparse.(*Command).precedingCommands2Result(0xfb6c6ab6000, {0x4dae6e, 0x6}, {0xfb6c6aac030, 0x1, 0x0?}, {0xfb6c6aae048, 0x3, 0x0?}, 0x50)
/home/Michal/go/pkg/mod/github.com/akamensky/argparse@v1.4.0/argparse.go:619 +0x163
github.com/akamensky/argparse.(*Command).Usage(0xfb6c6ab6000, {0x0?, 0x0?})
/home/Michal/go/pkg/mod/github.com/akamensky/argparse@v1.4.0/argparse.go:753 +0x4df
github.com/akamensky/argparse.(*Command).Help(0xfb6c6aa2ae0?, {0x0?, 0x0?})
/home/Michal/go/pkg/mod/github.com/akamensky/argparse@v1.4.0/argparse.go:75 +0x47
github.com/akamensky/argparse.(*arg).parseSomeType(0xfb6c6ab8000, {0xfb6c6ab2070?, 0x7f2649821a48?, 0x0?}, 0x0?)
/home/Michal/go/pkg/mod/github.com/akamensky/argparse@v1.4.0/argument.go:395 +0x66
github.com/akamensky/argparse.(*arg).parse(0xfb6c6ab8000?, {0xfb6c6ab2070?, 0x6?, 0xfb6c6aa2c18?}, 0x1000000000014?)
/home/Michal/go/pkg/mod/github.com/akamensky/argparse@v1.4.0/argument.go:445 +0x419
github.com/akamensky/argparse.(*Command).parseArguments(0x4bac80?, 0xfb6c6aa2e40)
/home/Michal/go/pkg/mod/github.com/akamensky/argparse@v1.4.0/command.go:170 +0x356
github.com/akamensky/argparse.(*Command).parse(0xfb6c6ab6000, 0xfb6c6aa2e40)
/home/Michal/go/pkg/mod/github.com/akamensky/argparse@v1.4.0/command.go:231 +0x10a
github.com/akamensky/argparse.(*Parser).Parse(0xfb6c6ab6000, {0xfb6c6ab2000?, 0x2, 0x4dac52?})
/home/Michal/go/pkg/mod/github.com/akamensky/argparse@v1.4.0/argparse.go:772 +0x7c
main.parseArgs()
/home/Michal/Dokumenty/github/fprinter/cli/main.go:15 +0xf3
main.main()
/home/Michal/Dokumenty/github/fprinter/cli/main.go:30 +0xf
As part of the diagnosis, I added if v.opts == nil in for loop:
func (o *Command) precedingCommands2Result(result string, chain []string, arguments []*arg, maxWidth int) string {
usedHelp := false
leftPadding := len("usage: " + chain[0] + "")
// Add preceding commands
for _, v := range chain {
result = addToLastLine(result, v, maxWidth, leftPadding, true)
}
// Add arguments from this and all preceding commands
for _, v := range arguments {
// Cas in with null apird
if v.opts == nil {
log.Fatal("Null pointer exeption")
}
// Skip arguments that are hidden
if v.opts.Help == DisableDescription {
continue
}
if v.lname == "help" && usedHelp {
} else {
result = addToLastLine(result, v.usage(), maxWidth, leftPadding, true)
}
if v.lname == "help" || v.sname == "h" {
usedHelp = true
}
}
// Add program/Command description to the result
result = result + "\n\n" + strings.Repeat(" ", leftPadding)
result = addToLastLine(result, o.description, maxWidth, leftPadding, true)
result = result + "\n\n"
return result
}
After restarting with the null check, I got the expected value:
[Michal@msi tmp]$ ./test --help
2026/06/13 00:07:49 Null pointer exeption
if v.opts == nil {
log.Fatal("Null pointer exeption")
}
I'm not very experienced with go, so my fix for this bug would probably make the code worse, but at least that's all I could do
While testing the library, I found a case where it crashes with a segfault.
In the argparse.go file, on line 619, the library reads data from a pointer that may be null - which is what happened in my case.
A scenario in which an error occurs:
When you run the code with this flag, you get a segmentation fault:
As part of the diagnosis, I added
if v.opts == nilin for loop:After restarting with the null check, I got the expected value:
I'm not very experienced with go, so my fix for this bug would probably make the code worse, but at least that's all I could do