From 5630cb7518140e58174db7c0db40f16d982ba647 Mon Sep 17 00:00:00 2001 From: Dave Day Date: Wed, 16 Mar 2016 10:24:03 +1100 Subject: [PATCH] net: make SplitHostPort return an empty host on error This change also refactors SplitHostPort to avoid using gotos and naked returns. Fixes #14827 Change-Id: I4dca528936757fd06da76c23af8a0f6175bbedd1 Reviewed-on: https://go-review.googlesource.com/20726 Reviewed-by: Brad Fitzpatrick --- src/net/ip_test.go | 5 ++++- src/net/ipsock.go | 42 +++++++++++++++++------------------------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/net/ip_test.go b/src/net/ip_test.go index 2b24baf58e9..20060858187 100644 --- a/src/net/ip_test.go +++ b/src/net/ip_test.go @@ -421,13 +421,16 @@ func TestSplitHostPort(t *testing.T) { } } for _, tt := range splitFailureTests { - if _, _, err := SplitHostPort(tt.hostPort); err == nil { + if host, port, err := SplitHostPort(tt.hostPort); err == nil { t.Errorf("SplitHostPort(%q) should have failed", tt.hostPort) } else { e := err.(*AddrError) if e.Err != tt.err { t.Errorf("SplitHostPort(%q) = _, _, %q; want %q", tt.hostPort, e.Err, tt.err) } + if host != "" || port != "" { + t.Errorf("SplitHostPort(%q) = %q, %q, err; want %q, %q, err on failure", tt.hostPort, host, port, "", "") + } } } } diff --git a/src/net/ipsock.go b/src/net/ipsock.go index d6a6785e066..f3ac00df052 100644 --- a/src/net/ipsock.go +++ b/src/net/ipsock.go @@ -110,69 +110,61 @@ func ipv6only(addr IPAddr) bool { // must be enclosed in square brackets, as in "[::1]:80", // "[ipv6-host]:http" or "[ipv6-host%zone]:80". func SplitHostPort(hostport string) (host, port string, err error) { + const ( + missingPort = "missing port in address" + tooManyColons = "too many colons in address" + ) + addrErr := func(addr, why string) (host, port string, err error) { + return "", "", &AddrError{Err: why, Addr: addr} + } j, k := 0, 0 // The port starts after the last colon. i := last(hostport, ':') if i < 0 { - goto missingPort + return addrErr(hostport, missingPort) } if hostport[0] == '[' { // Expect the first ']' just before the last ':'. end := byteIndex(hostport, ']') if end < 0 { - err = &AddrError{Err: "missing ']' in address", Addr: hostport} - return + return addrErr(hostport, "missing ']' in address") } switch end + 1 { case len(hostport): // There can't be a ':' behind the ']' now. - goto missingPort + return addrErr(hostport, missingPort) case i: // The expected result. default: // Either ']' isn't followed by a colon, or it is // followed by a colon that is not the last one. if hostport[end+1] == ':' { - goto tooManyColons + return addrErr(hostport, tooManyColons) } - goto missingPort + return addrErr(hostport, missingPort) } host = hostport[1:end] j, k = 1, end+1 // there can't be a '[' resp. ']' before these positions } else { host = hostport[:i] if byteIndex(host, ':') >= 0 { - goto tooManyColons + return addrErr(hostport, tooManyColons) } if byteIndex(host, '%') >= 0 { - goto missingBrackets + return addrErr(hostport, "missing brackets in address") } } if byteIndex(hostport[j:], '[') >= 0 { - err = &AddrError{Err: "unexpected '[' in address", Addr: hostport} - return + return addrErr(hostport, "unexpected '[' in address") } if byteIndex(hostport[k:], ']') >= 0 { - err = &AddrError{Err: "unexpected ']' in address", Addr: hostport} - return + return addrErr(hostport, "unexpected ']' in address") } port = hostport[i+1:] - return - -missingPort: - err = &AddrError{Err: "missing port in address", Addr: hostport} - return - -tooManyColons: - err = &AddrError{Err: "too many colons in address", Addr: hostport} - return - -missingBrackets: - err = &AddrError{Err: "missing brackets in address", Addr: hostport} - return + return host, port, nil } func splitHostZone(s string) (host, zone string) {