Skip to content

Commit 0c028ef

Browse files
committed
Merge remote-tracking branch 'go/release-branch.go1.25' into update-go1.25.6
2 parents 7232d92 + 69801b2 commit 0c028ef

51 files changed

Lines changed: 887 additions & 448 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

VERSION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
go1.25.5
2-
time 2025-11-26T02:01:51Z
1+
go1.25.6
2+
time 2026-01-08T21:56:04Z

doc/godebug.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@ will fail early. The default value is `httpcookiemaxnum=3000`. Setting
163163
number of cookies. To avoid denial of service attacks, this setting and default
164164
was backported to Go 1.25.2 and Go 1.24.8.
165165

166+
Go 1.26 added a new `urlmaxqueryparams` setting that controls the maximum number
167+
of query parameters that net/url will accept when parsing a URL-encoded query string.
168+
If the number of parameters exceeds the number set in `urlmaxqueryparams`,
169+
parsing will fail early. The default value is `urlmaxqueryparams=10000`.
170+
Setting `urlmaxqueryparams=0`bles the limit. To avoid denial of service attacks,
171+
this setting and default was backported to Go 1.25.4 and Go 1.24.10.
172+
166173
### Go 1.25
167174

168175
Go 1.25 added a new `decoratemappings` setting that controls whether the Go

src/archive/zip/reader.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,16 @@ func (r *Reader) initFileList() {
834834
continue
835835
}
836836

837-
for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
837+
dir := name
838+
for {
839+
if idx := strings.LastIndex(dir, "/"); idx < 0 {
840+
break
841+
} else {
842+
dir = dir[:idx]
843+
}
844+
if dirs[dir] {
845+
break
846+
}
838847
dirs[dir] = true
839848
}
840849

src/archive/zip/reader_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"encoding/binary"
1010
"encoding/hex"
1111
"errors"
12+
"fmt"
1213
"internal/obscuretestdata"
1314
"io"
1415
"io/fs"
@@ -1876,3 +1877,83 @@ func TestBaseOffsetPlusOverflow(t *testing.T) {
18761877
// as the section reader offset & size were < 0.
18771878
NewReader(bytes.NewReader(data), int64(len(data))+1875)
18781879
}
1880+
1881+
func BenchmarkReaderOneDeepDir(b *testing.B) {
1882+
var buf bytes.Buffer
1883+
zw := NewWriter(&buf)
1884+
1885+
for i := range 4000 {
1886+
name := strings.Repeat("a/", i) + "data"
1887+
zw.CreateHeader(&FileHeader{
1888+
Name: name,
1889+
Method: Store,
1890+
})
1891+
}
1892+
1893+
if err := zw.Close(); err != nil {
1894+
b.Fatal(err)
1895+
}
1896+
data := buf.Bytes()
1897+
1898+
for b.Loop() {
1899+
zr, err := NewReader(bytes.NewReader(data), int64(len(data)))
1900+
if err != nil {
1901+
b.Fatal(err)
1902+
}
1903+
zr.Open("does-not-exist")
1904+
}
1905+
}
1906+
1907+
func BenchmarkReaderManyDeepDirs(b *testing.B) {
1908+
var buf bytes.Buffer
1909+
zw := NewWriter(&buf)
1910+
1911+
for i := range 2850 {
1912+
name := fmt.Sprintf("%x", i)
1913+
name = strings.Repeat("/"+name, i+1)[1:]
1914+
1915+
zw.CreateHeader(&FileHeader{
1916+
Name: name,
1917+
Method: Store,
1918+
})
1919+
}
1920+
1921+
if err := zw.Close(); err != nil {
1922+
b.Fatal(err)
1923+
}
1924+
data := buf.Bytes()
1925+
1926+
for b.Loop() {
1927+
zr, err := NewReader(bytes.NewReader(data), int64(len(data)))
1928+
if err != nil {
1929+
b.Fatal(err)
1930+
}
1931+
zr.Open("does-not-exist")
1932+
}
1933+
}
1934+
1935+
func BenchmarkReaderManyShallowFiles(b *testing.B) {
1936+
var buf bytes.Buffer
1937+
zw := NewWriter(&buf)
1938+
1939+
for i := range 310000 {
1940+
name := fmt.Sprintf("%v", i)
1941+
zw.CreateHeader(&FileHeader{
1942+
Name: name,
1943+
Method: Store,
1944+
})
1945+
}
1946+
1947+
if err := zw.Close(); err != nil {
1948+
b.Fatal(err)
1949+
}
1950+
data := buf.Bytes()
1951+
1952+
for b.Loop() {
1953+
zr, err := NewReader(bytes.NewReader(data), int64(len(data)))
1954+
if err != nil {
1955+
b.Fatal(err)
1956+
}
1957+
zr.Open("does-not-exist")
1958+
}
1959+
}

src/cmd/compile/internal/ssa/sccp.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,10 @@ func (t *worklist) propagate(block *Block) {
511511
branchIdx = 1 - condLattice.val.AuxInt
512512
} else {
513513
branchIdx = condLattice.val.AuxInt
514+
if branchIdx < 0 || branchIdx >= int64(len(block.Succs)) {
515+
// unreachable code, do nothing then
516+
break
517+
}
514518
}
515519
t.edges = append(t.edges, block.Succs[branchIdx])
516520
} else {

src/cmd/go/internal/modcmd/edit.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,10 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) {
321321

322322
// parsePathVersion parses -flag=arg expecting arg to be path@version.
323323
func parsePathVersion(flag, arg string) (path, version string) {
324-
before, after, found := strings.Cut(arg, "@")
324+
before, after, found, err := modload.ParsePathVersion(arg)
325+
if err != nil {
326+
base.Fatalf("go: -%s=%s: %v", flag, arg, err)
327+
}
325328
if !found {
326329
base.Fatalf("go: -%s=%s: need path@version", flag, arg)
327330
}
@@ -355,7 +358,10 @@ func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version
355358
if allowDirPath && modfile.IsDirectoryPath(arg) {
356359
return arg, "", nil
357360
}
358-
before, after, found := strings.Cut(arg, "@")
361+
before, after, found, err := modload.ParsePathVersion(arg)
362+
if err != nil {
363+
return "", "", err
364+
}
359365
if !found {
360366
path = arg
361367
} else {

src/cmd/go/internal/modfetch/codehost/git.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ func (r *gitRepo) loadRefs(ctx context.Context) (map[string]string, error) {
248248
r.refsErr = err
249249
return
250250
}
251-
out, gitErr := r.runGit(ctx, "git", "ls-remote", "-q", r.remote)
251+
out, gitErr := r.runGit(ctx, "git", "ls-remote", "-q", "--end-of-options", r.remote)
252252
release()
253253

254254
if gitErr != nil {
@@ -534,7 +534,7 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro
534534
if fromTag && !slices.Contains(info.Tags, tag) {
535535
// The local repo includes the commit hash we want, but it is missing
536536
// the corresponding tag. Add that tag and try again.
537-
_, err := r.runGit(ctx, "git", "tag", tag, hash)
537+
_, err := r.runGit(ctx, "git", "tag", "--end-of-options", tag, hash)
538538
if err != nil {
539539
return nil, err
540540
}
@@ -583,7 +583,7 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro
583583
// an apparent Git bug introduced in Git 2.21 (commit 61c771),
584584
// which causes the handler for protocol version 1 to sometimes miss
585585
// tags that point to the requested commit (see https://go.dev/issue/56881).
586-
_, err = r.runGit(ctx, "git", "-c", "protocol.version=2", "fetch", "-f", "--depth=1", r.remote, refspec)
586+
_, err = r.runGit(ctx, "git", "-c", "protocol.version=2", "fetch", "-f", "--depth=1", "--end-of-options", r.remote, refspec)
587587
release()
588588

589589
if err == nil {
@@ -629,12 +629,12 @@ func (r *gitRepo) fetchRefsLocked(ctx context.Context) error {
629629
}
630630
defer release()
631631

632-
if _, err := r.runGit(ctx, "git", "fetch", "-f", r.remote, "refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
632+
if _, err := r.runGit(ctx, "git", "fetch", "-f", "--end-of-options", r.remote, "refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
633633
return err
634634
}
635635

636636
if _, err := os.Stat(filepath.Join(r.dir, "shallow")); err == nil {
637-
if _, err := r.runGit(ctx, "git", "fetch", "--unshallow", "-f", r.remote); err != nil {
637+
if _, err := r.runGit(ctx, "git", "fetch", "--unshallow", "-f", "--end-of-options", r.remote); err != nil {
638638
return err
639639
}
640640
}
@@ -647,7 +647,7 @@ func (r *gitRepo) fetchRefsLocked(ctx context.Context) error {
647647
// statLocal returns a new RevInfo describing rev in the local git repository.
648648
// It uses version as info.Version.
649649
func (r *gitRepo) statLocal(ctx context.Context, version, rev string) (*RevInfo, error) {
650-
out, err := r.runGit(ctx, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", rev, "--")
650+
out, err := r.runGit(ctx, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", "--end-of-options", rev, "--")
651651
if err != nil {
652652
// Return info with Origin.RepoSum if possible to allow caching of negative lookup.
653653
var info *RevInfo
@@ -737,7 +737,7 @@ func (r *gitRepo) ReadFile(ctx context.Context, rev, file string, maxSize int64)
737737
if err != nil {
738738
return nil, err
739739
}
740-
out, err := r.runGit(ctx, "git", "cat-file", "blob", info.Name+":"+file)
740+
out, err := r.runGit(ctx, "git", "cat-file", "--end-of-options", "blob", info.Name+":"+file)
741741
if err != nil {
742742
return nil, fs.ErrNotExist
743743
}
@@ -755,7 +755,7 @@ func (r *gitRepo) RecentTag(ctx context.Context, rev, prefix string, allowed fun
755755
// result is definitive.
756756
describe := func() (definitive bool) {
757757
var out []byte
758-
out, err = r.runGit(ctx, "git", "for-each-ref", "--format", "%(refname)", "refs/tags", "--merged", rev)
758+
out, err = r.runGit(ctx, "git", "for-each-ref", "--format=%(refname)", "--merged="+rev)
759759
if err != nil {
760760
return true
761761
}
@@ -904,7 +904,7 @@ func (r *gitRepo) ReadZip(ctx context.Context, rev, subdir string, maxSize int64
904904
// TODO: Use maxSize or drop it.
905905
args := []string{}
906906
if subdir != "" {
907-
args = append(args, "--", subdir)
907+
args = append(args, subdir)
908908
}
909909
info, err := r.Stat(ctx, rev) // download rev into local git repo
910910
if err != nil {
@@ -926,7 +926,7 @@ func (r *gitRepo) ReadZip(ctx context.Context, rev, subdir string, maxSize int64
926926
// text file line endings. Setting -c core.autocrlf=input means only
927927
// translate files on the way into the repo, not on the way out (archive).
928928
// The -c core.eol=lf should be unnecessary but set it anyway.
929-
archive, err := r.runGit(ctx, "git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", "--prefix=prefix/", info.Name, args)
929+
archive, err := r.runGit(ctx, "git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", "--prefix=prefix/", "--end-of-options", info.Name, args)
930930
if err != nil {
931931
if bytes.Contains(err.(*RunError).Stderr, []byte("did not match any files")) {
932932
return nil, fs.ErrNotExist

src/cmd/go/internal/modfetch/codehost/vcs.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -176,20 +176,20 @@ var vcsCmds = map[string]*vcsCmd{
176176
branchRE: re(`(?m)^[^\n]+$`),
177177
badLocalRevRE: re(`(?m)^(tip)$`),
178178
statLocal: func(rev, remote string) []string {
179-
return []string{"hg", "log", "-l1", "-r", rev, "--template", "{node} {date|hgdate} {tags}"}
179+
return []string{"hg", "log", "-l1", fmt.Sprintf("--rev=%s", rev), "--template", "{node} {date|hgdate} {tags}"}
180180
},
181181
parseStat: hgParseStat,
182182
fetch: []string{"hg", "pull", "-f"},
183183
latest: "tip",
184184
readFile: func(rev, file, remote string) []string {
185-
return []string{"hg", "cat", "-r", rev, file}
185+
return []string{"hg", "cat", fmt.Sprintf("--rev=%s", rev), "--", file}
186186
},
187187
readZip: func(rev, subdir, remote, target string) []string {
188188
pattern := []string{}
189189
if subdir != "" {
190-
pattern = []string{"-I", subdir + "/**"}
190+
pattern = []string{fmt.Sprintf("--include=%s", subdir+"/**")}
191191
}
192-
return str.StringList("hg", "archive", "-t", "zip", "--no-decode", "-r", rev, "--prefix=prefix/", pattern, "--", target)
192+
return str.StringList("hg", "archive", "-t", "zip", "--no-decode", fmt.Sprintf("--rev=%s", rev), "--prefix=prefix/", pattern, "--", target)
193193
},
194194
},
195195

@@ -229,19 +229,19 @@ var vcsCmds = map[string]*vcsCmd{
229229
tagRE: re(`(?m)^\S+`),
230230
badLocalRevRE: re(`^revno:-`),
231231
statLocal: func(rev, remote string) []string {
232-
return []string{"bzr", "log", "-l1", "--long", "--show-ids", "-r", rev}
232+
return []string{"bzr", "log", "-l1", "--long", "--show-ids", fmt.Sprintf("--revision=%s", rev)}
233233
},
234234
parseStat: bzrParseStat,
235235
latest: "revno:-1",
236236
readFile: func(rev, file, remote string) []string {
237-
return []string{"bzr", "cat", "-r", rev, file}
237+
return []string{"bzr", "cat", fmt.Sprintf("--revision=%s", rev), "--", file}
238238
},
239239
readZip: func(rev, subdir, remote, target string) []string {
240240
extra := []string{}
241241
if subdir != "" {
242242
extra = []string{"./" + subdir}
243243
}
244-
return str.StringList("bzr", "export", "--format=zip", "-r", rev, "--root=prefix/", "--", target, extra)
244+
return str.StringList("bzr", "export", "--format=zip", fmt.Sprintf("--revision=%s", rev), "--root=prefix/", "--", target, extra)
245245
},
246246
},
247247

@@ -256,17 +256,17 @@ var vcsCmds = map[string]*vcsCmd{
256256
},
257257
tagRE: re(`XXXTODO`),
258258
statLocal: func(rev, remote string) []string {
259-
return []string{"fossil", "info", "-R", ".fossil", rev}
259+
return []string{"fossil", "info", "-R", ".fossil", "--", rev}
260260
},
261261
parseStat: fossilParseStat,
262262
latest: "trunk",
263263
readFile: func(rev, file, remote string) []string {
264-
return []string{"fossil", "cat", "-R", ".fossil", "-r", rev, file}
264+
return []string{"fossil", "cat", "-R", ".fossil", fmt.Sprintf("-r=%s", rev), "--", file}
265265
},
266266
readZip: func(rev, subdir, remote, target string) []string {
267267
extra := []string{}
268268
if subdir != "" && !strings.ContainsAny(subdir, "*?[],") {
269-
extra = []string{"--include", subdir}
269+
extra = []string{fmt.Sprintf("--include=%s", subdir)}
270270
}
271271
// Note that vcsRepo.ReadZip below rewrites this command
272272
// to run in a different directory, to work around a fossil bug.

src/cmd/go/internal/modget/query.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ func errSet(err error) pathSet { return pathSet{err: err} }
139139
// newQuery returns a new query parsed from the raw argument,
140140
// which must be either path or path@version.
141141
func newQuery(raw string) (*query, error) {
142-
pattern, rawVers, found := strings.Cut(raw, "@")
142+
pattern, rawVers, found, err := modload.ParsePathVersion(raw)
143+
if err != nil {
144+
return nil, err
145+
}
143146
if found && (strings.Contains(rawVers, "@") || rawVers == "") {
144147
return nil, fmt.Errorf("invalid module version syntax %q", raw)
145148
}

src/cmd/go/internal/modload/build.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"io/fs"
1313
"os"
1414
"path/filepath"
15-
"strings"
1615

1716
"cmd/go/internal/base"
1817
"cmd/go/internal/cfg"
@@ -88,7 +87,16 @@ func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic {
8887
return nil
8988
}
9089

91-
if path, vers, found := strings.Cut(path, "@"); found {
90+
path, vers, found, err := ParsePathVersion(path)
91+
if err != nil {
92+
return &modinfo.ModulePublic{
93+
Path: path,
94+
Error: &modinfo.ModuleError{
95+
Err: err.Error(),
96+
},
97+
}
98+
}
99+
if found {
92100
m := module.Version{Path: path, Version: vers}
93101
return moduleInfo(ctx, nil, m, 0, nil)
94102
}

0 commit comments

Comments
 (0)