From 99df9bdb2a014a0873b62b3f81d04970477004ad Mon Sep 17 00:00:00 2001 From: database64128 Date: Mon, 2 Mar 2026 00:43:57 +0800 Subject: [release-branch.go1.26] net: correctly handle non-nil empty cmsg buffer on windows Updates #77875 Fixes #77885 Change-Id: I0ed91be7ed10c04ddea3af55548a8dbf0be5f3a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/750420 Reviewed-by: Quim Muntal Reviewed-by: Damien Neil Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI (cherry picked from commit 9e0b5684e1f7166d6427635673001c80218ac9f4) Reviewed-on: https://go-review.googlesource.com/c/go/+/753060 Reviewed-by: Dmitri Shuralyov --- src/internal/poll/fd_windows.go | 8 +++++--- src/net/udpsock_test.go | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index edad656350..2ba967f990 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -159,9 +159,11 @@ func newWSAMsg(p []byte, oob []byte, flags int, unconnected bool) *windows.WSAMs msg := wsaMsgPool.Get().(*windows.WSAMsg) msg.Buffers.Len = uint32(len(p)) msg.Buffers.Buf = unsafe.SliceData(p) - msg.Control = syscall.WSABuf{ - Len: uint32(len(oob)), - Buf: unsafe.SliceData(oob), + if len(oob) > 0 { + msg.Control = syscall.WSABuf{ + Len: uint32(len(oob)), + Buf: unsafe.SliceData(oob), + } } msg.Flags = uint32(flags) if unconnected { diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index a79e9f83c1..1700ebaad1 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -750,3 +750,45 @@ func TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) { t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr6) should have failed, but got no error") } } + +// TestReadWriteMsgUDPAddrPortEmptyCmsg verifies that ReadMsgUDPAddrPort and +// WriteMsgUDPAddrPort won't fail when the cmsg buffer (the oob parameter) is +// non-nil but empty. +// +// This is a regression test for https://golang.org/issue/77875. +func TestReadWriteMsgUDPAddrPortEmptyCmsg(t *testing.T) { + switch runtime.GOOS { + case "plan9": + t.Skipf("not supported on %s", runtime.GOOS) + } + + if !testableNetwork("udp4") { + t.Skipf("skipping: udp4 not available") + } + + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + buf := make([]byte, 8) + cmsgBuf := make([]byte, 8)[:0] + daddr := conn.LocalAddr().(*UDPAddr).AddrPort() + + _, cmsgn, err := conn.WriteMsgUDPAddrPort(buf, cmsgBuf, daddr) + if err != nil { + t.Fatalf("WriteMsgUDPAddrPort failed: %v", err) + } + if cmsgn != 0 { + t.Errorf("WriteMsgUDPAddrPort wrote %d cmsg bytes; want 0", cmsgn) + } + + _, cmsgn, _, _, err = conn.ReadMsgUDPAddrPort(buf, cmsgBuf) + if err != nil { + t.Fatalf("ReadMsgUDPAddrPort failed: %v", err) + } + if cmsgn != 0 { + t.Errorf("ReadMsgUDPAddrPort read %d cmsg bytes; want 0", cmsgn) + } +} -- cgit v1.3