diff --git a/msg_helpers.go b/msg_helpers.go index 98fadc31..e5362fb4 100644 --- a/msg_helpers.go +++ b/msg_helpers.go @@ -783,28 +783,31 @@ func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) { if int(prefix) > 8*len(ip) { return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"} } - afdlen := int(nlen & 0x7f) - if (int(prefix)+7)/8 != afdlen { - return APLPrefix{}, len(msg), &Error{err: "invalid APL address length"} + if afdlen > len(ip) { + return APLPrefix{}, len(msg), &Error{err: "APL length too long"} } if off+afdlen > len(msg) { return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"} } off += copy(ip, msg[off:off+afdlen]) - if prefix%8 > 0 { + if afdlen > 0 { last := ip[afdlen-1] - zero := uint8(0xff) >> (prefix % 8) - if last&zero > 0 { + if last == 0 { return APLPrefix{}, len(msg), &Error{err: "extra APL address bits"} } } + ipnet := net.IPNet{ + IP: ip, + Mask: net.CIDRMask(int(prefix), 8*len(ip)), + } + network := ipnet.IP.Mask(ipnet.Mask) + if !network.Equal(ipnet.IP) { + return APLPrefix{}, len(msg), &Error{err: "invalid APL address length"} + } return APLPrefix{ Negation: (nlen & 0x80) != 0, - Network: net.IPNet{ - IP: ip, - Mask: net.CIDRMask(int(prefix), 8*len(ip)), - }, + Network: ipnet, }, off, nil } diff --git a/msg_helpers_test.go b/msg_helpers_test.go index 4ce3cd17..70e3b238 100644 --- a/msg_helpers_test.go +++ b/msg_helpers_test.go @@ -397,6 +397,10 @@ func TestUnpackDataAplPrefix_Errors(t *testing.T) { "extra bits set", []byte{0x00, 0x01, 22, 0x03, 192, 0, 2}, }, + { + "afdlen invalid", + []byte{0x00, 0x01, 22, 0x05, 192, 0, 2, 0, 0}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -416,6 +420,14 @@ func TestUnpackDataApl(t *testing.T) { 0x00, 0x01, 0x18, 0x03, 192, 0, 2, // !1:192.0.2.128/25 0x00, 0x01, 0x19, 0x84, 192, 0, 2, 128, + // 1:10.0.0.0/24 + 0x00, 0x01, 0x18, 0x01, 0x0a, + // !1:10.0.0.1/32 + 0x00, 0x01, 0x20, 0x84, 0x0a, 0, 0, 1, + // !1:0.0.0.0/0 + 0x00, 0x01, 0x00, 0x80, + // 2::0/0 + 0x00, 0x02, 0x00, 0x00, } expect := []APLPrefix{ { @@ -439,6 +451,34 @@ func TestUnpackDataApl(t *testing.T) { Mask: net.CIDRMask(25, 32), }, }, + { + Negation: false, + Network: net.IPNet{ + IP: net.ParseIP("10.0.0.0").To4(), + Mask: net.CIDRMask(24, 32), + }, + }, + { + Negation: true, + Network: net.IPNet{ + IP: net.ParseIP("10.0.0.1").To4(), + Mask: net.CIDRMask(32, 32), + }, + }, + { + Negation: true, + Network: net.IPNet{ + IP: net.ParseIP("0.0.0.0").To4(), + Mask: net.CIDRMask(0, 32), + }, + }, + { + Negation: false, + Network: net.IPNet{ + IP: net.ParseIP("::").To16(), + Mask: net.CIDRMask(0, 128), + }, + }, } got, off, err := unpackDataApl(wire, 0)