[dev.boringcrypto.go1.18] all: merge go1.18.9 into dev.boringcrypto.go1.18

Change-Id: I5eda3a3fb2fc381e237d18d2846cf1b1810d8015
This commit is contained in:
Heschi Kreinick 2022-12-07 10:36:28 -05:00
commit fc1ed37e82
29 changed files with 531 additions and 52 deletions

View File

@ -2215,6 +2215,8 @@ var dwarfToName = map[string]string{
"long long unsigned int": "ulonglong",
"signed char": "schar",
"unsigned char": "uchar",
"unsigned long": "ulong", // Used by Clang 14; issue 53013.
"unsigned long long": "ulonglong", // Used by Clang 14; issue 53013.
}
const signedDelta = 64

View File

@ -323,7 +323,9 @@ func (p *noder) processPragmas() {
}
n := ir.AsNode(typecheck.Lookup(l.local).Def)
if n == nil || n.Op() != ir.ONAME {
p.errorAt(l.pos, "//go:linkname must refer to declared function or variable")
if types.AllowsGoVersion(types.LocalPkg, 1, 18) {
p.errorAt(l.pos, "//go:linkname must refer to declared function or variable")
}
continue
}
if n.Sym().Linkname != "" {

View File

@ -0,0 +1,65 @@
// Copyright 2022 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.
//go:build !compiler_bootstrap
// +build !compiler_bootstrap
package test
// The racecompile builder only builds packages, but does not build
// or run tests. This is a non-test file to hold cases that (used
// to) trigger compiler data races, so they will be exercised on
// the racecompile builder.
//
// This package is not imported so functions here are not included
// in the actual compiler.
// Issue 55357: data race when building multiple instantiations of
// generic closures with _ parameters.
func Issue55357() {
type U struct {
A int
B string
C string
}
var q T55357[U]
q.Count()
q.List()
type M struct {
A int64
B uint32
C uint32
}
var q2 T55357[M]
q2.Count()
q2.List()
}
type T55357[T any] struct{}
//go:noinline
func (q *T55357[T]) do(w, v bool, fn func(bk []byte, v T) error) error {
return nil
}
func (q *T55357[T]) Count() (n int, rerr error) {
err := q.do(false, false, func(kb []byte, _ T) error {
n++
return nil
})
return n, err
}
func (q *T55357[T]) List() (list []T, rerr error) {
var l []T
err := q.do(false, true, func(_ []byte, v T) error {
l = append(l, v)
return nil
})
if err != nil {
return nil, err
}
return l, nil
}

View File

@ -1356,7 +1356,8 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type {
newfields[i].SetNointerface(true)
}
if f.Nname != nil && ts.Vars != nil {
v := ts.Vars[f.Nname.(*ir.Name)]
n := f.Nname.(*ir.Name)
v := ts.Vars[n]
if v != nil {
// This is the case where we are
// translating the type of the function we
@ -1364,6 +1365,13 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type {
// the subst.ts.vars table, and we want to
// change to reference the new dcl.
newfields[i].Nname = v
} else if ir.IsBlank(n) {
// Blank variable is not dcl list. Make a
// new one to not share.
m := ir.NewNameAt(n.Pos(), ir.BlankNode.Sym())
m.SetType(n.Type())
m.SetTypecheck(1)
newfields[i].Nname = m
} else {
// This is the case where we are
// translating the type of a function

View File

@ -34,6 +34,8 @@ import (
// See issues 36852, 41409, and 43687.
// (Also see golang.org/issue/27348.)
func TestAllDependencies(t *testing.T) {
t.Skip("TODO(#57008): 1.18.9 contains unreleased changes from vendored modules")
goBin := testenv.GoToolPath(t)
// Ensure that all packages imported within GOROOT

View File

@ -540,8 +540,8 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) {
func TestGoVerify(t *testing.T) {
// Temporarily enable SHA-1 verification since a number of test chains
// require it. TODO(filippo): regenerate test chains.
defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1)
debugAllowSHA1 = true
t.Setenv("GODEBUG", "x509sha1=1")
for _, test := range verifyTests {
t.Run(test.name, func(t *testing.T) {
testVerify(t, test, false)

View File

@ -730,9 +730,6 @@ type Certificate struct {
// involves algorithms that are not currently implemented.
var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented")
// debugAllowSHA1 allows SHA-1 signatures. See issue 41682.
var debugAllowSHA1 = godebug.Get("x509sha1") == "1"
// An InsecureAlgorithmError indicates that the SignatureAlgorithm used to
// generate the signature is not secure, and the signature has been rejected.
//
@ -792,7 +789,7 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) error {
// TODO(agl): don't ignore the path length constraint.
return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature, parent.PublicKey, debugAllowSHA1)
return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature, parent.PublicKey, false)
}
// CheckSignature verifies that signature is a valid signature over signed from
@ -839,7 +836,8 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey
case crypto.MD5:
return InsecureAlgorithmError(algo)
case crypto.SHA1:
if !allowSHA1 {
// SHA-1 signatures are mostly disabled. See go.dev/issue/41682.
if !allowSHA1 && godebug.Get("x509sha1") != "1" {
return InsecureAlgorithmError(algo)
}
fallthrough

View File

@ -1864,9 +1864,7 @@ func TestSHA1(t *testing.T) {
t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err)
}
defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1)
debugAllowSHA1 = true
t.Setenv("GODEBUG", "x509sha1=1")
if err = cert.CheckSignatureFrom(cert); err != nil {
t.Fatalf("SHA-1 certificate did not verify with GODEBUG=x509sha1=1: %v", err)
}
@ -3335,8 +3333,7 @@ func TestLargeOID(t *testing.T) {
}
func TestDisableSHA1ForCertOnly(t *testing.T) {
defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1)
debugAllowSHA1 = false
t.Setenv("GODEBUG", "")
tmpl := &Certificate{
SerialNumber: big.NewInt(1),

View File

@ -168,6 +168,7 @@ var depsRules = `
io/fs
< internal/testlog
< internal/poll
< internal/safefilepath
< os
< os/signal;

View File

@ -0,0 +1,21 @@
// Copyright 2022 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 safefilepath manipulates operating-system file paths.
package safefilepath
import (
"errors"
)
var errInvalidPath = errors.New("invalid path")
// FromFS converts a slash-separated path into an operating-system path.
//
// FromFS returns an error if the path cannot be represented by the operating
// system. For example, paths containing '\' and ':' characters are rejected
// on Windows.
func FromFS(path string) (string, error) {
return fromFS(path)
}

View File

@ -0,0 +1,23 @@
// Copyright 2022 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.
//go:build !windows
package safefilepath
import "runtime"
func fromFS(path string) (string, error) {
if runtime.GOOS == "plan9" {
if len(path) > 0 && path[0] == '#' {
return path, errInvalidPath
}
}
for i := range path {
if path[i] == 0 {
return "", errInvalidPath
}
}
return path, nil
}

View File

@ -0,0 +1,88 @@
// Copyright 2022 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 safefilepath_test
import (
"internal/safefilepath"
"os"
"path/filepath"
"runtime"
"testing"
)
type PathTest struct {
path, result string
}
const invalid = ""
var fspathtests = []PathTest{
{".", "."},
{"/a/b/c", "/a/b/c"},
{"a\x00b", invalid},
}
var winreservedpathtests = []PathTest{
{`a\b`, `a\b`},
{`a:b`, `a:b`},
{`a/b:c`, `a/b:c`},
{`NUL`, `NUL`},
{`./com1`, `./com1`},
{`a/nul/b`, `a/nul/b`},
}
// Whether a reserved name with an extension is reserved or not varies by
// Windows version.
var winreservedextpathtests = []PathTest{
{"nul.txt", "nul.txt"},
{"a/nul.txt/b", "a/nul.txt/b"},
}
var plan9reservedpathtests = []PathTest{
{`#c`, `#c`},
}
func TestFromFS(t *testing.T) {
switch runtime.GOOS {
case "windows":
if canWriteFile(t, "NUL") {
t.Errorf("can unexpectedly write a file named NUL on Windows")
}
if canWriteFile(t, "nul.txt") {
fspathtests = append(fspathtests, winreservedextpathtests...)
} else {
winreservedpathtests = append(winreservedpathtests, winreservedextpathtests...)
}
for i := range winreservedpathtests {
winreservedpathtests[i].result = invalid
}
for i := range fspathtests {
fspathtests[i].result = filepath.FromSlash(fspathtests[i].result)
}
case "plan9":
for i := range plan9reservedpathtests {
plan9reservedpathtests[i].result = invalid
}
}
tests := fspathtests
tests = append(tests, winreservedpathtests...)
tests = append(tests, plan9reservedpathtests...)
for _, test := range tests {
got, err := safefilepath.FromFS(test.path)
if (got == "") != (err != nil) {
t.Errorf(`FromFS(%q) = %q, %v; want "" only if err != nil`, test.path, got, err)
}
if got != test.result {
t.Errorf("FromFS(%q) = %q, %v; want %q", test.path, got, err, test.result)
}
}
}
func canWriteFile(t *testing.T, name string) bool {
path := filepath.Join(t.TempDir(), name)
os.WriteFile(path, []byte("ok"), 0666)
b, _ := os.ReadFile(path)
return string(b) == "ok"
}

View File

@ -0,0 +1,95 @@
// Copyright 2022 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 safefilepath
import (
"syscall"
"unicode/utf8"
)
func fromFS(path string) (string, error) {
if !utf8.ValidString(path) {
return "", errInvalidPath
}
for len(path) > 1 && path[0] == '/' && path[1] == '/' {
path = path[1:]
}
containsSlash := false
for p := path; p != ""; {
// Find the next path element.
i := 0
dot := -1
for i < len(p) && p[i] != '/' {
switch p[i] {
case 0, '\\', ':':
return "", errInvalidPath
case '.':
if dot < 0 {
dot = i
}
}
i++
}
part := p[:i]
if i < len(p) {
containsSlash = true
p = p[i+1:]
} else {
p = ""
}
// Trim the extension and look for a reserved name.
base := part
if dot >= 0 {
base = part[:dot]
}
if isReservedName(base) {
if dot < 0 {
return "", errInvalidPath
}
// The path element is a reserved name with an extension.
// Some Windows versions consider this a reserved name,
// while others do not. Use FullPath to see if the name is
// reserved.
if p, _ := syscall.FullPath(part); len(p) >= 4 && p[:4] == `\\.\` {
return "", errInvalidPath
}
}
}
if containsSlash {
// We can't depend on strings, so substitute \ for / manually.
buf := []byte(path)
for i, b := range buf {
if b == '/' {
buf[i] = '\\'
}
}
path = string(buf)
}
return path, nil
}
// isReservedName reports if name is a Windows reserved device name.
// It does not detect names with an extension, which are also reserved on some Windows versions.
//
// For details, search for PRN in
// https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file.
func isReservedName(name string) bool {
if 3 <= len(name) && len(name) <= 4 {
switch string([]byte{toUpper(name[0]), toUpper(name[1]), toUpper(name[2])}) {
case "CON", "PRN", "AUX", "NUL":
return len(name) == 3
case "COM", "LPT":
return len(name) == 4 && '1' <= name[3] && name[3] <= '9'
}
}
return false
}
func toUpper(c byte) byte {
if 'a' <= c && c <= 'z' {
return c - ('a' - 'A')
}
return c
}

View File

@ -9,6 +9,7 @@ package http
import (
"errors"
"fmt"
"internal/safefilepath"
"io"
"io/fs"
"mime"
@ -69,14 +70,15 @@ func mapOpenError(originalErr error, name string, sep rune, stat func(string) (f
// Open implements FileSystem using os.Open, opening files for reading rooted
// and relative to the directory d.
func (d Dir) Open(name string) (File, error) {
if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) {
return nil, errors.New("http: invalid character in file path")
path, err := safefilepath.FromFS(path.Clean("/" + name))
if err != nil {
return nil, errors.New("http: invalid or unsafe file path")
}
dir := string(d)
if dir == "" {
dir = "."
}
fullName := filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name)))
fullName := filepath.Join(dir, path)
f, err := os.Open(fullName)
if err != nil {
return nil, mapOpenError(err, fullName, filepath.Separator, os.Stat)

View File

@ -648,6 +648,34 @@ func TestFileServerZeroByte(t *testing.T) {
}
}
func TestFileServerNamesEscape(t *testing.T) {
t.Run("h1", func(t *testing.T) {
testFileServerNamesEscape(t, h1Mode)
})
t.Run("h2", func(t *testing.T) {
testFileServerNamesEscape(t, h2Mode)
})
}
func testFileServerNamesEscape(t *testing.T, h2 bool) {
defer afterTest(t)
ts := newClientServerTest(t, h2, FileServer(Dir("testdata"))).ts
defer ts.Close()
for _, path := range []string{
"/../testdata/file",
"/NUL", // don't read from device files on Windows
} {
res, err := ts.Client().Get(ts.URL + path)
if err != nil {
t.Fatal(err)
}
res.Body.Close()
if res.StatusCode < 400 || res.StatusCode > 599 {
t.Errorf("Get(%q): got status %v, want 4xx or 5xx", path, res.StatusCode)
}
}
}
type fakeFileInfo struct {
dir bool
basename string

View File

@ -3384,10 +3384,11 @@ func (s http2SettingID) String() string {
// name (key). See httpguts.ValidHeaderName for the base rules.
//
// Further, http2 says:
// "Just as in HTTP/1.x, header field names are strings of ASCII
// characters that are compared in a case-insensitive
// fashion. However, header field names MUST be converted to
// lowercase prior to their encoding in HTTP/2. "
//
// "Just as in HTTP/1.x, header field names are strings of ASCII
// characters that are compared in a case-insensitive
// fashion. However, header field names MUST be converted to
// lowercase prior to their encoding in HTTP/2. "
func http2validWireHeaderFieldName(v string) bool {
if len(v) == 0 {
return false
@ -3578,8 +3579,8 @@ func (s *http2sorter) SortStrings(ss []string) {
// validPseudoPath reports whether v is a valid :path pseudo-header
// value. It must be either:
//
// *) a non-empty string starting with '/'
// *) the string '*', for OPTIONS requests.
// *) a non-empty string starting with '/'
// *) the string '*', for OPTIONS requests.
//
// For now this is only used a quick check for deciding when to clean
// up Opaque URLs before sending requests from the Transport.
@ -4242,6 +4243,7 @@ type http2serverConn struct {
headerTableSize uint32
peerMaxHeaderListSize uint32 // zero means unknown (default)
canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
canonHeaderKeysSize int // canonHeader keys size in bytes
writingFrame bool // started writing a frame (on serve goroutine or separate)
writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
needsFrameFlush bool // last frame write wasn't a flush
@ -4421,6 +4423,13 @@ func (sc *http2serverConn) condlogf(err error, format string, args ...interface{
}
}
// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size
// of the entries in the canonHeader cache.
// This should be larger than the size of unique, uncommon header keys likely to
// be sent by the peer, while not so high as to permit unreasonable memory usage
// if the peer sends an unbounded number of unique header keys.
const http2maxCachedCanonicalHeadersKeysSize = 2048
func (sc *http2serverConn) canonicalHeader(v string) string {
sc.serveG.check()
http2buildCommonHeaderMapsOnce()
@ -4436,14 +4445,10 @@ func (sc *http2serverConn) canonicalHeader(v string) string {
sc.canonHeader = make(map[string]string)
}
cv = CanonicalHeaderKey(v)
// maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
// entries in the canonHeader cache. This should be larger than the number
// of unique, uncommon header keys likely to be sent by the peer, while not
// so high as to permit unreaasonable memory usage if the peer sends an unbounded
// number of unique header keys.
const maxCachedCanonicalHeaders = 32
if len(sc.canonHeader) < maxCachedCanonicalHeaders {
size := 100 + len(v)*2 // 100 bytes of map overhead + key + value
if sc.canonHeaderKeysSize+size <= http2maxCachedCanonicalHeadersKeysSize {
sc.canonHeader[v] = cv
sc.canonHeaderKeysSize += size
}
return cv
}

View File

@ -71,6 +71,10 @@ var lookupGoogleSRVTests = []struct {
var backoffDuration = [...]time.Duration{time.Second, 5 * time.Second, 30 * time.Second}
func TestLookupGoogleSRV(t *testing.T) {
// TODO(mknyszek): Figure out next steps for this test. This is just
// a quick fix.
t.Skip("fails consistently due to an upstream DNS change; see #56707.")
t.Parallel()
mustHaveExternalNetwork(t)
@ -631,6 +635,10 @@ func TestLookupDotsWithLocalSource(t *testing.T) {
}
func TestLookupDotsWithRemoteSource(t *testing.T) {
// TODO(mknyszek): Figure out next steps for this test. This is just
// a quick fix.
t.Skip("fails consistently due to an upstream DNS change; see #56707.")
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
testenv.SkipFlaky(t, 27992)
}

View File

@ -12,6 +12,7 @@ import (
func TestDedupEnv(t *testing.T) {
tests := []struct {
noCase bool
nulOK bool
in []string
want []string
wantErr bool
@ -36,9 +37,15 @@ func TestDedupEnv(t *testing.T) {
want: []string{"B=b"},
wantErr: true,
},
{
// Plan 9 needs to preserve environment variables with NUL (#56544).
nulOK: true,
in: []string{"path=one\x00two"},
want: []string{"path=one\x00two"},
},
}
for _, tt := range tests {
got, err := dedupEnvCase(tt.noCase, tt.in)
got, err := dedupEnvCase(tt.noCase, tt.nulOK, tt.in)
if !reflect.DeepEqual(got, tt.want) || (err != nil) != tt.wantErr {
t.Errorf("Dedup(%v, %q) = %q, %v; want %q, error:%v", tt.noCase, tt.in, got, err, tt.want, tt.wantErr)
}

View File

@ -745,23 +745,27 @@ func minInt(a, b int) int {
// dedupEnv returns a copy of env with any duplicates removed, in favor of
// later values.
// Items not of the normal environment "key=value" form are preserved unchanged.
// Items containing NUL characters are removed, and an error is returned along with
// the remaining values.
// Except on Plan 9, items containing NUL characters are removed, and
// an error is returned along with the remaining values.
func dedupEnv(env []string) ([]string, error) {
return dedupEnvCase(runtime.GOOS == "windows", env)
return dedupEnvCase(runtime.GOOS == "windows", runtime.GOOS == "plan9", env)
}
// dedupEnvCase is dedupEnv with a case option for testing.
// If caseInsensitive is true, the case of keys is ignored.
func dedupEnvCase(caseInsensitive bool, env []string) ([]string, error) {
// If nulOK is false, items containing NUL characters are allowed.
func dedupEnvCase(caseInsensitive, nulOK bool, env []string) ([]string, error) {
var err error
out := make([]string, 0, len(env))
saw := make(map[string]int, len(env)) // key => index into out
for _, kv := range env {
if strings.IndexByte(kv, 0) != -1 {
// Reject NUL in environment variables to prevent security issues (#56284);
// except on Plan 9, which uses NUL as os.PathListSeparator (#56544).
if !nulOK && strings.IndexByte(kv, 0) != -1 {
err = errors.New("exec: environment variable contains NUL")
continue
}
k, _, ok := strings.Cut(kv, "=")
if !ok {
out = append(out, kv)

View File

@ -1030,6 +1030,9 @@ func TestDedupEnvEcho(t *testing.T) {
}
func TestEnvNULCharacter(t *testing.T) {
if runtime.GOOS == "plan9" {
t.Skip("plan9 explicitly allows NUL in the enviroment")
}
cmd := helperCommand(t, "echoenv", "FOO", "BAR")
cmd.Env = append(cmd.Env, "FOO=foo\x00BAR=bar")
out, err := cmd.CombinedOutput()

View File

@ -37,12 +37,12 @@
// Note: The maximum number of concurrent operations on a File may be limited by
// the OS or the system. The number should be high, but exceeding it may degrade
// performance or cause other issues.
//
package os
import (
"errors"
"internal/poll"
"internal/safefilepath"
"internal/testlog"
"internal/unsafeheader"
"io"
@ -623,6 +623,8 @@ func isWindowsNulName(name string) bool {
// the /prefix tree, then using DirFS does not stop the access any more than using
// os.Open does. DirFS is therefore not a general substitute for a chroot-style security
// mechanism when the directory tree contains arbitrary content.
//
// The directory dir must not be "".
func DirFS(dir string) fs.FS {
return dirFS(dir)
}
@ -641,10 +643,11 @@ func containsAny(s, chars string) bool {
type dirFS string
func (dir dirFS) Open(name string) (fs.File, error) {
if !fs.ValidPath(name) || runtime.GOOS == "windows" && containsAny(name, `\:`) {
return nil, &PathError{Op: "open", Path: name, Err: ErrInvalid}
fullname, err := dir.join(name)
if err != nil {
return nil, &PathError{Op: "stat", Path: name, Err: err}
}
f, err := Open(string(dir) + "/" + name)
f, err := Open(fullname)
if err != nil {
return nil, err // nil fs.File
}
@ -652,16 +655,35 @@ func (dir dirFS) Open(name string) (fs.File, error) {
}
func (dir dirFS) Stat(name string) (fs.FileInfo, error) {
if !fs.ValidPath(name) || runtime.GOOS == "windows" && containsAny(name, `\:`) {
return nil, &PathError{Op: "stat", Path: name, Err: ErrInvalid}
fullname, err := dir.join(name)
if err != nil {
return nil, &PathError{Op: "stat", Path: name, Err: err}
}
f, err := Stat(string(dir) + "/" + name)
f, err := Stat(fullname)
if err != nil {
return nil, err
}
return f, nil
}
// join returns the path for name in dir.
func (dir dirFS) join(name string) (string, error) {
if dir == "" {
return "", errors.New("os: DirFS with empty root")
}
if !fs.ValidPath(name) {
return "", ErrInvalid
}
name, err := safefilepath.FromFS(name)
if err != nil {
return "", ErrInvalid
}
if IsPathSeparator(dir[len(dir)-1]) {
return string(dir) + name, nil
}
return string(dir) + string(PathSeparator) + name, nil
}
// ReadFile reads the named file and returns the contents.
// A successful call returns err == nil, not err == EOF.
// Because ReadFile reads the whole file, it does not treat an EOF from Read

View File

@ -2696,6 +2696,44 @@ func TestDirFS(t *testing.T) {
if err == nil {
t.Fatalf(`Open testdata\dirfs succeeded`)
}
// Test that Open does not open Windows device files.
_, err = d.Open(`NUL`)
if err == nil {
t.Errorf(`Open NUL succeeded`)
}
}
func TestDirFSRootDir(t *testing.T) {
cwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
cwd = cwd[len(filepath.VolumeName(cwd)):] // trim volume prefix (C:) on Windows
cwd = filepath.ToSlash(cwd) // convert \ to /
cwd = strings.TrimPrefix(cwd, "/") // trim leading /
// Test that Open can open a path starting at /.
d := DirFS("/")
f, err := d.Open(cwd + "/testdata/dirfs/a")
if err != nil {
t.Fatal(err)
}
f.Close()
}
func TestDirFSEmptyDir(t *testing.T) {
d := DirFS("")
cwd, _ := os.Getwd()
for _, path := range []string{
"testdata/dirfs/a", // not DirFS(".")
filepath.ToSlash(cwd) + "/testdata/dirfs/a", // not DirFS("/")
} {
_, err := d.Open(path)
if err == nil {
t.Fatalf(`DirFS("").Open(%q) succeeded`, path)
}
}
}
func TestDirFSPathsValid(t *testing.T) {

View File

@ -1135,6 +1135,16 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
// the garbage collector could follow a pointer to x,
// but see uninitialized memory or stale heap bits.
publicationBarrier()
// As x and the heap bits are initialized, update
// freeIndexForScan now so x is seen by the GC
// (including convervative scan) as an allocated object.
// While this pointer can't escape into user code as a
// _live_ pointer until we return, conservative scanning
// may find a dead pointer that happens to point into this
// object. Delaying this update until now ensures that
// conservative scanning considers this pointer dead until
// this point.
span.freeIndexForScan = span.freeindex
// Allocate black during GC.
// All slots hold nil so no scanning is needed.

View File

@ -220,7 +220,7 @@ func (s *mspan) nextFreeIndex() uintptr {
// been no preemption points since ensuring this (which could allow a
// GC transition, which would allow the state to change).
func (s *mspan) isFree(index uintptr) bool {
if index < s.freeindex {
if index < s.freeIndexForScan {
return false
}
bytep, mask := s.allocBits.bitp(index)

View File

@ -623,6 +623,7 @@ func (sl *sweepLocked) sweep(preserve bool) bool {
s.allocCount = nalloc
s.freeindex = 0 // reset allocation index to start of span.
s.freeIndexForScan = 0
if trace.enabled {
getg().m.p.ptr().traceReclaimed += uintptr(nfreed) * s.elemsize
}

View File

@ -459,6 +459,14 @@ type mspan struct {
limit uintptr // end of data in span
speciallock mutex // guards specials list
specials *special // linked list of special records sorted by offset.
// freeIndexForScan is like freeindex, except that freeindex is
// used by the allocator whereas freeIndexForScan is used by the
// GC scanner. They are two fields so that the GC sees the object
// is allocated only when the object and the heap bits are
// initialized (see also the assignment of freeIndexForScan in
// mallocgc, and issue 54596).
freeIndexForScan uintptr
}
func (s *mspan) base() uintptr {
@ -1250,6 +1258,7 @@ HaveSpan:
// Initialize mark and allocation structures.
s.freeindex = 0
s.freeIndexForScan = 0
s.allocCache = ^uint64(0) // all 1s indicating all free.
s.gcmarkBits = newMarkBits(s.nelems)
s.allocBits = newAllocBits(s.nelems)
@ -1565,6 +1574,7 @@ func (span *mspan) init(base uintptr, npages uintptr) {
span.specials = nil
span.needzero = 0
span.freeindex = 0
span.freeIndexForScan = 0
span.allocBits = nil
span.gcmarkBits = nil
span.state.set(mSpanDead)

View File

@ -119,16 +119,23 @@ TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
MOVW R3, errno+16(FP)
RET
// func usleep(usec uint32)
TEXT runtime·usleep(SB),NOSPLIT,$16-4
MOVW usec+0(FP), R3
MOVD R3, R5
MOVW $1000000, R4
DIVD R4, R3
MOVD R3, 8(R1)
MOVW $1000, R4
MULLD R3, R4
SUB R4, R5
MOVD R5, 16(R1)
// Use magic constant 0x8637bd06 and shift right 51
// to perform usec/1000000.
ORIS $0x8637, R0, R4 // Note, R0 always contains 0 here.
OR $0xbd06, R4, R4
MULLD R3, R4, R4 // Convert usec to S.
SRD $51, R4, R4
MOVD R4, 8(R1) // Store to tv_sec
MOVD $1000000, R5
MULLW R4, R5, R5 // Convert tv_sec back into uS
SUB R5, R3, R5 // Compute remainder uS.
MULLD $1000, R5, R5 // Convert to nsec
MOVD R5, 16(R1) // Store to tv_nsec
// nanosleep(&ts, 0)
ADD $8, R1, R3

View File

@ -182,6 +182,17 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
case funcID_systemstack:
// systemstack returns normally, so just follow the
// stack transition.
if usesLR && funcspdelta(f, frame.pc, &cache) == 0 {
// We're at the function prologue and the stack
// switch hasn't happened, or epilogue where we're
// about to return. Just unwind normally.
// Do this only on LR machines because on x86
// systemstack doesn't have an SP delta (the CALL
// instruction opens the frame), therefore no way
// to check.
flag &^= funcFlag_SPWRITE
break
}
frame.sp = gp.m.curg.sched.sp
stack = gp.m.curg.stack
cgoCtxt = gp.m.curg.cgoCtxt

View File

@ -0,0 +1,21 @@
// errorcheck -0 -lang=go1.17
// Copyright 2022 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.
// Prior to Go 1.18, ineffectual //go:linkname directives were treated
// as noops. Ensure that modules that contain these directives (e.g.,
// x/sys prior to go.dev/cl/274573) continue to compile.
package p
import _ "unsafe"
//go:linkname nonexistent nonexistent
//go:linkname constant constant
const constant = 42
//go:linkname typename typename
type typename int