commit 43b5924d68041cf73f473b56c275e5983ee40014 Author: David Fifield david@bamsoftware.com Date: Sat Nov 9 18:34:05 2013 -0800
Make resolveAddr more strict.
Go's net.ResolveTCPAddr allows an empty host or port part, returning for them nil and 0 respectively. It will also resolve names, which I don't think we need so we should avoid it for now.
These are the test failures that this change fixes: --- FAIL: TestResolveAddr (0.00 seconds) pt_test.go:201: "" unexpectedly succeeded: "<nil>:0" pt_test.go:201: "1.2.3.4:" unexpectedly succeeded: "1.2.3.4:0" pt_test.go:201: ":9999" unexpectedly succeeded: "<nil>:9999" pt_test.go:201: "[1:2::3:4]:" unexpectedly succeeded: "[1:2::3:4]:0" pt_test.go:201: "localhost:9999" unexpectedly succeeded: "127.0.0.1:9999" pt_test.go:201: "[localhost]:9999" unexpectedly succeeded: "127.0.0.1:9999" --- pt.go | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-)
diff --git a/pt.go b/pt.go index 45efc04..308238c 100644 --- a/pt.go +++ b/pt.go @@ -245,21 +245,40 @@ type BindAddr struct { Addr *net.TCPAddr }
-// Resolve an address string into a net.TCPAddr. +// Resolve an address string into a net.TCPAddr. We are a bit more strict than +// net.ResolveTCPAddr; we don't allow an empty host or port, and the host part +// must be a literal IP address. func resolveAddr(addrStr string) (*net.TCPAddr, error) { - addr, err := net.ResolveTCPAddr("tcp", addrStr) - if err == nil { - return addr, nil - } - // Before the fixing of bug #7011, tor doesn't put brackets around IPv6 - // addresses. Split after the last colon, assuming it is a port - // separator, and try adding the brackets. - parts := strings.Split(addrStr, ":") - if len(parts) <= 2 { + ipStr, portStr, err := net.SplitHostPort(addrStr) + if err != nil { + // Before the fixing of bug #7011, tor doesn't put brackets around IPv6 + // addresses. Split after the last colon, assuming it is a port + // separator, and try adding the brackets. + parts := strings.Split(addrStr, ":") + if len(parts) <= 2 { + return nil, err + } + addrStr := "[" + strings.Join(parts[:len(parts)-1], ":") + "]:" + parts[len(parts)-1] + ipStr, portStr, err = net.SplitHostPort(addrStr) + } + if err != nil { + return nil, err + } + if ipStr == "" { + return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a host part", addrStr)) + } + if portStr == "" { + return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a port part", addrStr)) + } + ip, err := net.ResolveIPAddr("ip", ipStr) + if err != nil { + return nil, err + } + port, err := net.LookupPort("tcp", portStr) + if err != nil { return nil, err } - addrStr = "[" + strings.Join(parts[:len(parts)-1], ":") + "]:" + parts[len(parts)-1] - return net.ResolveTCPAddr("tcp", addrStr) + return &net.TCPAddr{IP: ip.IP, Port: port, Zone: ip.Zone}, nil }
// Return a new slice, the members of which are those members of addrs having a