diff --git a/route/address.go b/route/address.go index bae63003f..b649f4314 100644 --- a/route/address.go +++ b/route/address.go @@ -176,7 +176,7 @@ func parseInetAddr(af int, b []byte) (Addr, error) { ) switch af { case syscall.AF_INET: - if len(b) < (off4+1) || len(b) < int(b[0]) { + if len(b) < (off4+1) || len(b) < int(b[0]) || b[0] == 0 { return nil, errInvalidAddr } sockAddrLen := int(b[0]) @@ -188,7 +188,7 @@ func parseInetAddr(af int, b []byte) (Addr, error) { copy(a.IP[:], b[off4:n]) return a, nil case syscall.AF_INET6: - if len(b) < (off6+1) || len(b) < int(b[0]) { + if len(b) < (off6+1) || len(b) < int(b[0]) || b[0] == 0 { return nil, errInvalidAddr } sockAddrLen := int(b[0]) @@ -404,12 +404,16 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( } b = b[l:] case syscall.AF_INET, syscall.AF_INET6: - af = int(b[1]) - a, err := parseInetAddr(af, b) - if err != nil { - return nil, err + // #70528: if the sockaddrlen is 0, no address to parse inside, + // skip over the record. + if b[0] > 0 { + af = int(b[1]) + a, err := parseInetAddr(af, b) + if err != nil { + return nil, err + } + as[i] = a } - as[i] = a l := roundup(int(b[0])) if len(b) < l { return nil, errMessageTooShort diff --git a/route/address_darwin_test.go b/route/address_darwin_test.go index 0b5c72d1d..add72e37e 100644 --- a/route/address_darwin_test.go +++ b/route/address_darwin_test.go @@ -86,9 +86,61 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, }, []Addr{ - &Inet6Addr{IP: [16]byte{ 0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81 }}, - &Inet6Addr{IP: [16]byte{ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff }, ZoneID: 33}, - &Inet6Addr{IP: [16]byte{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,}}, + &Inet6Addr{IP: [16]byte{0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81}}, + &Inet6Addr{IP: [16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff}, ZoneID: 33}, + &Inet6Addr{IP: [16]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + nil, + nil, + nil, + nil, + nil, + }, + }, + // golang/go#70528, the kernel can produce addresses of length 0 + { + syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + parseKernelInetAddr, + []byte{ + 0x00, 0x1e, 0x00, 0x00, + + 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, + 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff, + 0x00, 0x00, 0x00, 0x00, + + 0x0e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + }, + []Addr{ + nil, + &Inet6Addr{IP: [16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff}, ZoneID: 33}, + &Inet6Addr{IP: [16]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + nil, + nil, + nil, + nil, + nil, + }, + }, + // Additional case: golang/go/issues/70528#issuecomment-2498692877 + { + syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + parseKernelInetAddr, + []byte{ + 0x84, 0x00, 0x05, 0x04, 0x01, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x01, 0x15, 0x00, 0x00, 0x00, + 0x1B, 0x01, 0x00, 0x00, 0xF5, 0x5A, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x14, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }, + []Addr{ + &Inet4Addr{IP: [4]byte{0x0, 0x0, 0x0, 0x0}}, + nil, + nil, nil, nil, nil,