Commit 66f49f78 authored by Russ Cox's avatar Russ Cox

net: make sure failed Dial returns nil Conn

Fixes #6614.

R=golang-dev, bradfitz, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/14950045
parent f6329700
...@@ -215,26 +215,30 @@ func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Con ...@@ -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 // dialSingle attempts to establish and returns a single connection to
// the destination address. // 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() { 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())} return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
} }
switch ra := ra.(type) { switch ra := ra.(type) {
case *TCPAddr: case *TCPAddr:
la, _ := la.(*TCPAddr) la, _ := la.(*TCPAddr)
return dialTCP(net, la, ra, deadline) c, err = dialTCP(net, la, ra, deadline)
case *UDPAddr: case *UDPAddr:
la, _ := la.(*UDPAddr) la, _ := la.(*UDPAddr)
return dialUDP(net, la, ra, deadline) c, err = dialUDP(net, la, ra, deadline)
case *IPAddr: case *IPAddr:
la, _ := la.(*IPAddr) la, _ := la.(*IPAddr)
return dialIP(net, la, ra, deadline) c, err = dialIP(net, la, ra, deadline)
case *UnixAddr: case *UnixAddr:
la, _ := la.(*UnixAddr) la, _ := la.(*UnixAddr)
return dialUnix(net, la, ra, deadline) c, err = dialUnix(net, la, ra, deadline)
default: default:
return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}} 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. // Listen announces on the local network address laddr.
...@@ -246,14 +250,19 @@ func Listen(net, laddr string) (Listener, error) { ...@@ -246,14 +250,19 @@ func Listen(net, laddr string) (Listener, error) {
if err != nil { if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err} return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
} }
var l Listener
switch la := la.toAddr().(type) { switch la := la.toAddr().(type) {
case *TCPAddr: case *TCPAddr:
return ListenTCP(net, la) l, err = ListenTCP(net, la)
case *UnixAddr: case *UnixAddr:
return ListenUnix(net, la) l, err = ListenUnix(net, la)
default: default:
return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}} 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. // ListenPacket announces on the local network address laddr.
...@@ -265,14 +274,19 @@ func ListenPacket(net, laddr string) (PacketConn, error) { ...@@ -265,14 +274,19 @@ func ListenPacket(net, laddr string) (PacketConn, error) {
if err != nil { if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err} return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
} }
var l PacketConn
switch la := la.toAddr().(type) { switch la := la.toAddr().(type) {
case *UDPAddr: case *UDPAddr:
return ListenUDP(net, la) l, err = ListenUDP(net, la)
case *IPAddr: case *IPAddr:
return ListenIP(net, la) l, err = ListenIP(net, la)
case *UnixAddr: case *UnixAddr:
return ListenUnixgram(net, la) l, err = ListenUnixgram(net, la)
default: default:
return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}} 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
} }
...@@ -218,3 +218,41 @@ func TestTCPClose(t *testing.T) { ...@@ -218,3 +218,41 @@ func TestTCPClose(t *testing.T) {
t.Fatal(err) 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)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment