diff --git a/internal/third_party/forked/golang/net/ip.go b/internal/third_party/forked/golang/net/ip.go deleted file mode 100644 index 4340b6e7..00000000 --- a/internal/third_party/forked/golang/net/ip.go +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// IP address manipulations -// -// IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes. -// An IPv4 address can be converted to an IPv6 address by -// adding a canonical prefix (10 zeros, 2 0xFFs). -// This library accepts either size of byte slice but always -// returns 16-byte addresses. - -package net - -/////////////////////////////////////////////////////////////////////////////// -// NOTE: This file was forked because we need to maintain backwards-compatible -// IP parsing logic, which was changed in a correct but incompatible way in -// go-1.17. -// -// See https://issue.k8s.io/100895 -/////////////////////////////////////////////////////////////////////////////// - -import ( - stdnet "net" -) - -// -// Lean on the standard net lib as much as possible. -// - -type IP = stdnet.IP -type IPNet = stdnet.IPNet -type ParseError = stdnet.ParseError - -const IPv4len = stdnet.IPv4len -const IPv6len = stdnet.IPv6len - -var CIDRMask = stdnet.CIDRMask -var IPv4 = stdnet.IPv4 - -// Parse IPv4 address (d.d.d.d). -func parseIPv4(s string) IP { - var p [IPv4len]byte - for i := 0; i < IPv4len; i++ { - if len(s) == 0 { - // Missing octets. - return nil - } - if i > 0 { - if s[0] != '.' { - return nil - } - s = s[1:] - } - n, c, ok := dtoi(s) - if !ok || n > 0xFF { - return nil - } - // - // NOTE: This correct check was added for go-1.17, but is a - // backwards-incompatible change for kubernetes users, who might have - // stored data which uses these leading zeroes already. - // - // See https://issue.k8s.io/100895 - // - //if c > 1 && s[0] == '0' { - // // Reject non-zero components with leading zeroes. - // return nil - //} - s = s[c:] - p[i] = byte(n) - } - if len(s) != 0 { - return nil - } - return IPv4(p[0], p[1], p[2], p[3]) -} - -// parseIPv6 parses s as a literal IPv6 address described in RFC 4291 -// and RFC 5952. -func parseIPv6(s string) (ip IP) { - ip = make(IP, IPv6len) - ellipsis := -1 // position of ellipsis in ip - - // Might have leading ellipsis - if len(s) >= 2 && s[0] == ':' && s[1] == ':' { - ellipsis = 0 - s = s[2:] - // Might be only ellipsis - if len(s) == 0 { - return ip - } - } - - // Loop, parsing hex numbers followed by colon. - i := 0 - for i < IPv6len { - // Hex number. - n, c, ok := xtoi(s) - if !ok || n > 0xFFFF { - return nil - } - - // If followed by dot, might be in trailing IPv4. - if c < len(s) && s[c] == '.' { - if ellipsis < 0 && i != IPv6len-IPv4len { - // Not the right place. - return nil - } - if i+IPv4len > IPv6len { - // Not enough room. - return nil - } - ip4 := parseIPv4(s) - if ip4 == nil { - return nil - } - ip[i] = ip4[12] - ip[i+1] = ip4[13] - ip[i+2] = ip4[14] - ip[i+3] = ip4[15] - s = "" - i += IPv4len - break - } - - // Save this 16-bit chunk. - ip[i] = byte(n >> 8) - ip[i+1] = byte(n) - i += 2 - - // Stop at end of string. - s = s[c:] - if len(s) == 0 { - break - } - - // Otherwise must be followed by colon and more. - if s[0] != ':' || len(s) == 1 { - return nil - } - s = s[1:] - - // Look for ellipsis. - if s[0] == ':' { - if ellipsis >= 0 { // already have one - return nil - } - ellipsis = i - s = s[1:] - if len(s) == 0 { // can be at end - break - } - } - } - - // Must have used entire string. - if len(s) != 0 { - return nil - } - - // If didn't parse enough, expand ellipsis. - if i < IPv6len { - if ellipsis < 0 { - return nil - } - n := IPv6len - i - for j := i - 1; j >= ellipsis; j-- { - ip[j+n] = ip[j] - } - for j := ellipsis + n - 1; j >= ellipsis; j-- { - ip[j] = 0 - } - } else if ellipsis >= 0 { - // Ellipsis must represent at least one 0 group. - return nil - } - return ip -} - -// ParseIP parses s as an IP address, returning the result. -// The string s can be in IPv4 dotted decimal ("192.0.2.1"), IPv6 -// ("2001:db8::68"), or IPv4-mapped IPv6 ("::ffff:192.0.2.1") form. -// If s is not a valid textual representation of an IP address, -// ParseIP returns nil. -func ParseIP(s string) IP { - for i := 0; i < len(s); i++ { - switch s[i] { - case '.': - return parseIPv4(s) - case ':': - return parseIPv6(s) - } - } - return nil -} - -// ParseCIDR parses s as a CIDR notation IP address and prefix length, -// like "192.0.2.0/24" or "2001:db8::/32", as defined in -// RFC 4632 and RFC 4291. -// -// It returns the IP address and the network implied by the IP and -// prefix length. -// For example, ParseCIDR("192.0.2.1/24") returns the IP address -// 192.0.2.1 and the network 192.0.2.0/24. -func ParseCIDR(s string) (IP, *IPNet, error) { - i := indexByteString(s, '/') - if i < 0 { - return nil, nil, &ParseError{Type: "CIDR address", Text: s} - } - addr, mask := s[:i], s[i+1:] - iplen := IPv4len - ip := parseIPv4(addr) - if ip == nil { - iplen = IPv6len - ip = parseIPv6(addr) - } - n, i, ok := dtoi(mask) - if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen { - return nil, nil, &ParseError{Type: "CIDR address", Text: s} - } - m := CIDRMask(n, 8*iplen) - return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil -} - -// This is copied from go/src/internal/bytealg, which includes versions -// optimized for various platforms. Those optimizations are elided here so we -// don't have to maintain them. -func indexByteString(s string, c byte) int { - for i := 0; i < len(s); i++ { - if s[i] == c { - return i - } - } - return -1 -} diff --git a/internal/third_party/forked/golang/net/ip_test.go b/internal/third_party/forked/golang/net/ip_test.go deleted file mode 100644 index 108ea89d..00000000 --- a/internal/third_party/forked/golang/net/ip_test.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package net - -/////////////////////////////////////////////////////////////////////////////// -// NOTE: This file was forked because we need to maintain backwards-compatible -// IP parsing logic, which was changed in a correct but incompatible way in -// go-1.17. -// -// See https://issue.k8s.io/100895 -/////////////////////////////////////////////////////////////////////////////// - -import ( - stdnet "net" - "reflect" - "testing" -) - -// -// Lean on the standard net lib as much as possible. -// -type IPMask = stdnet.IPMask - -var IPv4Mask = stdnet.IPv4Mask - -var parseIPTests = []struct { - in string - out IP -}{ - {"127.0.1.2", IPv4(127, 0, 1, 2)}, - {"127.0.0.1", IPv4(127, 0, 0, 1)}, - {"127.001.002.003", IPv4(127, 1, 2, 3)}, // see https://issue.k8s.io/100895 - {"127.007.008.009", IPv4(127, 7, 8, 9)}, // see https://issue.k8s.io/100895 - {"127.010.020.030", IPv4(127, 10, 20, 30)}, // see https://issue.k8s.io/100895 - {"::ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, - {"::ffff:127.001.002.003", IPv4(127, 1, 2, 3)}, // see https://issue.k8s.io/100895 - {"::ffff:127.007.008.009", IPv4(127, 7, 8, 9)}, // see https://issue.k8s.io/100895 - {"::ffff:127.010.020.030", IPv4(127, 10, 20, 30)}, // see https://issue.k8s.io/100895 - {"::ffff:7f01:0203", IPv4(127, 1, 2, 3)}, - {"0:0:0:0:0000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, - {"0:0:0:0:000000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, - {"0:0:0:0::ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, - - {"2001:4860:0:2001::68", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}}, - {"2001:4860:0000:2001:0000:0000:0000:0068", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}}, - - {"-0.0.0.0", nil}, - {"0.-1.0.0", nil}, - {"0.0.-2.0", nil}, - {"0.0.0.-3", nil}, - {"127.0.0.256", nil}, - {"abc", nil}, - {"123:", nil}, - {"fe80::1%lo0", nil}, - {"fe80::1%911", nil}, - {"", nil}, - {"a1:a2:a3:a4::b1:b2:b3:b4", nil}, // Issue 6628 - // - // NOTE: These correct failures were added for go-1.17, but are a - // backwards-incompatible change for kubernetes users, who might have - // stored data which uses these leading zeroes already. - // - // See https://github.com/kubernetes/kubernetes/issues/100895 - // - //{"127.001.002.003", nil}, - //{"::ffff:127.001.002.003", nil}, - //{"123.000.000.000", nil}, - //{"1.2..4", nil}, - //{"0123.0.0.1", nil}, -} - -func TestParseIP(t *testing.T) { - for _, tt := range parseIPTests { - if out := ParseIP(tt.in); !reflect.DeepEqual(out, tt.out) { - t.Errorf("ParseIP(%q) = %v, want %v", tt.in, out, tt.out) - } - } -} - -var parseCIDRTests = []struct { - in string - ip IP - net *IPNet - err error -}{ - {"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 255)}, nil}, - {"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet{IP: IPv4(0, 0, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil}, - {"135.104.0.0/24", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil}, - {"135.104.0.1/32", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 1), Mask: IPv4Mask(255, 255, 255, 255)}, nil}, - {"135.104.0.1/24", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil}, - // see https://issue.k8s.io/100895 - {"127.000.000.001/32", IPv4(127, 0, 0, 1), &IPNet{IP: IPv4(127, 0, 0, 1), Mask: IPv4Mask(255, 255, 255, 255)}, nil}, - {"127.007.008.009/32", IPv4(127, 7, 8, 9), &IPNet{IP: IPv4(127, 7, 8, 9), Mask: IPv4Mask(255, 255, 255, 255)}, nil}, - {"127.010.020.030/32", IPv4(127, 10, 20, 30), &IPNet{IP: IPv4(127, 10, 20, 30), Mask: IPv4Mask(255, 255, 255, 255)}, nil}, - {"::1/128", ParseIP("::1"), &IPNet{IP: ParseIP("::1"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))}, nil}, - {"abcd:2345::/127", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"))}, nil}, - {"abcd:2345::/65", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::"))}, nil}, - {"abcd:2345::/64", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff::"))}, nil}, - {"abcd:2345::/63", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:fffe::"))}, nil}, - {"abcd:2345::/33", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:8000::"))}, nil}, - {"abcd:2345::/32", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff::"))}, nil}, - {"abcd:2344::/31", ParseIP("abcd:2344::"), &IPNet{IP: ParseIP("abcd:2344::"), Mask: IPMask(ParseIP("ffff:fffe::"))}, nil}, - {"abcd:2300::/24", ParseIP("abcd:2300::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil}, - {"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil}, - {"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil}, - {"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil}, - {"192.168.1.1/255.255.255.0", nil, nil, &ParseError{Type: "CIDR address", Text: "192.168.1.1/255.255.255.0"}}, - {"192.168.1.1/35", nil, nil, &ParseError{Type: "CIDR address", Text: "192.168.1.1/35"}}, - {"2001:db8::1/-1", nil, nil, &ParseError{Type: "CIDR address", Text: "2001:db8::1/-1"}}, - {"2001:db8::1/-0", nil, nil, &ParseError{Type: "CIDR address", Text: "2001:db8::1/-0"}}, - {"-0.0.0.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "-0.0.0.0/32"}}, - {"0.-1.0.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.-1.0.0/32"}}, - {"0.0.-2.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.-2.0/32"}}, - {"0.0.0.-3/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.-3/32"}}, - {"0.0.0.0/-0", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.0/-0"}}, - // see https://issue.k8s.io/100895 - //{"127.000.000.001/32", nil, nil, &ParseError{Type: "CIDR address", Text: "127.000.000.001/32"}}, - {"", nil, nil, &ParseError{Type: "CIDR address", Text: ""}}, -} - -func TestParseCIDR(t *testing.T) { - for _, tt := range parseCIDRTests { - ip, net, err := ParseCIDR(tt.in) - if !reflect.DeepEqual(err, tt.err) { - t.Errorf("ParseCIDR(%q) = %v, %v; want %v, %v", tt.in, ip, net, tt.ip, tt.net) - } - if err == nil && (!tt.ip.Equal(ip) || !tt.net.IP.Equal(net.IP) || !reflect.DeepEqual(net.Mask, tt.net.Mask)) { - t.Errorf("ParseCIDR(%q) = %v, {%v, %v}; want %v, {%v, %v}", tt.in, ip, net.IP, net.Mask, tt.ip, tt.net.IP, tt.net.Mask) - } - } -} diff --git a/internal/third_party/forked/golang/net/parse.go b/internal/third_party/forked/golang/net/parse.go deleted file mode 100644 index cc2fdcb9..00000000 --- a/internal/third_party/forked/golang/net/parse.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Simple file i/o and string manipulation, to avoid -// depending on strconv and bufio and strings. - -package net - -/////////////////////////////////////////////////////////////////////////////// -// NOTE: This file was forked because it is used by other code that needed to -// be forked, not because it is used on its own. -/////////////////////////////////////////////////////////////////////////////// - -// Bigger than we need, not too big to worry about overflow -const big = 0xFFFFFF - -// Decimal to integer. -// Returns number, characters consumed, success. -func dtoi(s string) (n int, i int, ok bool) { - n = 0 - for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { - n = n*10 + int(s[i]-'0') - if n >= big { - return big, i, false - } - } - if i == 0 { - return 0, 0, false - } - return n, i, true -} - -// Hexadecimal to integer. -// Returns number, characters consumed, success. -func xtoi(s string) (n int, i int, ok bool) { - n = 0 - for i = 0; i < len(s); i++ { - if '0' <= s[i] && s[i] <= '9' { - n *= 16 - n += int(s[i] - '0') - } else if 'a' <= s[i] && s[i] <= 'f' { - n *= 16 - n += int(s[i]-'a') + 10 - } else if 'A' <= s[i] && s[i] <= 'F' { - n *= 16 - n += int(s[i]-'A') + 10 - } else { - break - } - if n >= big { - return 0, i, false - } - } - if i == 0 { - return 0, i, false - } - return n, i, true -} diff --git a/net/parse.go b/net/parse.go index 400d364d..c152b7fb 100644 --- a/net/parse.go +++ b/net/parse.go @@ -17,17 +17,40 @@ limitations under the License. package net import ( - forkednet "k8s.io/utils/internal/third_party/forked/golang/net" + "net" + "regexp" ) +var matchZeros = regexp.MustCompile(`(^|:)0*(0|[1-9][0-9]*)\.0*(0|[1-9][0-9]*)\.0*(0|[1-9][0-9]*)\.0*(0|[1-9][0-9]*)((/)0*(0|[1-9][0-9]*))?$`) + +const stripZeros = `$1$2.$3.$4.$5$7$8` + // ParseIPSloppy is identical to Go's standard net.ParseIP, except that it allows // leading '0' characters on numbers. Go used to allow this and then changed // the behavior in 1.17. We're choosing to keep it for compat with potential // stored values. -var ParseIPSloppy = forkednet.ParseIP +func ParseIPSloppy(str string) net.IP { + // Try calling ParseIP directly, which will probably work. + if ip := net.ParseIP(str); ip != nil { + return ip + } + // Try stripping 0s and parsing the result. + str = matchZeros.ReplaceAllString(str, stripZeros) + return net.ParseIP(str) +} // ParseCIDRSloppy is identical to Go's standard net.ParseCIDR, except that it allows // leading '0' characters on numbers. Go used to allow this and then changed // the behavior in 1.17. We're choosing to keep it for compat with potential // stored values. -var ParseCIDRSloppy = forkednet.ParseCIDR +func ParseCIDRSloppy(str string) (net.IP, *net.IPNet, error) { + // Try calling ParseCIDR directly, which will probably work. + if ip, ipnet, err := net.ParseCIDR(str); err == nil { + return ip, ipnet, err + } + // Try stripping 0s and parsing the result. Note that if str didn't have any + // leading 0s, then this will just fail again in exactly the same way (with + // exactly the same error) as the first call. + str = matchZeros.ReplaceAllString(str, stripZeros) + return net.ParseCIDR(str) +}