Update to go1.24.4

This commit is contained in:
Vorapol Rinsatitnon
2025-06-09 00:13:09 +07:00
parent fc8a9f2ce8
commit b065c9156b
16 changed files with 189 additions and 58 deletions

View File

@@ -1,2 +1,2 @@
go1.24.3
time 2025-04-30T18:13:34Z
go1.24.4
time 2025-05-29T19:37:36Z

View File

@@ -0,0 +1 @@
v1.0.0

View File

@@ -452,33 +452,50 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
if oldsym.Dupok() {
return oldi
}
// If one is a DATA symbol (i.e. has content, DataSize != 0)
// and the other is BSS, the one with content wins.
// If one is a DATA symbol (i.e. has content, DataSize != 0,
// including RODATA) and the other is BSS, the one with content wins.
// If both are BSS, the one with larger size wins.
// Specifically, the "overwrite" variable and the final result are
//
// new sym old sym overwrite
// For a special case, we allow a TEXT symbol overwrites a BSS symbol
// even if the BSS symbol has larger size. This is because there is
// code like below to take the address of a function
//
// //go:linkname fn
// var fn uintptr
// var fnAddr = uintptr(unsafe.Pointer(&fn))
//
// TODO: maybe limit this case to just pointer sized variable?
//
// In summary, the "overwrite" variable and the final result are
//
// new sym old sym result
// ---------------------------------------------
// DATA DATA true => ERROR
// DATA lg/eq BSS sm/eq true => new wins
// DATA small BSS large true => ERROR
// BSS large DATA small true => ERROR
// BSS large BSS small true => new wins
// BSS sm/eq D/B lg/eq false => old wins
overwrite := r.DataSize(li) != 0 || oldsz < sz
if overwrite {
// TEXT BSS new wins
// DATA DATA ERROR
// DATA lg/eq BSS sm/eq new wins
// DATA small BSS large ERROR
// BSS large DATA small ERROR
// BSS large BSS small new wins
// BSS sm/eq D/B lg/eq old wins
// BSS TEXT old wins
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
newtyp := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
oldIsText := oldtyp.IsText()
newIsText := newtyp.IsText()
oldHasContent := oldr.DataSize(oldli) != 0
newHasContent := r.DataSize(li) != 0
oldIsBSS := oldtyp.IsData() && !oldHasContent
newIsBSS := newtyp.IsData() && !newHasContent
switch {
case newIsText && oldIsBSS,
newHasContent && oldIsBSS && sz >= oldsz,
newIsBSS && oldIsBSS && sz > oldsz:
// new symbol overwrites old symbol.
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) || oldsz > sz {
log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg)
}
l.objSyms[oldi] = objSym{r.objidx, li}
} else {
// old symbol overwrites new symbol.
typ := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
if !typ.IsData() { // only allow overwriting data symbol
log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg)
}
case newIsBSS && (oldsz >= sz || oldIsText):
// old win, just ignore the new symbol.
default:
log.Fatalf("duplicated definition of symbol %s, from %s (type %s size %d) and %s (type %s size %d)", name, r.unit.Lib.Pkg, newtyp, sz, oldr.unit.Lib.Pkg, oldtyp, oldsz)
}
return oldi
}

View File

@@ -1512,6 +1512,9 @@ func TestCheckLinkname(t *testing.T) {
{"ok.go", true},
// push linkname is ok
{"push.go", true},
// using a linknamed variable to reference an assembly
// function in the same package is ok
{"textvar", true},
// pull linkname of blocked symbol is not ok
{"coro.go", false},
{"coro_var.go", false},
@@ -1529,7 +1532,7 @@ func TestCheckLinkname(t *testing.T) {
test := test
t.Run(test.src, func(t *testing.T) {
t.Parallel()
src := filepath.Join("testdata", "linkname", test.src)
src := "./testdata/linkname/" + test.src
exe := filepath.Join(tmpdir, test.src+".exe")
cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", exe, src)
out, err := cmd.CombinedOutput()

View File

@@ -0,0 +1,6 @@
// Copyright 2024 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.
TEXT ·asmfunc(SB),0,$0-0
RET

View File

@@ -0,0 +1,17 @@
// Copyright 2024 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.
// Using a linknamed variable to reference an assembly
// function in the same package is ok.
package main
import _ "unsafe"
func main() {
println(&asmfunc)
}
//go:linkname asmfunc
var asmfunc uintptr

View File

@@ -841,31 +841,45 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
}
}
if len(opts.KeyUsages) == 0 {
opts.KeyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
}
for _, eku := range opts.KeyUsages {
if eku == ExtKeyUsageAny {
// If any key usage is acceptable, no need to check the chain for
// key usages.
return candidateChains, nil
}
}
chains = make([][]*Certificate, 0, len(candidateChains))
var incompatibleKeyUsageChains, invalidPoliciesChains int
var invalidPoliciesChains int
for _, candidate := range candidateChains {
if !checkChainForKeyUsage(candidate, opts.KeyUsages) {
incompatibleKeyUsageChains++
continue
}
if !policiesValid(candidate, opts) {
invalidPoliciesChains++
continue
}
chains = append(chains, candidate)
}
if len(chains) == 0 {
return nil, CertificateInvalidError{c, NoValidChains, "all candidate chains have invalid policies"}
}
for _, eku := range opts.KeyUsages {
if eku == ExtKeyUsageAny {
// If any key usage is acceptable, no need to check the chain for
// key usages.
return chains, nil
}
}
if len(opts.KeyUsages) == 0 {
opts.KeyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
}
candidateChains = chains
chains = chains[:0]
var incompatibleKeyUsageChains int
for _, candidate := range candidateChains {
if !checkChainForKeyUsage(candidate, opts.KeyUsages) {
incompatibleKeyUsageChains++
continue
}
chains = append(chains, candidate)
}
if len(chains) == 0 {
var details []string
if incompatibleKeyUsageChains > 0 {

View File

@@ -3012,3 +3012,39 @@ func TestPoliciesValid(t *testing.T) {
})
}
}
func TestInvalidPolicyWithAnyKeyUsage(t *testing.T) {
loadTestCert := func(t *testing.T, path string) *Certificate {
b, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
p, _ := pem.Decode(b)
c, err := ParseCertificate(p.Bytes)
if err != nil {
t.Fatal(err)
}
return c
}
testOID3 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 3})
root, intermediate, leaf := loadTestCert(t, "testdata/policy_root.pem"), loadTestCert(t, "testdata/policy_intermediate_require.pem"), loadTestCert(t, "testdata/policy_leaf.pem")
expectedErr := "x509: no valid chains built: all candidate chains have invalid policies"
roots, intermediates := NewCertPool(), NewCertPool()
roots.AddCert(root)
intermediates.AddCert(intermediate)
_, err := leaf.Verify(VerifyOptions{
Roots: roots,
Intermediates: intermediates,
KeyUsages: []ExtKeyUsage{ExtKeyUsageAny},
CertificatePolicies: []OID{testOID3},
})
if err == nil {
t.Fatal("unexpected success, invalid policy shouldn't be bypassed by passing VerifyOptions.KeyUsages with ExtKeyUsageAny")
} else if err.Error() != expectedErr {
t.Fatalf("unexpected error, got %q, want %q", err, expectedErr)
}
}

View File

@@ -161,7 +161,7 @@ func appendT(h *Hash, v reflect.Value) {
case reflect.Bool:
h.WriteByte(btoi(v.Bool()))
return
case reflect.UnsafePointer, reflect.Pointer:
case reflect.UnsafePointer, reflect.Pointer, reflect.Chan:
var buf [8]byte
// because pointing to the abi.Escape call in comparableReady,
// So this is ok to hash pointer,

View File

@@ -253,12 +253,17 @@ func TestComparable(t *testing.T) {
}
testComparable(t, s1, s2)
testComparable(t, s1.s, s2.s)
c1 := make(chan struct{})
c2 := make(chan struct{})
testComparable(t, c1, c1)
testComparable(t, chan struct{}(nil))
testComparable(t, float32(0), negativeZero[float32]())
testComparable(t, float64(0), negativeZero[float64]())
testComparableNoEqual(t, math.NaN(), math.NaN())
testComparableNoEqual(t, [2]string{"a", ""}, [2]string{"", "a"})
testComparableNoEqual(t, struct{ a, b string }{"foo", ""}, struct{ a, b string }{"", "foo"})
testComparableNoEqual(t, struct{ a, b any }{int(0), struct{}{}}, struct{ a, b any }{struct{}{}, int(0)})
testComparableNoEqual(t, c1, c2)
}
func testComparableNoEqual[T comparable](t *testing.T, v1, v2 T) {

View File

@@ -88,6 +88,7 @@ func Openat(dirfd syscall.Handle, name string, flag int, perm uint32) (_ syscall
switch {
case flag&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL):
disposition = FILE_CREATE
options |= FILE_OPEN_REPARSE_POINT // don't follow symlinks
case flag&syscall.O_CREAT == syscall.O_CREAT:
disposition = FILE_OPEN_IF
default:

View File

@@ -805,7 +805,8 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensit
for k, vv := range ireqhdr {
sensitive := false
switch CanonicalHeaderKey(k) {
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2":
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2",
"Proxy-Authorization", "Proxy-Authenticate":
sensitive = true
}
if !(sensitive && stripSensitiveHeaders) {

View File

@@ -1547,6 +1547,8 @@ func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) {
if r.Host+r.URL.Path != "a.example.com/" {
if h := r.Header.Get("Authorization"); h != "" {
t.Errorf("on request to %v%v, Authorization=%q, want no header", r.Host, r.URL.Path, h)
} else if h := r.Header.Get("Proxy-Authorization"); h != "" {
t.Errorf("on request to %v%v, Proxy-Authorization=%q, want no header", r.Host, r.URL.Path, h)
}
}
// Follow a chain of redirects from a to b and back to a.
@@ -1575,6 +1577,7 @@ func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) {
req, _ := NewRequest("GET", proto+"://a.example.com/", nil)
req.Header.Add("Cookie", "foo=bar")
req.Header.Add("Authorization", "secretpassword")
req.Header.Add("Proxy-Authorization", "secretpassword")
res, err := c.Do(req)
if err != nil {
t.Fatal(err)

View File

@@ -2223,6 +2223,31 @@ func TestFilePermissions(t *testing.T) {
}
func TestOpenFileCreateExclDanglingSymlink(t *testing.T) {
testMaybeRooted(t, func(t *testing.T, r *Root) {
const link = "link"
if err := Symlink("does_not_exist", link); err != nil {
t.Fatal(err)
}
var f *File
var err error
if r == nil {
f, err = OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o444)
} else {
f, err = r.OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o444)
}
if err == nil {
f.Close()
}
if !errors.Is(err, ErrExist) {
t.Errorf("OpenFile of a dangling symlink with O_CREATE|O_EXCL = %v, want ErrExist", err)
}
if _, err := Stat(link); err == nil {
t.Errorf("OpenFile of a dangling symlink with O_CREATE|O_EXCL created a file")
}
})
}
// TestFileRDWRFlags tests the O_RDONLY, O_WRONLY, and O_RDWR flags.
func TestFileRDWRFlags(t *testing.T) {
for _, test := range []struct {

View File

@@ -77,6 +77,7 @@ type Module struct {
// - CGO_CPPFLAGS: the effective CGO_CPPFLAGS environment variable
// - CGO_CXXFLAGS: the effective CGO_CXXFLAGS environment variable
// - CGO_LDFLAGS: the effective CGO_LDFLAGS environment variable
// - DefaultGODEBUG: the effective GODEBUG settings
// - GOARCH: the architecture target
// - GOAMD64/GOARM/GO386/etc: the architecture feature level for GOARCH
// - GOOS: the operating system target

View File

@@ -376,20 +376,6 @@ func Open(name string, flag int, perm uint32) (fd Handle, err error) {
if flag&O_CLOEXEC == 0 {
sa = makeInheritSa()
}
// We don't use CREATE_ALWAYS, because when opening a file with
// FILE_ATTRIBUTE_READONLY these will replace an existing file
// with a new, read-only one. See https://go.dev/issue/38225.
//
// Instead, we ftruncate the file after opening when O_TRUNC is set.
var createmode uint32
switch {
case flag&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
createmode = CREATE_NEW
case flag&O_CREAT == O_CREAT:
createmode = OPEN_ALWAYS
default:
createmode = OPEN_EXISTING
}
var attrs uint32 = FILE_ATTRIBUTE_NORMAL
if perm&S_IWRITE == 0 {
attrs = FILE_ATTRIBUTE_READONLY
@@ -404,6 +390,21 @@ func Open(name string, flag int, perm uint32) (fd Handle, err error) {
const _FILE_FLAG_WRITE_THROUGH = 0x80000000
attrs |= _FILE_FLAG_WRITE_THROUGH
}
// We don't use CREATE_ALWAYS, because when opening a file with
// FILE_ATTRIBUTE_READONLY these will replace an existing file
// with a new, read-only one. See https://go.dev/issue/38225.
//
// Instead, we ftruncate the file after opening when O_TRUNC is set.
var createmode uint32
switch {
case flag&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
createmode = CREATE_NEW
attrs |= FILE_FLAG_OPEN_REPARSE_POINT // don't follow symlinks
case flag&O_CREAT == O_CREAT:
createmode = OPEN_ALWAYS
default:
createmode = OPEN_EXISTING
}
h, err := createFile(namep, access, sharemode, sa, createmode, attrs, 0)
if h == InvalidHandle {
if err == ERROR_ACCESS_DENIED && (flag&O_WRONLY != 0 || flag&O_RDWR != 0) {