From 658b5e66ecbc41a49e6fb5aa63c5d9c804cf305f Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 18 May 2021 12:23:56 -0400 Subject: [PATCH] net: return nil UDPAddr from ReadFromUDP In cases where the socket operation has no underlying address, golang.org/cl/291509 unintentionally changed ReadFromUDP from return a nil *UDPAddr to a non-nil (but zero value) *UDPAddr. This may break callers that assume "no address" is always addr == nil, so change it back to remain nil. Fixes #46238 Change-Id: I8531e8fa16b853ed7560088eabda0b9e3e53f5be Reviewed-on: https://go-review.googlesource.com/c/go/+/320909 Trust: Michael Pratt Trust: Josh Bleecher Snyder Reviewed-by: Filippo Valsorda Reviewed-by: Josh Bleecher Snyder --- src/net/udpsock_posix.go | 3 +++ src/net/udpsock_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index fcfb9c004cd..96fb373ce77 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -50,6 +50,9 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port} case *syscall.SockaddrInet6: *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))} + default: + // No sockaddr, so don't return UDPAddr. + addr = nil } return n, addr, err } diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index b4000b5664d..0e8c3511c36 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -8,7 +8,9 @@ package net import ( + "errors" "internal/testenv" + "os" "reflect" "runtime" "testing" @@ -446,6 +448,33 @@ func TestUDPReadSizeError(t *testing.T) { } } +// TestUDPReadTimeout verifies that ReadFromUDP with timeout returns an error +// without data or an address. +func TestUDPReadTimeout(t *testing.T) { + la, err := ResolveUDPAddr("udp4", "127.0.0.1:0") + if err != nil { + t.Fatal(err) + } + c, err := ListenUDP("udp4", la) + if err != nil { + t.Fatal(err) + } + defer c.Close() + + c.SetDeadline(time.Now()) + b := make([]byte, 1) + n, addr, err := c.ReadFromUDP(b) + if !errors.Is(err, os.ErrDeadlineExceeded) { + t.Errorf("ReadFromUDP got err %v want os.ErrDeadlineExceeded", err) + } + if n != 0 { + t.Errorf("ReadFromUDP got n %d want 0", n) + } + if addr != nil { + t.Errorf("ReadFromUDP got addr %+#v want nil", addr) + } +} + func BenchmarkWriteToReadFromUDP(b *testing.B) { conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) if err != nil {