mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
[dev.boringcrypto.go1.18] all: merge go1.18.9 into dev.boringcrypto.go1.18
Change-Id: I5eda3a3fb2fc381e237d18d2846cf1b1810d8015
This commit is contained in:
commit
fc1ed37e82
@ -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
|
||||
|
@ -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 != "" {
|
||||
|
65
src/cmd/compile/internal/test/race.go
Normal file
65
src/cmd/compile/internal/test/race.go
Normal 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
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -168,6 +168,7 @@ var depsRules = `
|
||||
io/fs
|
||||
< internal/testlog
|
||||
< internal/poll
|
||||
< internal/safefilepath
|
||||
< os
|
||||
< os/signal;
|
||||
|
||||
|
21
src/internal/safefilepath/path.go
Normal file
21
src/internal/safefilepath/path.go
Normal 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)
|
||||
}
|
23
src/internal/safefilepath/path_other.go
Normal file
23
src/internal/safefilepath/path_other.go
Normal 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
|
||||
}
|
88
src/internal/safefilepath/path_test.go
Normal file
88
src/internal/safefilepath/path_test.go
Normal 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"
|
||||
}
|
95
src/internal/safefilepath/path_windows.go
Normal file
95
src/internal/safefilepath/path_windows.go
Normal 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
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
21
test/fixedbugs/issue55889.go
Normal file
21
test/fixedbugs/issue55889.go
Normal 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
|
Loading…
x
Reference in New Issue
Block a user