Compare commits

...

21 Commits

Author SHA1 Message Date
Gopher Robot
56ebf80e57 [release-branch.go1.25] go1.25.1
Change-Id: I93a703d161b821cf7a78934f8711416ac6b00485
Reviewed-on: https://go-review.googlesource.com/c/go/+/700736
Auto-Submit: Gopher Robot <gobot@golang.org>
TryBot-Bypass: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
2025-09-03 10:46:11 -07:00
Filippo Valsorda
b1959cf6f7 [release-branch.go1.25] net/http: require exact match for CrossSiteProtection bypass patterns
Fixes #75160
Updates #75054
Fixes CVE-2025-47910

Change-Id: I6a6a696440c45c450d2cd681f418b01aa0422a60
Reviewed-on: https://go-review.googlesource.com/c/go/+/699276
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-08-27 08:45:05 -07:00
database64128
cdd8cf4988 [release-branch.go1.25] net: fix WriteMsgUDPAddrPort addr handling on IPv4 sockets
Accept IPv4-mapped IPv6 destination addresses on IPv4 UDP sockets.

Fixes #74999.

Change-Id: I4624b9b8f861aedcae29e51d5298d23ce1c0f2c7
Reviewed-on: https://go-review.googlesource.com/c/go/+/689976
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit bdb2d50fdf)
Reviewed-on: https://go-review.googlesource.com/c/go/+/695875
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
2025-08-25 19:49:59 -07:00
qmuntal
8995e84ac6 [release-branch.go1.25] internal/poll: set the correct file offset in FD.Seek for Windows overlapped handles
Windows doesn't keep the file pointer for overlapped file handles. To
work around this, we keep track of the current offset ourselves and use
it on every Read/Write operation.

When the user calls File.Seek with whence == io.SeekCurrent, it expects
that the offset we keep track of is also accounted for, else the the
seek'ed value won't match the file pointer seen by the user.

Fixes #75083.

Change-Id: Ieca7c3779e5349292883ffc293a8474088a4dec7
Reviewed-on: https://go-review.googlesource.com/c/go/+/697275
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
(cherry picked from CL 697275)
Reviewed-on: https://go-review.googlesource.com/c/go/+/697995
2025-08-25 11:19:12 -07:00
Damien Neil
749dff880a [release-branch.go1.25] runtime: make all synctest bubble violations fatal panics
Unblocking a bubbled goroutine from outside the bubble is an error
and panics. Currently, some of those panics are regular panics
and some are fatal. We use fatal panics in cases where its difficult
to panic without leaving something in an inconsistent state.

Change the regular panics (channel and timer operations) to be fatal.

This makes our behavior more consistent: All bubble violations are
always fatal.

More importantly, it avoids introducing new, recoverable panics.
A motivating example for this change is the context package,
which performs channel operations with a mutex held in the
expectation that those operations can never panic. These operations
can now panic as a result of a bubble violation, potentially
leaving a context.Context in an inconsistent state.

For #74837
Fixes #75021

Change-Id: Ie6efd916b7f505c0f13dde42de1572992401f15c
Reviewed-on: https://go-review.googlesource.com/c/go/+/696195
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
(cherry picked from commit a8564bd412)
Reviewed-on: https://go-review.googlesource.com/c/go/+/696196
2025-08-25 11:17:11 -07:00
Richard Miller
21ac81c1e1 [release-branch.go1.25] os/exec: fix incorrect expansion of ".." in LookPath on plan9
The correction in CL 685755 is incomplete for plan9, where path
search is performed even on file strings containing "/". By
applying filepath.Clean to the argument of validateLookPath,
we can check for bogus file strings containing ".." where the
later call to filepath.Join would transform a path like
"badfile/dir/.." to "badfile" even where "dir" isn't a directory
or doesn't exist.

For #74466
Fixes #75008

Change-Id: I3f8b73a1de6bc7d8001b1ca8e74b78722408548e
Reviewed-on: https://go-review.googlesource.com/c/go/+/693935
Reviewed-by: David du Colombier <0intro@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
(cherry picked from commit 674c5f0edd)
Reviewed-on: https://go-review.googlesource.com/c/go/+/698416
Reviewed-by: Cherry Mui <cherryyz@google.com>
2025-08-25 11:15:17 -07:00
Michael Matloob
c72fcab6d6 [release-branch.go1.25] cmd/go/internal/gover: fix ModIsPrerelease for toolchain versions
We forgot to call the IsPrerelease function on FromToolchain(vers)
rather than on vers itself. IsPrerelase expects a version without the
"go" prefix. See the corresponding code in ModIsValid and ModIsPrefix
that call FromToolchain before passing the versions to IsValid and
IsLang respectively.

Fixes #74822

Change-Id: I3cf055e1348e6a9dc0334e414f06fe85eaf78024
Reviewed-on: https://go-review.googlesource.com/c/go/+/691655
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Matloob <matloob@golang.org>
Reviewed-by: Michael Matloob <matloob@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
(cherry picked from commit 69338a335a)
Reviewed-on: https://go-review.googlesource.com/c/go/+/691958
2025-08-20 12:47:59 -07:00
Gopher Robot
6e676ab2b8 [release-branch.go1.25] go1.25.0
Change-Id: I46dcb2de47fd752d61863cc351ad792b64995a93
Reviewed-on: https://go-review.googlesource.com/c/go/+/695416
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Bypass: Gopher Robot <gobot@golang.org>
Commit-Queue: David Chase <drchase@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: David Chase <drchase@google.com>
2025-08-12 13:50:10 -07:00
Gopher Robot
ac94297758 [release-branch.go1.25] go1.25rc3
Change-Id: I7801c8fe17b0712b479d45fda0d81c060a904097
Reviewed-on: https://go-review.googlesource.com/c/go/+/693716
TryBot-Bypass: Gopher Robot <gobot@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
2025-08-06 11:09:03 -07:00
Damien Neil
6961c3775f [release-branch.go1.25] database/sql: avoid closing Rows while scan is in progress
A database/sql/driver.Rows can return database-owned data
from Rows.Next. The driver.Rows documentation doesn't explicitly
document the lifetime guarantees for this data, but a reasonable
expectation is that the caller of Next should only access it
until the next call to Rows.Close or Rows.Next.

Avoid violating that constraint when a query is cancelled while
a call to database/sql.Rows.Scan (note the difference between
the two different Rows types!) is in progress. We previously
took care to avoid closing a driver.Rows while the user has
access to driver-owned memory via a RawData, but we could still
close a driver.Rows while a Scan call was in the process of
reading previously-returned driver-owned data.

Update the fake DB used in database/sql tests to invalidate
returned data to help catch other places we might be
incorrectly retaining it.

Updates #74831
Fixes #74834

Change-Id: Ice45b5fad51b679c38e3e1d21ef39156b56d6037
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2540
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Neal Patel <nealpatel@google.com>
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2600
Reviewed-on: https://go-review.googlesource.com/c/go/+/693559
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2025-08-06 10:52:26 -07:00
Olivier Mengué
ebee011a54 [release-branch.go1.25] os/exec: fix incorrect expansion of "", "." and ".." in LookPath
Fix incorrect expansion of "" and "." when $PATH contains an executable
file or, on Windows, a parent directory of a %PATH% element contains an
file with the same name as the %PATH% element but with one of the
%PATHEXT% extension (ex: C:\utils\bin is in PATH, and C:\utils\bin.exe
exists).

Fix incorrect expansion of ".." when $PATH contains an element which is
an the concatenation of the path to an executable file (or on Windows
a path that can be expanded to an executable by appending a %PATHEXT%
extension), a path separator and a name.

"", "." and ".." are now rejected early with ErrNotFound.

Fixes CVE-2025-47906
Fixes #74466

Change-Id: Ie50cc0a660fce8fbdc952a7f2e05c36062dcb50e
Reviewed-on: https://go-review.googlesource.com/c/go/+/685755
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit e0b07dc22e)
Reviewed-on: https://go-review.googlesource.com/c/go/+/691775
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2025-07-30 08:43:19 -07:00
qmuntal
84fb1b8253 [release-branch.go1.25] os/user: user random name for the test user account
TestImpersonated and TestGroupIdsTestUser are flaky due to sporadic
failures when creating the test user account when running the tests
from different processes at the same time.

This flakiness can be fixed by using a random name for the test user
account.

Fixes #73523
Fixes #74727
Fixes #74728
Fixes #74729
Fixes #74745
Fixes #74751

Cq-Include-Trybots: luci.golang.try:go1.25-windows-amd64-longtest
Change-Id: Ib2283a888437420502b1c11d876c975f5af4bc03
Reviewed-on: https://go-review.googlesource.com/c/go/+/690175
Auto-Submit: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@golang.org>
(cherry picked from commit 374e3be2eb)
Reviewed-on: https://go-review.googlesource.com/c/go/+/690555
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Mark Freeman <mark@golang.org>
2025-07-28 11:34:45 -07:00
Michael Matloob
c95d3093ca [release-branch.go1.25] cmd/go: always return the cached path from go tool -n
If we're running go tool -n always return the cached path of the tool.
We can't always use the cached path when running the tool because if we
copied the tool to the cached location in the same process and then try
to run it we'll run into #22315, producing spurious ETXTBSYs.

Fixes #72824

Change-Id: I81f23773b9028f955ccc97453627ae4f2573814b
Reviewed-on: https://go-review.googlesource.com/c/go/+/688895
Auto-Submit: Michael Matloob <matloob@golang.org>
Reviewed-by: Michael Matloob <matloob@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
(cherry picked from commit efc37e97c0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/690895
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Bypass: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2025-07-28 10:58:29 -07:00
Michael Anthony Knyszek
561964c9a8 [release-branch.go1.25] all: merge master (489868f) into release-branch.go1.25
Merge List:

+ 2025-07-23 489868f776 cmd/link: scope test to linux & net.sendFile
+ 2025-07-22 71c2bf5513 cmd/compile: fix loclist for heap return vars without optimizations
+ 2025-07-22 c74399e7f5 net: correct comment for ListenConfig.ListenPacket
+ 2025-07-22 4ed9943b26 all: go fmt
+ 2025-07-22 1aaf7422f1 cmd/internal/objabi: remove redundant word in comment
+ 2025-07-21 d5ec0815e6 runtime: relax TestMemoryLimitNoGCPercent a bit
+ 2025-07-21 f7cc61e7d7 cmd/compile: for arm64 epilog, do SP increment with a single instruction
+ 2025-07-21 5dac42363b runtime: fix asan wrapper for riscv64
+ 2025-07-21 e5502e0959 cmd/go: check subcommand properties
+ 2025-07-19 2363897932 cmd/internal/obj: enable got pcrel itype in fips140 for riscv64
+ 2025-07-19 e32255fcc0 cmd/compile/internal/ssa: restrict architectures for TestDebugLines_74576
+ 2025-07-18 0451816430 os: revert the use of AddCleanup to close files and roots
+ 2025-07-18 34b70684ba go/types: infer correct type for y in append(bytes, y...)
+ 2025-07-17 66536242fc cmd/compile/internal/escape: improve DWARF .debug_line numbering for literal rewriting optimizations
+ 2025-07-16 385000b004 runtime: fix idle time double-counting bug
+ 2025-07-16 f506ad2644 cmd/compile/internal/escape: speed up analyzing some functions with many closures
+ 2025-07-16 9c507e7942 cmd/link, runtime: on Wasm, put only function index in method table and func table
+ 2025-07-16 9782dcfd16 runtime: use 32-bit function index on Wasm
+ 2025-07-16 c876bf9346 cmd/internal/obj/wasm: use 64-bit instructions for indirect calls
+ 2025-07-15 b4309ece66 cmd/internal/doc: upgrade godoc pkgsite to 01b046e
+ 2025-07-15 75a19dbcd7 runtime: use memclrNoHeapPointers to clear inline mark bits
+ 2025-07-15 6d4a91c7a5 runtime: only clear inline mark bits on span alloc if necessary
+ 2025-07-15 0c6296ab12 runtime: have mergeInlineMarkBits also clear the inline mark bits
+ 2025-07-15 397d2117ec runtime: merge inline mark bits with gcmarkBits 8 bytes at a time
+ 2025-07-15 7dceabd3be runtime/maps: fix typo in group.go comment (instrinsified -> intrinsified)
+ 2025-07-15 d826bf4d74 os: remove useless error check
+ 2025-07-14 bb07e55aff runtime: expand GOMAXPROCS documentation
+ 2025-07-14 9159cd4ec6 encoding/json: decompose legacy options
+ 2025-07-14 c6556b8eb3 encoding/json/v2: add security section to doc
+ 2025-07-11 6ebb5f56d9 runtime: gofmt after CL 643897 and CL 662455
+ 2025-07-11 1e48ca7020 encoding/json: remove legacy option to EscapeInvalidUTF8
+ 2025-07-11 a0a99cb22b encoding/json/v2: report wrapped io.ErrUnexpectedEOF
+ 2025-07-11 9d04122d24 crypto/rsa: drop contradictory promise to keep PublicKey modulus secret
+ 2025-07-11 1ca23682dd crypto/rsa: fix documentation formatting
+ 2025-07-11 4bc3373c8e runtime: turn off large memmove tests under asan/msan
+ 2025-07-11 88cf0c5d55 cmd/link: do size fixups after symbol references are loaded
+ 2025-07-10 7a38975a48 os: trivial comment fix
+ 2025-07-10 aa5de9ebb5 synctest: fix comments for time.Now() in synctests
+ 2025-07-10 63ec70d4e1 crypto/cipher: Fix comment punctuation
+ 2025-07-09 8131635e5a runtime: run TestSignalDuringExec in its own process group
+ 2025-07-09 67c1704444 crypto/tls: empty server_name conf. ext. from server
+ 2025-07-08 54c9d77630 cmd/go: disable support for multiple vcs in one module
+ 2025-07-08 fca43a8436 internal: make struct comment match struct name
+ 2025-07-08 bb917bb030 cmd/compile: document that nosplit directive is unsafe
+ 2025-07-08 a5bda585d5 cmd/compile: run fmt on ssa
+ 2025-07-07 86b5ba7310 internal/trace: only test for sync preemption if async preemption is off
+ 2025-07-07 ef46e1b164 cmd/internal/doc: fix GOROOT skew and path joining bugs
+ 2025-07-07 75b43f9a97 runtime: make traceStack testable and add a benchmark
+ 2025-07-07 20978f46fd crypto/rsa: remove another forgotten note to future self
+ 2025-07-07 33fb4819f5 cmd/compile/internal/ssa: skip EndSequence entries in TestStmtLines
+ 2025-07-07 a995269a93 sort: clarify Less doc
+ 2025-07-03 6c3b5a2798 runtime: correct vdsoSP on S390X
+ 2025-07-03 dd687c3860 hash: document that Clone may only return ErrUnsupported or a nil error
+ 2025-07-02 b325151453 cmd/cgo/internal/testsanitizers: skip asan tests when FIPS140 mode is on
+ 2025-07-02 15d9fe43d6 testing/synctest: explicitly state Run will be removed in Go 1.26
+ 2025-07-01 de646d94f7 cmd/go/internal/modindex: apply changes in CL 502615 to modindex package

Change-Id: I0420eec24c176a76a0ae51ddf6e34ee3fe4ae8ba
2025-07-23 18:53:29 +00:00
Gopher Robot
e73dadc758 [release-branch.go1.25] go1.25rc2
Change-Id: Iaf3a30e4c794c3f58abf429000d41f1c4f2fede1
Reviewed-on: https://go-review.googlesource.com/c/go/+/686456
TryBot-Bypass: Gopher Robot <gobot@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
2025-07-08 10:29:35 -07:00
Roland Shoemaker
2899144b8d [release-branch.go1.25] cmd/go: disable support for multiple vcs in one module
Removes the somewhat redundant vcs.FromDir, "allowNesting" argument,
which was always enabled, and disallow multiple VCS metadata folders
being present in a single directory. This makes VCS injection attacks
much more difficult.

Also adds a GODEBUG, allowmultiplevcs, which re-enables this behavior.

Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc for
reporting this issue.

Fixes #74380
Fixes CVE-2025-4674

Change-Id: I95b619588ecb6661770aa4e1d6023d6cb22e2263
Reviewed-on: https://go-review.googlesource.com/c/go/+/686338
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Carlos Amedee <carlos@golang.org>
TryBot-Bypass: Carlos Amedee <carlos@golang.org>
2025-07-08 09:29:36 -07:00
David Chase
b062eb46e8 [release-branch.go1.25] all: merge master (2f653a5) into release-branch.go1.25
Merge List:

+ 2025-07-01 2f653a5a9e crypto/tls: ensure the ECDSA curve matches the signature algorithm
+ 2025-07-01 6e95fd96cc crypto/ecdsa: fix crypto/x509 godoc links
+ 2025-07-01 7755a05209 Revert "crypto/internal/fips140/subtle: add assembly implementation of xorBytes for arm"
+ 2025-07-01 d168ad18e1 slices: update TestIssue68488 to avoid false positives
+ 2025-07-01 27ad1f5013 internal/abi: fix comment on NonEmptyInterface
+ 2025-06-30 86fca3dcb6 encoding/json/jsontext: use bytes.Buffer.AvailableBuffer
+ 2025-06-30 6bd9944c9a encoding/json/v2: avoid escaping jsonopts.Struct
+ 2025-06-30 e46d586edd cmd/compile/internal/escape: add debug hash for literal allocation optimizations
+ 2025-06-30 479b51ee1f cmd/compile/internal/escape: stop disabling literal allocation optimizations when coverage is enabled
+ 2025-06-30 8002d283e8 crypto/tls: update bogo version
+ 2025-06-30 fdd7713fe5 internal/goexperiment: fix godoc formatting
+ 2025-06-30 740857f529 runtime: stash allpSnapshot on the M
+ 2025-06-30 9ae38be302 sync: disassociate WaitGroups from bubbles on Wait
+ 2025-06-30 4731832342 crypto/hmac: wrap ErrUnsupported returned by Clone
+ 2025-06-30 03ad694dcb runtime: update skips for TestGdbBacktrace
+ 2025-06-30 9d1cd0b881 iter: add missing type parameter in doc
+ 2025-06-29 acb914f2c2 cmd/doc: fix -http on Windows
+ 2025-06-27 b51f1cdb87 runtime: remove arbitrary 5-second timeout in TestNeedmDeadlock
+ 2025-06-27 f1e6ae2f6f reflect: fix TypeAssert on nil interface values
+ 2025-06-27 e81c624656 os: use minimal file permissions when opening parent directory in RemoveAll
+ 2025-06-27 2a22aefa1f encoding/json: add security section to doc
+ 2025-06-27 742fda9524 runtime: account for missing frame pointer in preamble
+ 2025-06-27 fdc076ce76 net/http: fix RoundTrip context cancellation for js/wasm
+ 2025-06-27 d9d2cadd63 encoding/json: fix typo in hotlink for jsontext.PreserveRawStrings
+ 2025-06-26 0f8ab2db17 cmd/link: permit a larger size BSS reference to a smaller DATA symbol
+ 2025-06-26 988a20c8c5 cmd/compile/internal/escape: evaluate any side effects when rewriting with literals
+ 2025-06-25 b5d555991a encoding/json/jsontext: remove Encoder.UnusedBuffer
+ 2025-06-25 0b4d2eab2f encoding/json/jsontext: rename Encoder.UnusedBuffer as Encoder.AvailableBuffer
+ 2025-06-25 f8ccda2e05 runtime: make explicit nil check in (*spanInlineMarkBits).init
+ 2025-06-25 f069a82998 runtime: note custom GOMAXPROCS even if value doesn't change
+ 2025-06-24 e515ef8bc2 context: fix typo in context_test.go
+ 2025-06-24 47b941f445 cmd/link: add one more linkname to the blocklist
+ 2025-06-24 34cf5f6205 go/types: add test for interface method field type
+ 2025-06-24 6e618cd42a encoding/json: use zstd compressed testdata
+ 2025-06-24 fcb9850859 net/http: reduce allocs in CrossOriginProtection.Check
+ 2025-06-24 11f11f2a00 encoding/json/v2: support ISO 8601 durations
+ 2025-06-24 62deaf4fb8 doc: fix links to runtime Environment Variables
+ 2025-06-24 2e9bb62bfe encoding/json/v2: reject unquoted dash as a JSON field name
+ 2025-06-23 ed7815726d encoding/json/v2: report error on time.Duration without explicit format
+ 2025-06-23 f866958246 cmd/dist: test encoding/json/... with GOEXPERIMENT=jsonv2
+ 2025-06-23 f77a0aa6b6 internal/trace: improve gc-stress test
+ 2025-06-23 4506796a6e encoding/json/jsontext: consistently use JSON terminology
+ 2025-06-23 456a90aa16 runtime: add missing unlock in sysReserveAlignedSbrk
+ 2025-06-23 1cf6386b5e Revert "go/types, types2: don't register interface methods in Info.Types map"
+ 2025-06-20 49cdf0c42e testing, testing/synctest: handle T.Helper in synctest bubbles
+ 2025-06-20 3bf1eecbd3 runtime: fix struct comment
+ 2025-06-20 8ed23a2936 crypto/cipher: fix link to crypto/aes
+ 2025-06-20 ef60769b46 go/doc: add a golden test that reproduces #62640
+ 2025-06-18 8552bcf7c2 cmd/go/internal/fips140: ignore GOEXPERIMENT on error
+ 2025-06-18 4c7567290c runtime: set mspan limit field early and eagerly
+ 2025-06-18 c6ac736288 runtime: prevent mutual deadlock between GC stopTheWorld and suspendG
+ 2025-06-17 53af292aed encoding/json/jsontext: fix spelling error
+ 2025-06-16 d058254689 cmd/dist: always include variant in package names
+ 2025-06-16 3254c2bb83 internal/reflectlite: fix comment about meaning of flag field
+ 2025-06-16 816199e421 runtime: don't let readTrace spin on trace.shutdown
+ 2025-06-16 ea00461b17 internal/trace: make Value follow reflect conventions
+ 2025-06-13 96a6e147b2 runtime: comment that some linknames are used by runtime/trace
+ 2025-06-13 644905891f runtime: remove unused unique.runtime_blockUntilEmptyFinalizerQueue
+ 2025-06-13 683810a368 cmd/link: block new standard library linknames
+ 2025-06-12 9149876112 all: replace a few user-visible mentions of golang.org and godoc.org
+ 2025-06-12 934d5f2cf7 internal/trace: end test programs with SIGQUIT
+ 2025-06-12 5a08865de3 net: remove some BUG entries
+ 2025-06-11 d166a0b03e encoding/json/jsontext, encoding/json/v2: document experimental nature
+ 2025-06-11 d4c6effaa7 cmd/compile: add up-to-date test for generated files

Change-Id: I555d5d1bf8c8607fa0660146019657f4c04084e3
2025-07-01 14:01:40 -04:00
Gopher Robot
8ac5714ef2 [release-branch.go1.25] go1.25rc1
Change-Id: I2611db09afd71b4b4811d118ec8c2446de4f8d40
Reviewed-on: https://go-review.googlesource.com/c/go/+/681056
Auto-Submit: Gopher Robot <gobot@golang.org>
TryBot-Bypass: Gopher Robot <gobot@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
2025-06-11 11:56:35 -07:00
Cherry Mui
9546293d22 [release-branch.go1.25] all: merge master (7fa2c73) into release-branch.go1.25
Merge List:

+ 2025-06-10 7fa2c736b3 os: disallow Root.Remove(".") on Plan 9, js, and Windows
+ 2025-06-10 281cfcfc1b runtime: handle system goroutines later in goroutine profiling
+ 2025-06-10 4f86f22671 testing/synctest, runtime: avoid panic when using linker-alloc WG from bubble
+ 2025-06-10 773701a853 internal/trace: pass GOTRACEBACK=crash to testprogs
+ 2025-06-10 fb0c27c514 os: do not follow dangling symlinks in Root when O_CREATE|O_EXCL on AIX
+ 2025-06-10 1cafdfb63b net/http: make the zero value of CrossOriginProtection work
+ 2025-06-10 a35701b352 cmd/dist: only install necessary tools when doing local test
+ 2025-06-10 a189516d3a runtime: don't do a direct G handoff in semrelease on systemstack
+ 2025-06-10 f18d046568 all.{bash,rc}: use "../bin/go tool dist" instead of "%GOTOOLDIR%/dist" print build info
+ 2025-06-09 ee7bfbdbcc cmd/compile/internal/ssa: fix PPC64 merging of (AND (S[RL]Dconst ...)
+ 2025-06-09 985d600f3a runtime: use small struct TestSynctest to ensure cleanups run
+ 2025-06-09 848a768ba7 runtime: clarify stack traces for bubbled goroutines
+ 2025-06-09 049a5e6036 runtime: return a different bubble deadlock error when main goroutine is done
+ 2025-06-09 ac1686752b cmd/internal/doc: increase version of pkgsite doc command that's run

Change-Id: Iba7b2c2f06e91a39fa039c08170e6054e50de3c6
2025-06-11 09:16:16 -04:00
Cherry Mui
4b3a0b9785 [release-branch.go1.25] all: merge master (da0e8c4) into release-branch.go1.25
Merge List:

+ 2025-06-09 da0e8c4517 cmd/compile: relax reshaping condition
+ 2025-06-09 7800f4f0ad log/slog: fix level doc on handlers
+ 2025-06-07 d184f8dc02 runtime: check for gsignal in racecall on loong64
+ 2025-06-06 0ccfbc834a os/signal: doc link to syscall.EPIPE

Change-Id: I4e3cfdb4769207ba87788da1650ed2a1f731ed86
2025-06-09 12:41:15 -04:00
Carlos Amedee
5abb1d84f8 [release-branch.go1.25] update codereview.cfg for release-branch.go1.25
Change-Id: Id2aa864e4549623cc6d98d95028858d41459fa63
Reviewed-on: https://go-review.googlesource.com/c/go/+/679176
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-06-06 12:45:11 -07:00
28 changed files with 489 additions and 158 deletions

2
VERSION Normal file
View File

@@ -0,0 +1,2 @@
go1.25.1
time 2025-08-27T15:49:40Z

View File

@@ -1 +1,2 @@
branch: master
branch: release-branch.go1.25
parent-branch: master

View File

@@ -109,6 +109,9 @@ func ModIsPrefix(path, vers string) bool {
// The caller is assumed to have checked that ModIsValid(path, vers) is true.
func ModIsPrerelease(path, vers string) bool {
if IsToolchain(path) {
if path == "toolchain" {
return IsPrerelease(FromToolchain(vers))
}
return IsPrerelease(vers)
}
return semver.Prerelease(vers) != ""

View File

@@ -277,6 +277,29 @@ func loadModTool(ctx context.Context, name string) string {
return ""
}
func builtTool(runAction *work.Action) string {
linkAction := runAction.Deps[0]
if toolN {
// #72824: If -n is set, use the cached path if we can.
// This is only necessary if the binary wasn't cached
// before this invocation of the go command: if the binary
// was cached, BuiltTarget() will be the cached executable.
// It's only in the "first run", where we actually do the build
// and save the result to the cache that BuiltTarget is not
// the cached binary. Ideally, we would set BuiltTarget
// to the cached path even in the first run, but if we
// copy the binary to the cached path, and try to run it
// in the same process, we'll run into the dreaded #22315
// resulting in occasional ETXTBSYs. Instead of getting the
// ETXTBSY and then retrying just don't use the cached path
// on the first run if we're going to actually run the binary.
if cached := linkAction.CachedExecutable(); cached != "" {
return cached
}
}
return linkAction.BuiltTarget()
}
func buildAndRunBuiltinTool(ctx context.Context, toolName, tool string, args []string) {
// Override GOOS and GOARCH for the build to build the tool using
// the same GOOS and GOARCH as this go command.
@@ -288,7 +311,7 @@ func buildAndRunBuiltinTool(ctx context.Context, toolName, tool string, args []s
modload.RootMode = modload.NoRoot
runFunc := func(b *work.Builder, ctx context.Context, a *work.Action) error {
cmdline := str.StringList(a.Deps[0].BuiltTarget(), a.Args)
cmdline := str.StringList(builtTool(a), a.Args)
return runBuiltTool(toolName, nil, cmdline)
}
@@ -300,7 +323,7 @@ func buildAndRunModtool(ctx context.Context, toolName, tool string, args []strin
// Use the ExecCmd to run the binary, as go run does. ExecCmd allows users
// to provide a runner to run the binary, for example a simulator for binaries
// that are cross-compiled to a different platform.
cmdline := str.StringList(work.FindExecCmd(), a.Deps[0].BuiltTarget(), a.Args)
cmdline := str.StringList(work.FindExecCmd(), builtTool(a), a.Args)
// Use same environment go run uses to start the executable:
// the original environment with cfg.GOROOTbin added to the path.
env := slices.Clip(cfg.OrigEnv)

View File

@@ -97,11 +97,12 @@ type Action struct {
CacheExecutable bool // Whether to cache executables produced by link steps
// Generated files, directories.
Objdir string // directory for intermediate objects
Target string // goal of the action: the created package or executable
built string // the actual created package or executable
actionID cache.ActionID // cache ID of action input
buildID string // build ID of action output
Objdir string // directory for intermediate objects
Target string // goal of the action: the created package or executable
built string // the actual created package or executable
cachedExecutable string // the cached executable, if CacheExecutable was set
actionID cache.ActionID // cache ID of action input
buildID string // build ID of action output
VetxOnly bool // Mode=="vet": only being called to supply info about dependencies
needVet bool // Mode=="build": need to fill in vet config
@@ -133,6 +134,10 @@ func (a *Action) BuildID() string { return a.buildID }
// from Target when the result was cached.
func (a *Action) BuiltTarget() string { return a.built }
// CachedExecutable returns the cached executable, if CacheExecutable
// was set and the executable could be cached, and "" otherwise.
func (a *Action) CachedExecutable() string { return a.cachedExecutable }
// An actionQueue is a priority queue of actions.
type actionQueue []*Action

View File

@@ -745,8 +745,9 @@ func (b *Builder) updateBuildID(a *Action, target string) error {
}
outputID, _, err := c.PutExecutable(a.actionID, name+cfg.ExeSuffix, r)
r.Close()
a.cachedExecutable = c.OutputFile(outputID)
if err == nil && cfg.BuildX {
sh.ShowCmd("", "%s # internal", joinUnambiguously(str.StringList("cp", target, c.OutputFile(outputID))))
sh.ShowCmd("", "%s # internal", joinUnambiguously(str.StringList("cp", target, a.cachedExecutable)))
}
}
}

View File

@@ -94,12 +94,14 @@ stderr '^go: added toolchain go1.24rc1$'
grep 'go 1.22.9' go.mod # no longer implied
grep 'toolchain go1.24rc1' go.mod
# go get toolchain@latest finds go1.999testmod.
# go get toolchain@latest finds go1.23.9.
cp go.mod.orig go.mod
go get toolchain@latest
stderr '^go: added toolchain go1.999testmod$'
stderr '^go: added toolchain go1.23.9$'
grep 'go 1.21' go.mod
grep 'toolchain go1.999testmod' go.mod
grep 'toolchain go1.23.9' go.mod
# Bug fixes.
@@ -115,7 +117,7 @@ stderr '^go: upgraded go 1.19 => 1.21.0'
# go get toolchain@1.24rc1 is OK too.
go get toolchain@1.24rc1
stderr '^go: downgraded toolchain go1.999testmod => go1.24rc1$'
stderr '^go: upgraded toolchain go1.23.9 => go1.24rc1$'
# go get go@1.21 should work if we are the Go 1.21 language version,
# even though there's no toolchain for it.

View File

@@ -0,0 +1,27 @@
[short] skip 'does a build in using an empty cache'
# Start with a fresh cache because we want to verify the behavior
# when the tool hasn't been cached previously.
env GOCACHE=$WORK${/}cache
# Even when the tool hasn't been previously cached but was built and
# saved to the cache in the invocation of 'go tool -n' we should return
# its cached location.
go tool -n foo
stdout $GOCACHE
# And of course we should also return the cached location on subsequent
# runs.
go tool -n foo
stdout $GOCACHE
-- go.mod --
module example.com/foo
go 1.25
tool example.com/foo
-- main.go --
package main
func main() {}

View File

@@ -335,7 +335,6 @@ func convertAssignRows(dest, src any, rows *Rows) error {
if rows == nil {
return errors.New("invalid context to convert cursor rows, missing parent *Rows")
}
rows.closemu.Lock()
*d = Rows{
dc: rows.dc,
releaseConn: func(error) {},
@@ -351,7 +350,6 @@ func convertAssignRows(dest, src any, rows *Rows) error {
parentCancel()
}
}
rows.closemu.Unlock()
return nil
}
}

View File

@@ -5,6 +5,7 @@
package sql
import (
"bytes"
"context"
"database/sql/driver"
"errors"
@@ -15,7 +16,6 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"testing"
"time"
)
@@ -91,8 +91,6 @@ func (cc *fakeDriverCtx) OpenConnector(name string) (driver.Connector, error) {
type fakeDB struct {
name string
useRawBytes atomic.Bool
mu sync.Mutex
tables map[string]*table
badConn bool
@@ -684,8 +682,6 @@ func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stm
switch cmd {
case "WIPE":
// Nothing
case "USE_RAWBYTES":
c.db.useRawBytes.Store(true)
case "SELECT":
stmt, err = c.prepareSelect(stmt, parts)
case "CREATE":
@@ -789,9 +785,6 @@ func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (d
case "WIPE":
db.wipe()
return driver.ResultNoRows, nil
case "USE_RAWBYTES":
s.c.db.useRawBytes.Store(true)
return driver.ResultNoRows, nil
case "CREATE":
if err := db.createTable(s.table, s.colName, s.colType); err != nil {
return nil, err
@@ -1076,10 +1069,9 @@ type rowsCursor struct {
errPos int
err error
// a clone of slices to give out to clients, indexed by the
// original slice's first byte address. we clone them
// just so we're able to corrupt them on close.
bytesClone map[*byte][]byte
// Data returned to clients.
// We clone and stash it here so it can be invalidated by Close and Next.
driverOwnedMemory [][]byte
// Every operation writes to line to enable the race detector
// check for data races.
@@ -1096,9 +1088,19 @@ func (rc *rowsCursor) touchMem() {
rc.line++
}
func (rc *rowsCursor) invalidateDriverOwnedMemory() {
for _, buf := range rc.driverOwnedMemory {
for i := range buf {
buf[i] = 'x'
}
}
rc.driverOwnedMemory = nil
}
func (rc *rowsCursor) Close() error {
rc.touchMem()
rc.parentMem.touchMem()
rc.invalidateDriverOwnedMemory()
rc.closed = true
return rc.closeErr
}
@@ -1129,6 +1131,8 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
if rc.posRow >= len(rc.rows[rc.posSet]) {
return io.EOF // per interface spec
}
// Corrupt any previously returned bytes.
rc.invalidateDriverOwnedMemory()
for i, v := range rc.rows[rc.posSet][rc.posRow].cols {
// TODO(bradfitz): convert to subset types? naah, I
// think the subset types should only be input to
@@ -1136,20 +1140,13 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
// a wider range of types coming out of drivers. all
// for ease of drivers, and to prevent drivers from
// messing up conversions or doing them differently.
dest[i] = v
if bs, ok := v.([]byte); ok && !rc.db.useRawBytes.Load() {
if rc.bytesClone == nil {
rc.bytesClone = make(map[*byte][]byte)
}
clone, ok := rc.bytesClone[&bs[0]]
if !ok {
clone = make([]byte, len(bs))
copy(clone, bs)
rc.bytesClone[&bs[0]] = clone
}
dest[i] = clone
if bs, ok := v.([]byte); ok {
// Clone []bytes and stash for later invalidation.
bs = bytes.Clone(bs)
rc.driverOwnedMemory = append(rc.driverOwnedMemory, bs)
v = bs
}
dest[i] = v
}
return nil
}

View File

@@ -3368,38 +3368,36 @@ func (rs *Rows) Scan(dest ...any) error {
// without calling Next.
return fmt.Errorf("sql: Scan called without calling Next (closemuScanHold)")
}
rs.closemu.RLock()
if rs.lasterr != nil && rs.lasterr != io.EOF {
rs.closemu.RUnlock()
return rs.lasterr
}
if rs.closed {
err := rs.lasterrOrErrLocked(errRowsClosed)
rs.closemu.RUnlock()
return err
}
if scanArgsContainRawBytes(dest) {
rs.raw = rs.raw[:0]
err := rs.scanLocked(dest...)
if err == nil && scanArgsContainRawBytes(dest) {
rs.closemuScanHold = true
rs.raw = rs.raw[:0]
} else {
rs.closemu.RUnlock()
}
return err
}
func (rs *Rows) scanLocked(dest ...any) error {
if rs.lasterr != nil && rs.lasterr != io.EOF {
return rs.lasterr
}
if rs.closed {
return rs.lasterrOrErrLocked(errRowsClosed)
}
if rs.lastcols == nil {
rs.closemuRUnlockIfHeldByScan()
return errors.New("sql: Scan called without calling Next")
}
if len(dest) != len(rs.lastcols) {
rs.closemuRUnlockIfHeldByScan()
return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
}
for i, sv := range rs.lastcols {
err := convertAssignRows(dest[i], sv, rs)
if err != nil {
rs.closemuRUnlockIfHeldByScan()
return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err)
}
}

View File

@@ -5,6 +5,7 @@
package sql
import (
"bytes"
"context"
"database/sql/driver"
"errors"
@@ -4434,10 +4435,6 @@ func testContextCancelDuringRawBytesScan(t *testing.T, mode string) {
db := newTestDB(t, "people")
defer closeDB(t, db)
if _, err := db.Exec("USE_RAWBYTES"); err != nil {
t.Fatal(err)
}
// cancel used to call close asynchronously.
// This test checks that it waits so as not to interfere with RawBytes.
ctx, cancel := context.WithCancel(context.Background())
@@ -4529,6 +4526,61 @@ func TestContextCancelBetweenNextAndErr(t *testing.T) {
}
}
type testScanner struct {
scanf func(src any) error
}
func (ts testScanner) Scan(src any) error { return ts.scanf(src) }
func TestContextCancelDuringScan(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
scanStart := make(chan any)
scanEnd := make(chan error)
scanner := &testScanner{
scanf: func(src any) error {
scanStart <- src
return <-scanEnd
},
}
// Start a query, and pause it mid-scan.
want := []byte("Alice")
r, err := db.QueryContext(ctx, "SELECT|people|name|name=?", string(want))
if err != nil {
t.Fatal(err)
}
if !r.Next() {
t.Fatalf("r.Next() = false, want true")
}
go func() {
r.Scan(scanner)
}()
got := <-scanStart
defer close(scanEnd)
gotBytes, ok := got.([]byte)
if !ok {
t.Fatalf("r.Scan returned %T, want []byte", got)
}
if !bytes.Equal(gotBytes, want) {
t.Fatalf("before cancel: r.Scan returned %q, want %q", gotBytes, want)
}
// Cancel the query.
// Sleep to give it a chance to finish canceling.
cancel()
time.Sleep(10 * time.Millisecond)
// Cancelling the query should not have changed the result.
if !bytes.Equal(gotBytes, want) {
t.Fatalf("after cancel: r.Scan result is now %q, want %q", gotBytes, want)
}
}
func TestNilErrorAfterClose(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
@@ -4562,10 +4614,6 @@ func TestRawBytesReuse(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
if _, err := db.Exec("USE_RAWBYTES"); err != nil {
t.Fatal(err)
}
var raw RawBytes
// The RawBytes in this query aliases driver-owned memory.

View File

@@ -1106,6 +1106,12 @@ func (fd *FD) Seek(offset int64, whence int) (int64, error) {
fd.l.Lock()
defer fd.l.Unlock()
if !fd.isBlocking && whence == io.SeekCurrent {
// Windows doesn't keep the file pointer for overlapped file handles.
// We do it ourselves in case to account for any read or write
// operations that may have occurred.
offset += fd.offset
}
n, err := syscall.Seek(fd.Sysfd, offset, whence)
fd.setOffset(n)
return n, err

View File

@@ -383,57 +383,59 @@ func TestChannelMovedOutOfBubble(t *testing.T) {
for _, test := range []struct {
desc string
f func(chan struct{})
wantPanic string
wantFatal string
}{{
desc: "receive",
f: func(ch chan struct{}) {
<-ch
},
wantPanic: "receive on synctest channel from outside bubble",
wantFatal: "receive on synctest channel from outside bubble",
}, {
desc: "send",
f: func(ch chan struct{}) {
ch <- struct{}{}
},
wantPanic: "send on synctest channel from outside bubble",
wantFatal: "send on synctest channel from outside bubble",
}, {
desc: "close",
f: func(ch chan struct{}) {
close(ch)
},
wantPanic: "close of synctest channel from outside bubble",
wantFatal: "close of synctest channel from outside bubble",
}} {
t.Run(test.desc, func(t *testing.T) {
// Bubbled channel accessed from outside any bubble.
t.Run("outside_bubble", func(t *testing.T) {
donec := make(chan struct{})
ch := make(chan chan struct{})
go func() {
defer close(donec)
defer wantPanic(t, test.wantPanic)
test.f(<-ch)
}()
synctest.Run(func() {
ch <- make(chan struct{})
wantFatal(t, test.wantFatal, func() {
donec := make(chan struct{})
ch := make(chan chan struct{})
go func() {
defer close(donec)
test.f(<-ch)
}()
synctest.Run(func() {
ch <- make(chan struct{})
})
<-donec
})
<-donec
})
// Bubbled channel accessed from a different bubble.
t.Run("different_bubble", func(t *testing.T) {
donec := make(chan struct{})
ch := make(chan chan struct{})
go func() {
defer close(donec)
c := <-ch
wantFatal(t, test.wantFatal, func() {
donec := make(chan struct{})
ch := make(chan chan struct{})
go func() {
defer close(donec)
c := <-ch
synctest.Run(func() {
test.f(c)
})
}()
synctest.Run(func() {
defer wantPanic(t, test.wantPanic)
test.f(c)
ch <- make(chan struct{})
})
}()
synctest.Run(func() {
ch <- make(chan struct{})
<-donec
})
<-donec
})
})
}
@@ -443,39 +445,40 @@ func TestTimerFromInsideBubble(t *testing.T) {
for _, test := range []struct {
desc string
f func(tm *time.Timer)
wantPanic string
wantFatal string
}{{
desc: "read channel",
f: func(tm *time.Timer) {
<-tm.C
},
wantPanic: "receive on synctest channel from outside bubble",
wantFatal: "receive on synctest channel from outside bubble",
}, {
desc: "Reset",
f: func(tm *time.Timer) {
tm.Reset(1 * time.Second)
},
wantPanic: "reset of synctest timer from outside bubble",
wantFatal: "reset of synctest timer from outside bubble",
}, {
desc: "Stop",
f: func(tm *time.Timer) {
tm.Stop()
},
wantPanic: "stop of synctest timer from outside bubble",
wantFatal: "stop of synctest timer from outside bubble",
}} {
t.Run(test.desc, func(t *testing.T) {
donec := make(chan struct{})
ch := make(chan *time.Timer)
go func() {
defer close(donec)
defer wantPanic(t, test.wantPanic)
test.f(<-ch)
}()
synctest.Run(func() {
tm := time.NewTimer(1 * time.Second)
ch <- tm
wantFatal(t, test.wantFatal, func() {
donec := make(chan struct{})
ch := make(chan *time.Timer)
go func() {
defer close(donec)
test.f(<-ch)
}()
synctest.Run(func() {
tm := time.NewTimer(1 * time.Second)
ch <- tm
})
<-donec
})
<-donec
})
}
}

View File

@@ -77,13 +77,21 @@ func (c *CrossOriginProtection) AddTrustedOrigin(origin string) error {
return nil
}
var noopHandler = HandlerFunc(func(w ResponseWriter, r *Request) {})
type noopHandler struct{}
func (noopHandler) ServeHTTP(ResponseWriter, *Request) {}
var sentinelHandler Handler = &noopHandler{}
// AddInsecureBypassPattern permits all requests that match the given pattern.
// The pattern syntax and precedence rules are the same as [ServeMux].
//
// AddInsecureBypassPattern can be called concurrently with other methods
// or request handling, and applies to future requests.
// The pattern syntax and precedence rules are the same as [ServeMux]. Only
// requests that match the pattern directly are permitted. Those that ServeMux
// would redirect to a pattern (e.g. after cleaning the path or adding a
// trailing slash) are not.
//
// AddInsecureBypassPattern can be called concurrently with other methods or
// request handling, and applies to future requests.
func (c *CrossOriginProtection) AddInsecureBypassPattern(pattern string) {
var bypass *ServeMux
@@ -99,7 +107,7 @@ func (c *CrossOriginProtection) AddInsecureBypassPattern(pattern string) {
}
}
bypass.Handle(pattern, noopHandler)
bypass.Handle(pattern, sentinelHandler)
}
// SetDenyHandler sets a handler to invoke when a request is rejected.
@@ -172,7 +180,7 @@ var (
// be deferred until the last moment.
func (c *CrossOriginProtection) isRequestExempt(req *Request) bool {
if bypass := c.bypass.Load(); bypass != nil {
if _, pattern := bypass.Handler(req); pattern != "" {
if h, _ := bypass.Handler(req); h == sentinelHandler {
// The request matches a bypass pattern.
return true
}

View File

@@ -113,6 +113,11 @@ func TestCrossOriginProtectionPatternBypass(t *testing.T) {
protection := http.NewCrossOriginProtection()
protection.AddInsecureBypassPattern("/bypass/")
protection.AddInsecureBypassPattern("/only/{foo}")
protection.AddInsecureBypassPattern("/no-trailing")
protection.AddInsecureBypassPattern("/yes-trailing/")
protection.AddInsecureBypassPattern("PUT /put-only/")
protection.AddInsecureBypassPattern("GET /get-only/")
protection.AddInsecureBypassPattern("POST /post-only/")
handler := protection.Handler(okHandler)
tests := []struct {
@@ -126,13 +131,23 @@ func TestCrossOriginProtectionPatternBypass(t *testing.T) {
{"non-bypass path without sec-fetch-site", "/api/", "", http.StatusForbidden},
{"non-bypass path with cross-site", "/api/", "cross-site", http.StatusForbidden},
{"redirect to bypass path without ..", "/foo/../bypass/bar", "", http.StatusOK},
{"redirect to bypass path with trailing slash", "/bypass", "", http.StatusOK},
{"redirect to bypass path without ..", "/foo/../bypass/bar", "", http.StatusForbidden},
{"redirect to bypass path with trailing slash", "/bypass", "", http.StatusForbidden},
{"redirect to non-bypass path with ..", "/foo/../api/bar", "", http.StatusForbidden},
{"redirect to non-bypass path with trailing slash", "/api", "", http.StatusForbidden},
{"wildcard bypass", "/only/123", "", http.StatusOK},
{"non-wildcard", "/only/123/foo", "", http.StatusForbidden},
// https://go.dev/issue/75054
{"no trailing slash exact match", "/no-trailing", "", http.StatusOK},
{"no trailing slash with slash", "/no-trailing/", "", http.StatusForbidden},
{"yes trailing slash exact match", "/yes-trailing/", "", http.StatusOK},
{"yes trailing slash without slash", "/yes-trailing", "", http.StatusForbidden},
{"method-specific hit", "/post-only/", "", http.StatusOK},
{"method-specific miss (PUT)", "/put-only/", "", http.StatusForbidden},
{"method-specific miss (GET)", "/get-only/", "", http.StatusForbidden},
}
for _, tc := range tests {

View File

@@ -237,8 +237,12 @@ func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, e
func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) {
// ipToSockaddrInet4 has special handling here for zero length slices.
// We do not, because netip has no concept of a generic zero IP address.
//
// addr is allowed to be an IPv4-mapped IPv6 address.
// As4 will unmap it to an IPv4 address.
// The error message is kept consistent with ipToSockaddrInet4.
addr := ap.Addr()
if !addr.Is4() {
if !addr.Is4() && !addr.Is4In6() {
return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: addr.String()}
}
sa := syscall.SockaddrInet4{

View File

@@ -705,3 +705,35 @@ func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
t.Fatal(err)
}
}
// TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion verifies that
// WriteMsgUDPAddrPort accepts IPv4 and IPv4-mapped IPv6 destination addresses,
// and rejects IPv6 destination addresses on a "udp4" connection.
func TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
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()
daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345)
daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345)
daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345)
buf := make([]byte, 8)
if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4); err != nil {
t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4) failed: %v", err)
}
if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6); err != nil {
t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6) failed: %v", err)
}
if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6); err == nil {
t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr6) should have failed, but got no error")
}
}

View File

@@ -177,4 +177,48 @@ func TestLookPath(t *testing.T) {
}
}
})
checker := func(test string) func(t *testing.T) {
return func(t *testing.T) {
t.Helper()
t.Logf("PATH=%s", os.Getenv("PATH"))
p, err := LookPath(test)
if err == nil {
t.Errorf("%q: error expected, got nil", test)
}
if p != "" {
t.Errorf("%q: path returned should be \"\". Got %q", test, p)
}
}
}
// Reference behavior for the next test
t.Run(pathVar+"=$OTHER2", func(t *testing.T) {
t.Run("empty", checker(""))
t.Run("dot", checker("."))
t.Run("dotdot1", checker("abc/.."))
t.Run("dotdot2", checker(".."))
})
// Test the behavior when PATH contains an executable file which is not a directory
t.Run(pathVar+"=exe", func(t *testing.T) {
// Inject an executable file (not a directory) in PATH.
// Use our own binary os.Args[0].
t.Setenv(pathVar, testenv.Executable(t))
t.Run("empty", checker(""))
t.Run("dot", checker("."))
t.Run("dotdot1", checker("abc/.."))
t.Run("dotdot2", checker(".."))
})
// Test the behavior when PATH contains an executable file which is not a directory
t.Run(pathVar+"=exe/xx", func(t *testing.T) {
// Inject an executable file (not a directory) in PATH.
// Use our own binary os.Args[0].
t.Setenv(pathVar, filepath.Join(testenv.Executable(t), "xx"))
t.Run("empty", checker(""))
t.Run("dot", checker("."))
t.Run("dotdot1", checker("abc/.."))
t.Run("dotdot2", checker(".."))
})
}

View File

@@ -1328,3 +1328,13 @@ func addCriticalEnv(env []string) []string {
// Code should use errors.Is(err, ErrDot), not err == ErrDot,
// to test whether a returned error err is due to this condition.
var ErrDot = errors.New("cannot run executable found relative to current directory")
// validateLookPath excludes paths that can't be valid
// executable names. See issue #74466 and CVE-2025-47906.
func validateLookPath(s string) error {
switch s {
case "", ".", "..":
return ErrNotFound
}
return nil
}

View File

@@ -36,6 +36,10 @@ func findExecutable(file string) error {
// As of Go 1.19, LookPath will instead return that path along with an error satisfying
// [errors.Is](err, [ErrDot]). See the package documentation for more details.
func LookPath(file string) (string, error) {
if err := validateLookPath(filepath.Clean(file)); err != nil {
return "", &Error{file, err}
}
// skip the path lookup for these prefixes
skip := []string{"/", "#", "./", "../"}

View File

@@ -54,6 +54,10 @@ func LookPath(file string) (string, error) {
// (only bypass the path if file begins with / or ./ or ../)
// but that would not match all the Unix shells.
if err := validateLookPath(file); err != nil {
return "", &Error{file, err}
}
if strings.Contains(file, "/") {
err := findExecutable(file)
if err == nil {

View File

@@ -67,6 +67,10 @@ func findExecutable(file string, exts []string) (string, error) {
// As of Go 1.19, LookPath will instead return that path along with an error satisfying
// [errors.Is](err, [ErrDot]). See the package documentation for more details.
func LookPath(file string) (string, error) {
if err := validateLookPath(file); err != nil {
return "", &Error{file, err}
}
return lookPath(file, pathExt())
}
@@ -80,6 +84,10 @@ func LookPath(file string) (string, error) {
// "C:\foo\example.com" would be returned as-is even if the
// program is actually "C:\foo\example.com.exe".
func lookExtensions(path, dir string) (string, error) {
if err := validateLookPath(path); err != nil {
return "", &Error{path, err}
}
if filepath.Base(path) == path {
path = "." + string(filepath.Separator) + path
}

View File

@@ -1845,6 +1845,44 @@ func TestFile(t *testing.T) {
}
}
func TestFileOverlappedSeek(t *testing.T) {
t.Parallel()
name := filepath.Join(t.TempDir(), "foo")
f := newFileOverlapped(t, name, true)
content := []byte("foo")
if _, err := f.Write(content); err != nil {
t.Fatal(err)
}
// Check that the file pointer is at the expected offset.
n, err := f.Seek(0, io.SeekCurrent)
if err != nil {
t.Fatal(err)
}
if n != int64(len(content)) {
t.Errorf("expected file pointer to be at offset %d, got %d", len(content), n)
}
// Set the file pointer to the start of the file.
if _, err := f.Seek(0, io.SeekStart); err != nil {
t.Fatal(err)
}
// Read the first byte.
var buf [1]byte
if _, err := f.Read(buf[:]); err != nil {
t.Fatal(err)
}
if !bytes.Equal(buf[:], content[:len(buf)]) {
t.Errorf("expected %q, got %q", content[:len(buf)], buf[:])
}
// Check that the file pointer is at the expected offset.
n, err = f.Seek(0, io.SeekCurrent)
if err != nil {
t.Fatal(err)
}
if n != int64(len(buf)) {
t.Errorf("expected file pointer to be at offset %d, got %d", len(buf), n)
}
}
func TestPipe(t *testing.T) {
t.Parallel()
r, w, err := os.Pipe()

View File

@@ -7,6 +7,7 @@ package user
import (
"crypto/rand"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"internal/syscall/windows"
@@ -16,11 +17,92 @@ import (
"runtime"
"slices"
"strconv"
"strings"
"syscall"
"testing"
"unicode"
"unicode/utf8"
"unsafe"
)
// addUserAccount creates a local user account.
// It returns the name and password of the new account.
// Multiple programs or goroutines calling addUserAccount simultaneously will not choose the same directory.
func addUserAccount(t *testing.T) (name, password string) {
t.TempDir()
pattern := t.Name()
// Windows limits the user name to 20 characters,
// leave space for a 4 digits random suffix.
const maxNameLen, suffixLen = 20, 4
pattern = pattern[:min(len(pattern), maxNameLen-suffixLen)]
// Drop unusual characters from the account name.
mapper := func(r rune) rune {
if r < utf8.RuneSelf {
if '0' <= r && r <= '9' ||
'a' <= r && r <= 'z' ||
'A' <= r && r <= 'Z' {
return r
}
} else if unicode.IsLetter(r) || unicode.IsNumber(r) {
return r
}
return -1
}
pattern = strings.Map(mapper, pattern)
// Generate a long random password.
var pwd [33]byte
rand.Read(pwd[:])
// Add special chars to ensure it satisfies password requirements.
password = base64.StdEncoding.EncodeToString(pwd[:]) + "_-As@!%*(1)4#2"
password16, err := syscall.UTF16PtrFromString(password)
if err != nil {
t.Fatal(err)
}
try := 0
for {
// Calculate a random suffix to append to the user name.
var suffix [2]byte
rand.Read(suffix[:])
suffixStr := strconv.FormatUint(uint64(binary.LittleEndian.Uint16(suffix[:])), 10)
name := pattern + suffixStr[:min(len(suffixStr), suffixLen)]
name16, err := syscall.UTF16PtrFromString(name)
if err != nil {
t.Fatal(err)
}
// Create user.
userInfo := windows.UserInfo1{
Name: name16,
Password: password16,
Priv: windows.USER_PRIV_USER,
}
err = windows.NetUserAdd(nil, 1, (*byte)(unsafe.Pointer(&userInfo)), nil)
if errors.Is(err, syscall.ERROR_ACCESS_DENIED) {
t.Skip("skipping test; don't have permission to create user")
}
// If the user already exists, try again with a different name.
if errors.Is(err, windows.NERR_UserExists) {
if try++; try < 1000 {
t.Log("user already exists, trying again with a different name")
continue
}
}
if err != nil {
t.Fatalf("NetUserAdd failed: %v", err)
}
// Delete the user when the test is done.
t.Cleanup(func() {
if err := windows.NetUserDel(nil, name16); err != nil {
if !errors.Is(err, windows.NERR_UserNotFound) {
t.Fatal(err)
}
}
})
return name, password
}
}
// windowsTestAccount creates a test user and returns a token for that user.
// If the user already exists, it will be deleted and recreated.
// The caller is responsible for closing the token.
@@ -32,47 +114,15 @@ func windowsTestAccount(t *testing.T) (syscall.Token, *User) {
// See https://dev.go/issue/70396.
t.Skip("skipping non-hermetic test outside of Go builders")
}
const testUserName = "GoStdTestUser01"
var password [33]byte
rand.Read(password[:])
// Add special chars to ensure it satisfies password requirements.
pwd := base64.StdEncoding.EncodeToString(password[:]) + "_-As@!%*(1)4#2"
name, err := syscall.UTF16PtrFromString(testUserName)
name, password := addUserAccount(t)
name16, err := syscall.UTF16PtrFromString(name)
if err != nil {
t.Fatal(err)
}
pwd16, err := syscall.UTF16PtrFromString(pwd)
pwd16, err := syscall.UTF16PtrFromString(password)
if err != nil {
t.Fatal(err)
}
userInfo := windows.UserInfo1{
Name: name,
Password: pwd16,
Priv: windows.USER_PRIV_USER,
}
// Create user.
err = windows.NetUserAdd(nil, 1, (*byte)(unsafe.Pointer(&userInfo)), nil)
if errors.Is(err, syscall.ERROR_ACCESS_DENIED) {
t.Skip("skipping test; don't have permission to create user")
}
if errors.Is(err, windows.NERR_UserExists) {
// User already exists, delete and recreate.
if err = windows.NetUserDel(nil, name); err != nil {
t.Fatal(err)
}
if err = windows.NetUserAdd(nil, 1, (*byte)(unsafe.Pointer(&userInfo)), nil); err != nil {
t.Fatal(err)
}
} else if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
if err = windows.NetUserDel(nil, name); err != nil {
if !errors.Is(err, windows.NERR_UserNotFound) {
t.Fatal(err)
}
}
})
domain, err := syscall.UTF16PtrFromString(".")
if err != nil {
t.Fatal(err)
@@ -80,13 +130,13 @@ func windowsTestAccount(t *testing.T) (syscall.Token, *User) {
const LOGON32_PROVIDER_DEFAULT = 0
const LOGON32_LOGON_INTERACTIVE = 2
var token syscall.Token
if err = windows.LogonUser(name, domain, pwd16, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &token); err != nil {
if err = windows.LogonUser(name16, domain, pwd16, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &token); err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
token.Close()
})
usr, err := Lookup(testUserName)
usr, err := Lookup(name)
if err != nil {
t.Fatal(err)
}

View File

@@ -191,7 +191,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
}
if c.bubble != nil && getg().bubble != c.bubble {
panic(plainError("send on synctest channel from outside bubble"))
fatal("send on synctest channel from outside bubble")
}
// Fast path: check for failed non-blocking operation without acquiring the lock.
@@ -318,7 +318,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
func send(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func(), skip int) {
if c.bubble != nil && getg().bubble != c.bubble {
unlockf()
panic(plainError("send on synctest channel from outside bubble"))
fatal("send on synctest channel from outside bubble")
}
if raceenabled {
if c.dataqsiz == 0 {
@@ -416,7 +416,7 @@ func closechan(c *hchan) {
panic(plainError("close of nil channel"))
}
if c.bubble != nil && getg().bubble != c.bubble {
panic(plainError("close of synctest channel from outside bubble"))
fatal("close of synctest channel from outside bubble")
}
lock(&c.lock)
@@ -538,7 +538,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
}
if c.bubble != nil && getg().bubble != c.bubble {
panic(plainError("receive on synctest channel from outside bubble"))
fatal("receive on synctest channel from outside bubble")
}
if c.timer != nil {
@@ -702,7 +702,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func(), skip int) {
if c.bubble != nil && getg().bubble != c.bubble {
unlockf()
panic(plainError("receive on synctest channel from outside bubble"))
fatal("receive on synctest channel from outside bubble")
}
if c.dataqsiz == 0 {
if raceenabled {

View File

@@ -178,7 +178,7 @@ func selectgo(cas0 *scase, order0 *uint16, pc0 *uintptr, nsends, nrecvs int, blo
if cas.c.bubble != nil {
if getg().bubble != cas.c.bubble {
panic(plainError("select on synctest channel from outside bubble"))
fatal("select on synctest channel from outside bubble")
}
} else {
allSynctest = false

View File

@@ -415,7 +415,7 @@ func newTimer(when, period int64, f func(arg any, seq uintptr, delay int64), arg
//go:linkname stopTimer time.stopTimer
func stopTimer(t *timeTimer) bool {
if t.isFake && getg().bubble == nil {
panic("stop of synctest timer from outside bubble")
fatal("stop of synctest timer from outside bubble")
}
return t.stop()
}
@@ -430,7 +430,7 @@ func resetTimer(t *timeTimer, when, period int64) bool {
racerelease(unsafe.Pointer(&t.timer))
}
if t.isFake && getg().bubble == nil {
panic("reset of synctest timer from outside bubble")
fatal("reset of synctest timer from outside bubble")
}
return t.reset(when, period)
}