Skip to content

Commit 5c9db06

Browse files
committed
Tighten IsIPv6() semantics, clarify docs
IsIPv6() previously returned true for invalid net.IP objects (such as a 0-length net.IP). Fix it to return false instead. Make all of the IsXXX docs more precise about edge cases.
1 parent d001242 commit 5c9db06

File tree

2 files changed

+44
-18
lines changed

2 files changed

+44
-18
lines changed

net/ipfamily.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -106,25 +106,28 @@ func IsDualStackCIDRStrings(cidrs []string) (bool, error) {
106106
return IsDualStackCIDRs(parsedCIDRs)
107107
}
108108

109-
// IsIPv6 returns if netIP is IPv6.
110-
func IsIPv6(netIP net.IP) bool {
111-
return netIP != nil && netIP.To4() == nil
109+
// IsIPv6 returns true if ip is IPv6, or false if it is IPv4, nil, or invalid.
110+
func IsIPv6(ip net.IP) bool {
111+
return ip.To16() != nil && ip.To4() == nil
112112
}
113113

114-
// IsIPv6String returns if ip is IPv6.
114+
// IsIPv6String returns true if ip contains a single IPv6 address and nothing else. It
115+
// returns false if ip is an empty string, an IPv4 address, or anything else that is not a
116+
// single IPv6 address.
115117
func IsIPv6String(ip string) bool {
116-
netIP := ParseIPSloppy(ip)
117-
return IsIPv6(netIP)
118+
return IsIPv6(ParseIPSloppy(ip))
118119
}
119120

120-
// IsIPv6CIDRString returns if cidr is IPv6.
121-
// This assumes cidr is a valid CIDR.
121+
// IsIPv6CIDRString returns true if cidr contains a single IPv6 CIDR and nothing else. It
122+
// returns false if cidr is an empty string, an IPv4 CIDR, or anything else that is not a
123+
// single valid IPv6 CIDR.
122124
func IsIPv6CIDRString(cidr string) bool {
123125
ip, _, _ := ParseCIDRSloppy(cidr)
124126
return IsIPv6(ip)
125127
}
126128

127-
// IsIPv6CIDR returns if a cidr is ipv6
129+
// IsIPv6CIDR returns true if a cidr is a valid IPv6 CIDR. It returns false if cidr is
130+
// nil or an IPv4 CIDR. Its behavior is not defined if cidr is invalid.
128131
func IsIPv6CIDR(cidr *net.IPNet) bool {
129132
if cidr == nil {
130133
return false
@@ -133,18 +136,20 @@ func IsIPv6CIDR(cidr *net.IPNet) bool {
133136
return IsIPv6(ip)
134137
}
135138

136-
// IsIPv4 returns if netIP is IPv4.
137-
func IsIPv4(netIP net.IP) bool {
138-
return netIP != nil && netIP.To4() != nil
139+
// IsIPv4 returns true if ip is IPv4, or false if it is IPv6, nil, or invalid.
140+
func IsIPv4(ip net.IP) bool {
141+
return ip.To4() != nil
139142
}
140143

141-
// IsIPv4String returns if ip is IPv4.
144+
// IsIPv4String returns true if ip contains a single IPv4 address and nothing else. It
145+
// returns false if ip is an empty string, an IPv6 address, or anything else that is not a
146+
// single IPv4 address.
142147
func IsIPv4String(ip string) bool {
143-
netIP := ParseIPSloppy(ip)
144-
return IsIPv4(netIP)
148+
return IsIPv4(ParseIPSloppy(ip))
145149
}
146150

147-
// IsIPv4CIDR returns if a cidr is ipv4
151+
// IsIPv4CIDR returns true if cidr is a valid IPv4 CIDR. It returns false if cidr is nil
152+
// or an IPv6 CIDR. Its behavior is not defined if cidr is invalid.
148153
func IsIPv4CIDR(cidr *net.IPNet) bool {
149154
if cidr == nil {
150155
return false
@@ -153,8 +158,9 @@ func IsIPv4CIDR(cidr *net.IPNet) bool {
153158
return IsIPv4(ip)
154159
}
155160

156-
// IsIPv4CIDRString returns if cidr is IPv4.
157-
// This assumes cidr is a valid CIDR.
161+
// IsIPv4CIDRString returns true if cidr contains a single IPv4 CIDR and nothing else. It
162+
// returns false if cidr is an empty string, an IPv6 CIDR, or anything else that is not a
163+
// single valid IPv4 CIDR.
158164
func IsIPv4CIDRString(cidr string) bool {
159165
ip, _, _ := ParseCIDRSloppy(cidr)
160166
return IsIPv4(ip)

net/ipfamily_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,26 @@ func TestIsIPvX(t *testing.T) {
483483
ip: nil,
484484
family: IPFamilyUnknown,
485485
},
486+
{
487+
desc: "invalid empty binary net.IP",
488+
ip: net.IP([]byte{}),
489+
family: IPFamilyUnknown,
490+
},
491+
{
492+
desc: "invalid short binary net.IP",
493+
ip: net.IP([]byte{1, 2, 3}),
494+
family: IPFamilyUnknown,
495+
},
496+
{
497+
desc: "invalid medium-length binary net.IP",
498+
ip: net.IP([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}),
499+
family: IPFamilyUnknown,
500+
},
501+
{
502+
desc: "invalid long binary net.IP",
503+
ip: net.IP([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}),
504+
family: IPFamilyUnknown,
505+
},
486506
}
487507
for _, tc := range testCases {
488508
t.Run(tc.desc, func(t *testing.T) {

0 commit comments

Comments
 (0)