Skip to content

Commit e07b02f

Browse files
author
Bryan C. Mills
committed
net: in (*netFD).dial, use the passed in local address if getsockname fails
'man getsockname' lists a number of possible failure modes, including ENOBUFS (for resource exhaustion) and EBADF (which we could possibly see in the event of a bug or race condition elsewhere in the program). If getsockname fails for an explicit user-provided local address, the user is probably not expecting LocalAddr on the returned net.Conn to return nil. This may or may not fix #34611, but should at least help us diagnose it more clearly. While we're add it, also add more nil-checking logic in the test based on the stack traces posted to https://golang.org/issue/34611#issuecomment-975923748. For #34611 Change-Id: Iba870b96787811e4b9959b74ef648afce9316602 Reviewed-on: https://go-review.googlesource.com/c/go/+/366536 Trust: Bryan Mills <[email protected]> Run-TryBot: Bryan Mills <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 0eb39ca commit e07b02f

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

src/net/server_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,17 @@ func TestUnixAndUnixpacketServer(t *testing.T) {
200200
if c == nil {
201201
panic("Dial returned a nil Conn")
202202
}
203-
if rc := reflect.ValueOf(c); rc.Kind() == reflect.Pointer && rc.IsNil() {
203+
rc := reflect.ValueOf(c)
204+
if rc.IsNil() {
204205
panic(fmt.Sprintf("Dial returned a nil %T", c))
205206
}
207+
fd := rc.Elem().FieldByName("fd")
208+
if fd.IsNil() {
209+
panic(fmt.Sprintf("Dial returned a %T with a nil fd", c))
210+
}
211+
if addr := fd.Elem().FieldByName("laddr"); addr.IsNil() {
212+
panic(fmt.Sprintf("Dial returned a %T whose fd has a nil laddr", c))
213+
}
206214
addr := c.LocalAddr()
207215
if addr == nil {
208216
panic(fmt.Sprintf("(%T).LocalAddr returned a nil Addr", c))

src/net/sock_posix.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,24 @@ func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr, ctrlFn func(st
156156
}
157157
}
158158
// Record the local and remote addresses from the actual socket.
159-
// Get the local address by calling Getsockname.
159+
// For the local address, use
160+
// 1) the one returned by Getsockname, if that succeeds; or
161+
// 2) the one passed to us as the laddr parameter; or
162+
// 3) nil.
160163
// For the remote address, use
161164
// 1) the one returned by the connect method, if any; or
162165
// 2) the one from Getpeername, if it succeeds; or
163166
// 3) the one passed to us as the raddr parameter.
164-
lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
167+
var laddrName Addr = laddr
168+
if lsa, err := syscall.Getsockname(fd.pfd.Sysfd); err == nil {
169+
laddrName = fd.addrFunc()(lsa)
170+
}
165171
if crsa != nil {
166-
fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa))
172+
fd.setAddr(laddrName, fd.addrFunc()(crsa))
167173
} else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil {
168-
fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa))
174+
fd.setAddr(laddrName, fd.addrFunc()(rsa))
169175
} else {
170-
fd.setAddr(fd.addrFunc()(lsa), raddr)
176+
fd.setAddr(laddrName, raddr)
171177
}
172178
return nil
173179
}

0 commit comments

Comments
 (0)