From 66f49f78a5a8f8e6832e8b66eea56387b0c72a52 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 18 Oct 2013 15:35:45 -0400 Subject: [PATCH] net: make sure failed Dial returns nil Conn Fixes #6614. R=golang-dev, bradfitz, mikioh.mikioh CC=golang-dev https://golang.org/cl/14950045 --- src/pkg/net/dial.go | 34 ++++++++++++++++++++++++---------- src/pkg/net/net_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/src/pkg/net/dial.go b/src/pkg/net/dial.go index fb47795d79f..6304818bf14 100644 --- a/src/pkg/net/dial.go +++ b/src/pkg/net/dial.go @@ -215,26 +215,30 @@ func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Con // dialSingle attempts to establish and returns a single connection to // the destination address. -func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (Conn, error) { +func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) { if la != nil && la.Network() != ra.Network() { return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())} } switch ra := ra.(type) { case *TCPAddr: la, _ := la.(*TCPAddr) - return dialTCP(net, la, ra, deadline) + c, err = dialTCP(net, la, ra, deadline) case *UDPAddr: la, _ := la.(*UDPAddr) - return dialUDP(net, la, ra, deadline) + c, err = dialUDP(net, la, ra, deadline) case *IPAddr: la, _ := la.(*IPAddr) - return dialIP(net, la, ra, deadline) + c, err = dialIP(net, la, ra, deadline) case *UnixAddr: la, _ := la.(*UnixAddr) - return dialUnix(net, la, ra, deadline) + c, err = dialUnix(net, la, ra, deadline) default: return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}} } + if err != nil { + return nil, err // c is non-nil interface containing nil pointer + } + return c, nil } // Listen announces on the local network address laddr. @@ -246,14 +250,19 @@ func Listen(net, laddr string) (Listener, error) { if err != nil { return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err} } + var l Listener switch la := la.toAddr().(type) { case *TCPAddr: - return ListenTCP(net, la) + l, err = ListenTCP(net, la) case *UnixAddr: - return ListenUnix(net, la) + l, err = ListenUnix(net, la) default: return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}} } + if err != nil { + return nil, err // l is non-nil interface containing nil pointer + } + return l, nil } // ListenPacket announces on the local network address laddr. @@ -265,14 +274,19 @@ func ListenPacket(net, laddr string) (PacketConn, error) { if err != nil { return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err} } + var l PacketConn switch la := la.toAddr().(type) { case *UDPAddr: - return ListenUDP(net, la) + l, err = ListenUDP(net, la) case *IPAddr: - return ListenIP(net, la) + l, err = ListenIP(net, la) case *UnixAddr: - return ListenUnixgram(net, la) + l, err = ListenUnixgram(net, la) default: return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}} } + if err != nil { + return nil, err // l is non-nil interface containing nil pointer + } + return l, nil } diff --git a/src/pkg/net/net_test.go b/src/pkg/net/net_test.go index ee6cf0fcdd9..1320096df8f 100644 --- a/src/pkg/net/net_test.go +++ b/src/pkg/net/net_test.go @@ -218,3 +218,41 @@ func TestTCPClose(t *testing.T) { t.Fatal(err) } } + +func TestErrorNil(t *testing.T) { + c, err := Dial("tcp", "127.0.0.1:65535") + if err == nil { + t.Fatal("Dial 127.0.0.1:65535 succeeded") + } + if c != nil { + t.Fatalf("Dial returned non-nil interface %T(%v) with err != nil", c, c) + } + + // Make Listen fail by relistening on the same address. + l, err := Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatal("Listen 127.0.0.1:0: %v", err) + } + defer l.Close() + l1, err := Listen("tcp", l.Addr().String()) + if err == nil { + t.Fatal("second Listen %v: %v", l.Addr(), err) + } + if l1 != nil { + t.Fatalf("Listen returned non-nil interface %T(%v) with err != nil", l1, l1) + } + + // Make ListenPacket fail by relistening on the same address. + lp, err := ListenPacket("udp", "127.0.0.1:0") + if err != nil { + t.Fatal("Listen 127.0.0.1:0: %v", err) + } + defer lp.Close() + lp1, err := ListenPacket("udp", lp.LocalAddr().String()) + if err == nil { + t.Fatal("second Listen %v: %v", lp.LocalAddr(), err) + } + if lp1 != nil { + t.Fatalf("ListenPacket returned non-nil interface %T(%v) with err != nil", lp1, lp1) + } +}