Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
1e44a4c
[release-branch.go1.27] runtime: don't add the itabs of a plugin twice
dims Sep 1, 2026
072330d
[release-branch.go1.27] cmd/compile: correctly mark interface calls a…
cuonglm Sep 4, 2026
f8a45f6
[release-branch.go1.27] cmd/compile: fix large riscv64 move/zero
randall77 Aug 31, 2026
1cfd8f0
[release-branch.go1.27] encoding/json: avoid calling MarshalText on n…
dsnet Sep 4, 2026
aa6fc25
[release-branch.go1.27] net/http: fix HTTP/1 deadlock on concurrent r…
nicholashusin Sep 9, 2026
db53142
[release-branch.go1.27] net/http: read Response before signaling eofc…
dims Sep 13, 2026
8cd5a09
[release-branch.go1.27] net/http: return nil from Body.Close after a …
dims Sep 13, 2026
2e4b38e
[release-branch.go1.27] net/http: discard trailer when draining a res…
nicholashusin Sep 14, 2026
072779d
[release-branch.go1.27] net/http/internal/http2: delete malformed fra…
nicholashusin Sep 17, 2026
ff5898f
[release-branch.go1.27] internal/runtime/syscall/linux: sync EpollEve…
HeliC829 Aug 20, 2026
c407a15
[release-branch.go1.27] cmd/compile: don't stack-allocate a slice who…
cuonglm Sep 21, 2026
e89d44f
[release-branch.go1.27] os: handle unsupported OBJ_DONT_REPARSE on ol…
qmuntal Sep 7, 2026
d16d95c
[release-branch.go1.27] compress/flate: do not emit the preset dictio…
joechenrh Jul 23, 2026
620e2e0
[release-branch.go1.27] runtime: keep the working directory for non-b…
lazerg Sep 10, 2026
aee72ef
[release-branch.go1.27] testing: escape framing markers only in test2…
AndrewDeryabin Sep 17, 2026
fa3bd01
[release-branch.go1.27] cmd/compile: call racefuncexit before a tail …
cuonglm Sep 14, 2026
bd8f7a6
[release-branch.go1.27] cmd: vendor changes for "go fix"
madelinekalil Sep 23, 2026
359bec4
[release-branch.go1.27] cmd/compile: support unified V5 export data (…
adonovan Sep 1, 2026
4e4eec7
[release-branch.go1.27] os: preserve completion notification modes fo…
qmuntal Sep 7, 2026
bc516c2
[release-branch.go1.27] cmd/go: include VetxOnly in the vet action ID
lazerg Sep 26, 2026
322f178
[release-branch.go1.27] encoding/json/v2: avoid setting with errors p…
dsnet Aug 24, 2026
d995fb8
[release-branch.go1.27] net/http: populate Request.TLS from HTTP/2 co…
NIDJEL Sep 8, 2026
8ada93d
[release-branch.go1.27] encoding/json: fix UnsupportedValueError.Valu…
dsnet Aug 29, 2026
b73c143
[release-branch.go1.27] cmd/compile: use a 32-bit type for rewritten …
lazerg Sep 23, 2026
9c26a3a
[release-branch.go1.27] cmd/internal/obj/ppc64: fix async preempt saf…
rsc Aug 25, 2026
87b06e2
[release-branch.go1.27] runtime: create Windows threads on the system…
qmuntal Sep 28, 2026
ce0ff94
[release-branch.go1.27] cmd/cover: preserve statement counts when spl…
cuishuang Aug 21, 2026
bd9992d
[release-branch.go1.27] cmd/link: pass -no_fixup_chains to C linker w…
cherrymui Sep 30, 2026
b26d150
[release-branch.go1.27] html/template: reset JS context for template …
thatnealpatel Sep 28, 2026
6e2cfab
[release-branch.go1.27] html/template: recognize `yield` as regexp pr…
thatnealpatel Sep 28, 2026
1e4f1fe
[release-branch.go1.27] cmd/go: bundle go.sum h1 hashes for golang.or…
thatnealpatel Sep 28, 2026
68fa769
[release-branch.go1.27] cmd/go: always verify toolchain downloads wit…
thatnealpatel Sep 28, 2026
f022e61
[release-branch.go1.27] crypto/tls: validate ECH outer extension refe…
thatnealpatel Sep 28, 2026
7c79b50
[release-branch.go1.27] net/textproto: enforce MIME memory limit on f…
neild Sep 22, 2026
76875df
[release-branch.go1.27] net/http, net/http/httputil: avoid post-CONNE…
neild Aug 14, 2026
e92229e
[release-branch.go1.27] net/http: avoid server reuse of connection af…
neild Aug 14, 2026
9636ab0
[release-branch.go1.27] os: correct Root junction handling on Windows…
neild Sep 15, 2026
ababc3c
[release-branch.go1.27] net/http: limit the size of range headers par…
neild Sep 14, 2026
1d58cda
[release-branch.go1.27] net/http/internal/http2: avoid excessive work…
neild Sep 16, 2026
31dc9e2
[release-branch.go1.27] net/http/internal/http2: avoid 2x refund on s…
neild Aug 28, 2026
12acaf3
[release-branch.go1.27] net/http/internal/http2: prevent crash due to…
nicholashusin Sep 28, 2026
cbb0fb8
[release-branch.go1.27] net/http: apply header limits to Trailer head…
nicholashusin Sep 21, 2026
022c863
[release-branch.go1.27] go1.27.2
gopherbot Oct 8, 2026
4247e46
Update to Go 1.27.2
bradfitz Oct 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions VERSION
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
go1.27.1
time 2026-08-28T16:20:06Z
go1.27.2
time 2026-10-02T20:28:03Z
18 changes: 17 additions & 1 deletion doc/godebug.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,22 @@ for example,
see the [runtime documentation](/pkg/runtime#hdr-Environment_Variables)
and the [go command documentation](/cmd/go#hdr-Build_and_test_caching).

### Go 1.28

Go 1.28 changed
[`net/http.FileServer`](/pkg/net/http#FileServer),
[`net/http.FileServerFS`](/pkg/net/http#FileServerFS),
[`net/http.ServeContent`](/pkg/net/http#ServeContent),
[`net/http.ServeFile`](/pkg/net/http#ServeFile), and
[`net/http.ServeFileFS`](/pkg/net/http#ServeFileFS) to
limit the maximum number of ranges in a Range header.
When the number of ranges in a header exceeds the new
`httpservecontentmaxranges` setting, the header is ignored.
The default value is `httpservecontentmaxranges=200`.
Setting `httpservecontentmaxranges=0` disables the limit.
To avoid denial of service attacks, this setting and default
was backported to Go 1.27.2 and Go 1.26.9.

### Go 1.27

Go 1.27 removed the `gotypesalias` setting, as noted in the [Go 1.22](#go-122) section.
Expand Down Expand Up @@ -199,7 +215,7 @@ We plan to remove this setting in Go 1.31.

Go 1.26 added a new `httpcookiemaxnum` setting that controls the maximum number
of cookies that net/http will accept when parsing HTTP headers. If the number of
cookie in a header exceeds the number set in `httpcookiemaxnum`, cookie parsing
cookies in a header exceeds the number set in `httpcookiemaxnum`, cookie parsing
will fail early. The default value is `httpcookiemaxnum=3000`. Setting
`httpcookiemaxnum=0` will allow the cookie parsing to accept an indefinite
number of cookies. To avoid denial of service attacks, this setting and default
Expand Down
9 changes: 6 additions & 3 deletions lib/fips140/fips140.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# SHA256 checksums of snapshot zip files in this directory.
# Checksums of snapshot zip files in this directory.
# Each line is "NAME SHA256HEX H1HASH", where SHA256HEX is the SHA256
# checksum of the zip file and H1HASH is the module zip hash of its
# contents, as recorded in go.sum files and the module cache.
# These checksums are included in the FIPS security policy
# (validation instructions sent to the lab) and MUST NOT CHANGE.
# That is, the zip files themselves must not change.
Expand All @@ -9,5 +12,5 @@
#
# go test cmd/go/internal/fips140 -update
#
v1.0.0-c2097c7c.zip daf3614e0406f67ae6323c902db3f953a1effb199142362a039e7526dfb9368b
v1.26.0.zip 9b28f847fdf1db4a36cb2b2f8ec09443c039383f085630a03ecfaddf6db7ea23
v1.0.0-c2097c7c.zip daf3614e0406f67ae6323c902db3f953a1effb199142362a039e7526dfb9368b h1:YapsF69QWGwygaBqdI0rp7IfE5a6tAwepNAHONVcWqQ=
v1.26.0.zip 9b28f847fdf1db4a36cb2b2f8ec09443c039383f085630a03ecfaddf6db7ea23 h1:dtoPX1ALGGp4rMLzyh6oqIkYRXnXxRkpPWu56l5DFpM=
11 changes: 11 additions & 0 deletions src/cmd/cgo/internal/testplugin/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,14 @@ func TestIssue75102(t *testing.T) {
goCmd(t, "build", "-o", "issue75102.exe", "./issue75102/main.go")
run(t, "./issue75102.exe")
}

func TestIssue81303(t *testing.T) {
// Issue 81303: the itab copies of a plugin must not hide the itabs
// of the host for the same interface/type pairs.
globalSkip(t)
goCmd(t, "build", "-buildmode=plugin", "-o", "issue81303p1.so", "./issue81303/plugin1.go")
goCmd(t, "build", "-buildmode=plugin", "-o", "issue81303p2.so", "./issue81303/plugin2.go")
goCmd(t, "build", "-buildmode=plugin", "-o", "issue81303p3.so", "./issue81303/plugin3.go")
goCmd(t, "build", "-o", "issue81303.exe", "./issue81303/main.go")
run(t, "./issue81303.exe")
}
39 changes: 39 additions & 0 deletions src/cmd/cgo/internal/testplugin/testdata/issue81303/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Issue 81303: a plugin has its own copies of the itabs of the host.
// The runtime added these copies to the itab table as second entries
// for the same interface/type pairs. After the table grew, a lookup
// could return the copy from the plugin. A type switch compares the
// itab with the itab of the host, so it took the default case.
//
// Each plugin imports package p, which uses go/ast, so each plugin
// adds a copy of every go/ast itab of the host. The host walks a
// syntax tree before and after each plugin loads. The three plugins
// are the same because plugin.Open loads a plugin path only once.

package main

import (
"log"
"plugin"

"testplugin/issue81303/p"
)

func main() {
p.Walk()
for _, name := range []string{"issue81303p1.so", "issue81303p2.so", "issue81303p3.so"} {
pl, err := plugin.Open(name)
if err != nil {
log.Fatal(err)
}
f, err := pl.Lookup("F")
if err != nil {
log.Fatal(err)
}
f.(func())()
p.Walk()
}
}
48 changes: 48 additions & 0 deletions src/cmd/cgo/internal/testplugin/testdata/issue81303/p/p.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package p

import (
"go/ast"
"go/parser"
"go/token"
"log"
)

const src = `package p
import "fmt"
type T struct{ x int }
func (t *T) M(n int) (r int) {
defer func() { r++ }()
go fmt.Println(n)
if n > 0 {
r = n
} else {
r = -n
}
for i := 0; i < n; i++ {
r += t.x
}
switch v := any(n).(type) {
case int:
r = v
}
return
}
`

// Walk parses src and walks the syntax tree. ast.Walk converts each
// node to ast.Node, which looks up the itab in the itab table, and
// then compares that itab with the itab of the host in a type switch.
func Walk() {
f, err := parser.ParseFile(token.NewFileSet(), "src.go", src, parser.SkipObjectResolution)
if err != nil {
log.Fatal(err)
}
ast.Inspect(f, func(ast.Node) bool { return true })
}
11 changes: 11 additions & 0 deletions src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import "testplugin/issue81303/p"

func main() {}

func F() { p.Walk() }
11 changes: 11 additions & 0 deletions src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import "testplugin/issue81303/p"

func main() {}

func F() { p.Walk() }
11 changes: 11 additions & 0 deletions src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import "testplugin/issue81303/p"

func main() {}

func F() { p.Walk() }
56 changes: 48 additions & 8 deletions src/cmd/compile/internal/importer/ureader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
package importer

import (
"cmp"
"slices"

"cmd/compile/internal/base"
"cmd/compile/internal/syntax"
"cmd/compile/internal/types2"
Expand Down Expand Up @@ -459,12 +462,26 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
// about it, so maybe we can avoid worrying about that here.
underlying := r.typ().Underlying()

methods := make([]*types2.Func, r.Len())
for i := range methods {
methods[i] = r.method(true)
type indexedMethod struct {
index int // (or -1 in V4)
fn *types2.Func
}
var methods []indexedMethod

if r.Version().Has(pkgbits.GenericMethods) {
// V4 (go1.27.0) emitted all non-generic methods
// before all generic ones, discarding source
// order: a bug (go.dev/issue/81188).
// V5 (go1.27.x) fixes it by emitting an explicit
// index along with each method.

// ordinary methods
for range r.Len() {
idx, m := r.method(true)
methods = append(methods, indexedMethod{idx, m})
}

// generic methods
for range r.Len() {
// Careful: objIdx is used to read in package-scoped declarations, which
// methods are not. Instead, decode it here. This makes it easier to
Expand All @@ -479,17 +496,36 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
pkg, name := t.selector()
rtparams := t.typeParamNames(true, true)
recv := t.param()
methodIdx := -1
if r.Version().Has(pkgbits.PreserveMethodOrder) {
methodIdx = t.Len()
}
tparams := t.typeParamNames(true, false)
sig := t.signature(recv, rtparams, tparams)

r.delayed = append(r.delayed, t.delayed...) // propagate before retiring

pr.retireReader(t)
methods = append(methods, types2.NewFunc(pos, pkg, name, sig))
methods = append(methods, indexedMethod{methodIdx, types2.NewFunc(pos, pkg, name, sig)})
}

if r.Version().Has(pkgbits.PreserveMethodOrder) {
slices.SortFunc(methods, func(a, b indexedMethod) int {
return cmp.Compare(a.index, b.index)
})
}
} else {
for range r.Len() {
_, m := r.method(true)
methods = append(methods, indexedMethod{-1, m})
}
}

return tparams, underlying, methods, r.delayed
funcs := make([]*types2.Func, len(methods))
for i, m := range methods {
funcs[i] = m.fn
}

return tparams, underlying, funcs, r.delayed
})

case pkgbits.ObjVar:
Expand Down Expand Up @@ -606,16 +642,20 @@ func (r *reader) typeParamNames(isLazy bool, isGenMeth bool) []*types2.TypeParam
return tparams
}

func (r *reader) method(isLazy bool) *types2.Func {
func (r *reader) method(isLazy bool) (int, *types2.Func) {
r.Sync(pkgbits.SyncMethod)
idx := -1
if r.Version().Has(pkgbits.PreserveMethodOrder) {
idx = r.Len()
}
pos := r.pos()
pkg, name := r.selector()

rtparams := r.typeParamNames(isLazy, false)
sig := r.signature(r.param(), rtparams, nil)

_ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go.
return types2.NewFunc(pos, pkg, name, sig)
return idx, types2.NewFunc(pos, pkg, name, sig)
}

func (r *reader) qualifiedIdent() (*types2.Package, string) { return r.ident(pkgbits.SyncSym) }
Expand Down
6 changes: 6 additions & 0 deletions src/cmd/compile/internal/noder/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,9 @@ func (pr *pkgReader) objIdxMayFail(idx index, implicits, explicits []*types.Type
sel = r.selector()
r.recvTypeParamNames()
recv = r.param()
if r.Version().Has(pkgbits.PreserveMethodOrder) {
_ = r.Len() // method index not needed in compiler
}
} else {
if sym.Name == "init" {
sym = Renameinit()
Expand Down Expand Up @@ -1130,6 +1133,9 @@ func (r *reader) typeParamNames() {

func (r *reader) method(rext *reader) *types.Field {
r.Sync(pkgbits.SyncMethod)
if r.Version().Has(pkgbits.PreserveMethodOrder) {
_ = r.Len() // method index not needed in compiler
}
npos := r.pos()
sym := r.selector()
r.typeParamNames()
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/noder/unified.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import (
)

// uirVersion is the unified IR version to use for encoding/decoding.
// Use V4 for generic methods.
const uirVersion = pkgbits.V4
// Use V5 for generic method index ordering.
const uirVersion = pkgbits.V5

// localPkgReader holds the package reader used for reading the local
// package. It exists so the unified IR linker can refer back to it
Expand Down
20 changes: 15 additions & 5 deletions src/cmd/compile/internal/noder/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"go/version"
"internal/buildcfg"
"internal/pkgbits"
"log"
"os"
"slices"
"strings"
Expand Down Expand Up @@ -82,8 +83,9 @@ type pkgWriter struct {

// Maps from types2.Objects back to their syntax.Decl.

funDecls map[*types2.Func]*syntax.FuncDecl
typDecls map[*types2.TypeName]typeDeclGen
funDecls map[*types2.Func]*syntax.FuncDecl
typDecls map[*types2.TypeName]typeDeclGen
methodIdx map[*types2.Func]int // method declaration order, for x/tools decoder (#81188)

// linknames maps package-scope objects to their linker symbol name,
// if specified by a //go:linkname or //go:linknamestd directive.
Expand Down Expand Up @@ -114,8 +116,9 @@ func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo ma

posBasesIdx: make(map[*syntax.PosBase]index),

funDecls: make(map[*types2.Func]*syntax.FuncDecl),
typDecls: make(map[*types2.TypeName]typeDeclGen),
funDecls: make(map[*types2.Func]*syntax.FuncDecl),
typDecls: make(map[*types2.TypeName]typeDeclGen),
methodIdx: make(map[*types2.Func]int),

linknames: make(map[types2.Object]struct {
remote string
Expand Down Expand Up @@ -863,7 +866,7 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
// Unified IR panics are the worst; this is a huge help in debugging them.
defer func() {
if p := recover(); p != nil {
fmt.Printf("Intercepted unified IR writer panic for function %s, repanicking", obj.FullName())
log.Printf("Intercepted unified IR writer panic for function %s, repanicking", obj.FullName())
panic(p)
}
}()
Expand All @@ -879,6 +882,9 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
w.selector(obj)
w.typeParamNames(sig.RecvTypeParams())
w.param(sig.Recv())
if w.Version().Has(pkgbits.PreserveMethodOrder) {
w.Len(w.p.methodIdx[obj.Origin()])
}
} else {
if w.Version().Has(pkgbits.GenericMethods) {
w.Bool(false) // function
Expand Down Expand Up @@ -920,6 +926,7 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
var methods, gmethods []*types2.Func
for i := range named.NumMethods() {
m := named.Method(i)
w.p.methodIdx[m] = i
if isGenericMethod(m.Type()) {
gmethods = append(gmethods, m)
} else {
Expand Down Expand Up @@ -1054,6 +1061,9 @@ func (w *writer) method(wext *writer, meth *types2.Func) {
sig := meth.Type().(*types2.Signature)

w.Sync(pkgbits.SyncMethod)
if w.Version().Has(pkgbits.PreserveMethodOrder) {
w.Len(w.p.methodIdx[meth.Origin()])
}
w.pos(meth)
w.selector(meth)
w.typeParamNames(sig.RecvTypeParams())
Expand Down
Loading
Loading