From 3aac8b2c420fd4f15698da838d15ea7c984e90d7 Mon Sep 17 00:00:00 2001 From: Charlie Tonneslan Date: Mon, 25 May 2026 10:58:27 -0400 Subject: [PATCH] ip: stop GetIP erroring on a nil default flag IP("ip", nil, "...") followed by GetIP("ip") returned "invalid string being converted to IP address: " instead of (nil, nil). The flag's stored value is a nil net.IP, which net.IP.String renders as "", so ipConv saw that literal string and net.ParseIP rejected it. Treat "" and "" as "no IP" in ipConv, matching Set's empty-input behaviour, so a nil default round-trips cleanly through GetIP. Fixes #351 Signed-off-by: Charlie Tonneslan --- ip.go | 8 ++++++++ ip_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/ip.go b/ip.go index 06b8bcb5..4b767479 100644 --- a/ip.go +++ b/ip.go @@ -32,6 +32,14 @@ func (i *ipValue) Type() string { } func ipConv(sval string) (interface{}, error) { + // An unset IP flag with a nil default round-trips through String() as + // "", because that's what net.IP.String returns for a nil + // receiver. Treat that (and the empty string, to match how Set treats + // empty input) as "no IP" so GetIP doesn't error on + // IP("ip", nil, ...). See #351. + if sval == "" || sval == "" { + return net.IP(nil), nil + } ip := net.ParseIP(sval) if ip != nil { return ip, nil diff --git a/ip_test.go b/ip_test.go index 7a5da106..1c1ceb8a 100644 --- a/ip_test.go +++ b/ip_test.go @@ -61,3 +61,31 @@ func TestIP(t *testing.T) { } } } + +// TestIPNilDefault covers #351: declaring an IP flag with a nil default and +// then reading it without setting it must return (nil, nil), not an error. +// Before the ipConv guard, the unset flag's String() returned "" and +// GetIP tried to parse it as an address. +func TestIPNilDefault(t *testing.T) { + f := NewFlagSet("test", ContinueOnError) + f.IP("ip", nil, "") + + ip, err := f.GetIP("ip") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if ip != nil { + t.Errorf("expected nil IP, got %v", ip) + } + + var bound net.IP + f2 := NewFlagSet("test2", ContinueOnError) + f2.IPVar(&bound, "ip", nil, "") + ip, err = f2.GetIP("ip") + if err != nil { + t.Fatalf("unexpected error (IPVar variant): %v", err) + } + if ip != nil { + t.Errorf("expected nil IP (IPVar variant), got %v", ip) + } +}