internal/routebsd: fix parsing network address of length zero

This applies CL 646555 from the net repository to this copy.

For #70528

Change-Id: Ib7e23accfa3f278392e7bdca6f8544b8f1395e7e
Reviewed-on: https://go-review.googlesource.com/c/go/+/646676
Reviewed-by: Damien Neil <dneil@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
TryBot-Bypass: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
This commit is contained in:
Ian Lance Taylor 2025-02-04 15:11:42 -08:00 committed by Gopher Robot
parent b7c9cdd53c
commit f6ea0621d2
2 changed files with 40 additions and 36 deletions

View File

@ -102,44 +102,52 @@ func (a *InetAddr) Family() int {
// parseInetAddr parses b as an internet address for IPv4 or IPv6. // parseInetAddr parses b as an internet address for IPv4 or IPv6.
func parseInetAddr(af int, b []byte) (Addr, error) { func parseInetAddr(af int, b []byte) (Addr, error) {
const ( const (
off4 = 4 // offset of in_addr off4 = 4 // offset of in_addr
off6 = 8 // offset of in6_addr off6 = 8 // offset of in6_addr
ipv4Len = 4 // length of IPv4 address in bytes
ipv6Len = 16 // length of IPv6 address in bytes
) )
switch af { switch af {
case syscall.AF_INET: case syscall.AF_INET:
if len(b) < (off4+1) || len(b) < int(b[0]) || b[0] == 0 { if len(b) < (off4+1) || len(b) < int(b[0]) {
return nil, errInvalidAddr return nil, errInvalidAddr
} }
sockAddrLen := int(b[0]) sockAddrLen := int(b[0])
var ip [4]byte var ip [ipv4Len]byte
n := off4 + 4 if sockAddrLen != 0 {
if sockAddrLen < n { // Calculate how many bytes of the address to copy:
n = sockAddrLen // either full IPv4 length or the available length.
n := off4 + ipv4Len
if sockAddrLen < n {
n = sockAddrLen
}
copy(ip[:], b[off4:n])
} }
copy(ip[:], b[off4:n])
a := &InetAddr{ a := &InetAddr{
IP: netip.AddrFrom4(ip), IP: netip.AddrFrom4(ip),
} }
return a, nil return a, nil
case syscall.AF_INET6: case syscall.AF_INET6:
if len(b) < (off6+1) || len(b) < int(b[0]) || b[0] == 0 { if len(b) < (off6+1) || len(b) < int(b[0]) {
return nil, errInvalidAddr return nil, errInvalidAddr
} }
var ip [ipv6Len]byte
sockAddrLen := int(b[0]) sockAddrLen := int(b[0])
n := off6 + 16 if sockaddrLen != 0 {
if sockAddrLen < n { n := off6 + ipv6Len
n = sockAddrLen if sockAddrLen < n {
} n = sockAddrLen
var ip [16]byte }
copy(ip[:], b[off6:n]) copy(ip[:], b[off6:n])
if ip[0] == 0xfe && ip[1]&0xc0 == 0x80 || ip[0] == 0xff && (ip[1]&0x0f == 0x01 || ip[1]&0x0f == 0x02) { if ip[0] == 0xfe && ip[1]&0xc0 == 0x80 || ip[0] == 0xff && (ip[1]&0x0f == 0x01 || ip[1]&0x0f == 0x02) {
// KAME based IPv6 protocol stack usually // KAME based IPv6 protocol stack usually
// embeds the interface index in the // embeds the interface index in the
// interface-local or link-local address as // interface-local or link-local address as
// the kernel-internal form. // the kernel-internal form.
id := int(bigEndian.Uint16(ip[2:4])) id := int(bigEndian.Uint16(ip[2:4]))
if id != 0 { if id != 0 {
ip[2], ip[3] = 0, 0 ip[2], ip[3] = 0, 0
}
} }
} }
// The kernel can provide an integer zone ID. // The kernel can provide an integer zone ID.
@ -197,11 +205,11 @@ func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
switch { switch {
case b[0] == syscall.SizeofSockaddrInet6: case b[0] == syscall.SizeofSockaddrInet6:
a := &InetAddr{ a := &InetAddr{
IP: netip.AddrFrom16([16]byte(b[off6:off6+16])), IP: netip.AddrFrom16([16]byte(b[off6 : off6+16])),
} }
return int(b[0]), a, nil return int(b[0]), a, nil
case af == syscall.AF_INET6: case af == syscall.AF_INET6:
var ab[16]byte var ab [16]byte
if l-1 < off6 { if l-1 < off6 {
copy(ab[:], b[1:l]) copy(ab[:], b[1:l])
} else { } else {
@ -213,7 +221,7 @@ func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
return int(b[0]), a, nil return int(b[0]), a, nil
case b[0] == syscall.SizeofSockaddrInet4: case b[0] == syscall.SizeofSockaddrInet4:
a := &InetAddr{ a := &InetAddr{
IP: netip.AddrFrom4([4]byte(b[off4:off4+4])), IP: netip.AddrFrom4([4]byte(b[off4 : off4+4])),
} }
return int(b[0]), a, nil return int(b[0]), a, nil
default: // an old fashion, AF_UNSPEC or unknown means AF_INET default: // an old fashion, AF_UNSPEC or unknown means AF_INET
@ -251,16 +259,12 @@ func parseAddrs(attrs uint, b []byte) ([]Addr, error) {
} }
b = b[l:] b = b[l:]
case syscall.AF_INET, syscall.AF_INET6: case syscall.AF_INET, syscall.AF_INET6:
// #70528: if the sockaddrlen is 0, no address to parse inside, af = int(b[1])
// skip over the record. a, err := parseInetAddr(af, b)
if b[0] > 0 { if err != nil {
af = int(b[1]) return nil, err
a, err := parseInetAddr(af, b)
if err != nil {
return nil, err
}
as[i] = a
} }
as[i] = a
l := roundup(int(b[0])) l := roundup(int(b[0]))
if len(b) < l { if len(b) < l {
return nil, errMessageTooShort return nil, errMessageTooShort

View File

@ -108,7 +108,7 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
}, },
[]Addr{ []Addr{
nil, &InetAddr{IP: netip.AddrFrom16([16]byte{})},
&InetAddr{IP: netip.AddrFrom16([16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff})}, &InetAddr{IP: netip.AddrFrom16([16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff})},
&InetAddr{IP: netip.AddrFrom16([16]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff})}, &InetAddr{IP: netip.AddrFrom16([16]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff})},
nil, nil,