net: make protocol-specific WriteTo, WriteMsg methods return error instead of crash

R=golang-dev, dave, rsc, adg, bradfitz
CC=golang-dev
https://golang.org/cl/11809043
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go
index 8d41d20..1df661c 100644
--- a/src/pkg/net/iprawsock_posix.go
+++ b/src/pkg/net/iprawsock_posix.go
@@ -128,6 +128,9 @@
 	if !c.ok() {
 		return 0, syscall.EINVAL
 	}
+	if addr == nil {
+		return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
 	sa, err := addr.sockaddr(c.fd.family)
 	if err != nil {
 		return 0, &OpError{"write", c.fd.net, addr, err}
@@ -154,6 +157,9 @@
 	if !c.ok() {
 		return 0, 0, syscall.EINVAL
 	}
+	if addr == nil {
+		return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
 	sa, err := addr.sockaddr(c.fd.family)
 	if err != nil {
 		return 0, 0, &OpError{"write", c.fd.net, addr, err}
diff --git a/src/pkg/net/protoconn_test.go b/src/pkg/net/protoconn_test.go
index 7e4fbda..56f22da 100644
--- a/src/pkg/net/protoconn_test.go
+++ b/src/pkg/net/protoconn_test.go
@@ -161,6 +161,15 @@
 	} else {
 		f.Close()
 	}
+
+	defer func() {
+		if p := recover(); p != nil {
+			t.Fatalf("UDPConn.WriteToUDP or WriteMsgUDP panicked: %v", p)
+		}
+	}()
+
+	c.WriteToUDP(wb, nil)
+	c.WriteMsgUDP(wb, nil, nil)
 }
 
 func TestIPConnSpecificMethods(t *testing.T) {
@@ -218,6 +227,15 @@
 	} else {
 		f.Close()
 	}
+
+	defer func() {
+		if p := recover(); p != nil {
+			t.Fatalf("IPConn.WriteToIP or WriteMsgIP panicked: %v", p)
+		}
+	}()
+
+	c.WriteToIP(wb, nil)
+	c.WriteMsgIP(wb, nil, nil)
 }
 
 func TestUnixListenerSpecificMethods(t *testing.T) {
@@ -358,4 +376,15 @@
 	} else {
 		f.Close()
 	}
+
+	defer func() {
+		if p := recover(); p != nil {
+			t.Fatalf("UnixConn.WriteToUnix or WriteMsgUnix panicked: %v", p)
+		}
+	}()
+
+	c1.WriteToUnix(wb, nil)
+	c1.WriteMsgUnix(wb, nil, nil)
+	c3.WriteToUnix(wb, nil)
+	c3.WriteMsgUnix(wb, nil, nil)
 }
diff --git a/src/pkg/net/udpsock_plan9.go b/src/pkg/net/udpsock_plan9.go
index 12a3483..7362170 100644
--- a/src/pkg/net/udpsock_plan9.go
+++ b/src/pkg/net/udpsock_plan9.go
@@ -73,6 +73,9 @@
 	if !c.ok() || c.fd.data == nil {
 		return 0, syscall.EINVAL
 	}
+	if addr == nil {
+		return 0, &OpError{Op: "write", Net: c.fd.dir, Addr: nil, Err: errMissingAddress}
+	}
 	h := new(udpHeader)
 	h.raddr = addr.IP.To16()
 	h.laddr = c.fd.laddr.(*UDPAddr).IP.To16()
diff --git a/src/pkg/net/udpsock_posix.go b/src/pkg/net/udpsock_posix.go
index 0504e4f..1eee64f 100644
--- a/src/pkg/net/udpsock_posix.go
+++ b/src/pkg/net/udpsock_posix.go
@@ -124,6 +124,9 @@
 	if c.fd.isConnected {
 		return 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
 	}
+	if addr == nil {
+		return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
 	sa, err := addr.sockaddr(c.fd.family)
 	if err != nil {
 		return 0, &OpError{"write", c.fd.net, addr, err}
@@ -153,6 +156,9 @@
 	if c.fd.isConnected {
 		return 0, 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
 	}
+	if addr == nil {
+		return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
 	sa, err := addr.sockaddr(c.fd.family)
 	if err != nil {
 		return 0, 0, &OpError{"write", c.fd.net, addr, err}
diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go
index 593a435..2ae92a0 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/pkg/net/unixsock_posix.go
@@ -186,6 +186,9 @@
 	if !c.ok() {
 		return 0, syscall.EINVAL
 	}
+	if addr == nil {
+		return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+	}
 	if addr.Net != sotypeToNet(c.fd.sotype) {
 		return 0, syscall.EAFNOSUPPORT
 	}