mirror of
https://github.com/golang/go.git
synced 2026-01-30 15:42:04 +03:00
Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d828e80fa | ||
|
|
825eeee3f7 | ||
|
|
dbf30d88f3 | ||
|
|
6b51660c8c | ||
|
|
cc604130c8 | ||
|
|
21b488bb60 | ||
|
|
e038690847 | ||
|
|
1575127ef8 | ||
|
|
7d08a16fba | ||
|
|
5f2cbe1f64 | ||
|
|
6796ebb2cb | ||
|
|
85897ca220 | ||
|
|
9f9cf28f8f | ||
|
|
a31c931adf | ||
|
|
03811ab1b3 | ||
|
|
04a9473847 | ||
|
|
db8f1dc948 | ||
|
|
664cf832ec | ||
|
|
431f75a0b9 | ||
|
|
34c8b14ca9 | ||
|
|
8947f3395e | ||
|
|
06fd2f115b | ||
|
|
f66ab6521c | ||
|
|
c1f9c2c7b0 | ||
|
|
0ab64e2caa | ||
|
|
56eb99859d | ||
|
|
43130aff52 | ||
|
|
b2c005e7b2 | ||
|
|
a9d9b55709 | ||
|
|
fa7217f74d | ||
|
|
49860cf92a | ||
|
|
f3a302358f | ||
|
|
1d755aa488 | ||
|
|
9204aca6c2 | ||
|
|
0ae3ca0a20 | ||
|
|
dae59b594c | ||
|
|
b7fd97ae3e | ||
|
|
311096a6a2 | ||
|
|
e9162e7e22 | ||
|
|
d107ee90df | ||
|
|
213f1566ee | ||
|
|
ac1f5aa3d6 | ||
|
|
fd29397dca | ||
|
|
4524009ba6 | ||
|
|
bd1bc8a6e7 | ||
|
|
c2a34bedee | ||
|
|
0ace2d8aca | ||
|
|
e4119e9b74 | ||
|
|
339c903a75 | ||
|
|
334de7982f | ||
|
|
5d6920842b | ||
|
|
949eae84df | ||
|
|
0bfde51e0d | ||
|
|
45a52718e3 | ||
|
|
7f375e2c22 | ||
|
|
4070531920 | ||
|
|
5ffdb9c88b | ||
|
|
becc17ebcd | ||
|
|
d418e224ae | ||
|
|
456eaf5c29 | ||
|
|
e4ef83383e | ||
|
|
4e6d3468cc | ||
|
|
f5c388313f | ||
|
|
af236716b2 | ||
|
|
0f7b7600fb | ||
|
|
eb58df7dbf | ||
|
|
30f4d9e117 | ||
|
|
bb0e5c2045 | ||
|
|
cd0e528d3d | ||
|
|
80e2e474b8 | ||
|
|
3901409b5d | ||
|
|
35c0ea22a9 | ||
|
|
6d399e9da6 | ||
|
|
b7b4c60585 | ||
|
|
18068cb96a | ||
|
|
c43ac38b3b | ||
|
|
4241f582fc | ||
|
|
8a4c24f9bb | ||
|
|
3de5aca7d0 | ||
|
|
8336dfde70 | ||
|
|
6b60550504 | ||
|
|
468fad45a2 | ||
|
|
e06b6fc58d | ||
|
|
b3799ba634 | ||
|
|
16afa6a740 | ||
|
|
817d7bdc0a | ||
|
|
14bb1e11b9 | ||
|
|
2297c34cdf | ||
|
|
26682773ca |
@@ -1 +1,2 @@
|
||||
branch: master
|
||||
branch: release-branch.go1.24
|
||||
parent-branch: master
|
||||
|
||||
@@ -153,6 +153,17 @@ and the [go command documentation](/cmd/go#hdr-Build_and_test_caching).
|
||||
|
||||
### Go 1.24
|
||||
|
||||
Go 1.24 added a new `fips140` setting that controls whether the Go
|
||||
Cryptographic Module operates in FIPS 140-3 mode.
|
||||
The possible values are:
|
||||
- "off": no special support for FIPS 140-3 mode. This is the default.
|
||||
- "on": the Go Cryptographic Module operates in FIPS 140-3 mode.
|
||||
- "only": like "on", but cryptographic algorithms not approved by
|
||||
FIPS 140-3 return an error or panic.
|
||||
For more information, see [FIPS 140-3 Compliance](/doc/security/fips140).
|
||||
This setting is fixed at program startup time, and can't be modified
|
||||
by changing the `GODEBUG` environment variable after the program starts.
|
||||
|
||||
Go 1.24 changed the global [`math/rand.Seed`](/pkg/math/rand/#Seed) to be a
|
||||
no-op. This behavior is controlled by the `randseednop` setting.
|
||||
For Go 1.24 it defaults to `randseednop=1`.
|
||||
@@ -213,6 +224,10 @@ use and validate the CRT parameters in the encoded private key. This behavior
|
||||
can be controlled with the `x509rsacrt` setting. Using `x509rsacrt=0` restores
|
||||
the Go 1.23 behavior.
|
||||
|
||||
Go 1.24.5 disabled build information stamping when multiple VCS are detected due
|
||||
to concerns around VCS injection attacks. This behavior can be renabled with the
|
||||
setting `allowmultiplevcs=1`.
|
||||
|
||||
### Go 1.23
|
||||
|
||||
Go 1.23 changed the channels created by package time to be unbuffered
|
||||
|
||||
1
lib/fips140/inprocess.txt
Normal file
1
lib/fips140/inprocess.txt
Normal file
@@ -0,0 +1 @@
|
||||
v1.0.0
|
||||
@@ -67,26 +67,26 @@ func splitSeq(s, sep []byte, sepSave int) iter.Seq[[]byte] {
|
||||
}
|
||||
}
|
||||
|
||||
// SplitSeq returns an iterator over all substrings of s separated by sep.
|
||||
// The iterator yields the same strings that would be returned by [Split](s, sep),
|
||||
// but without constructing the slice.
|
||||
// SplitSeq returns an iterator over all subslices of s separated by sep.
|
||||
// The iterator yields the same subslices that would be returned by [Split](s, sep),
|
||||
// but without constructing a new slice containing the subslices.
|
||||
// It returns a single-use iterator.
|
||||
func SplitSeq(s, sep []byte) iter.Seq[[]byte] {
|
||||
return splitSeq(s, sep, 0)
|
||||
}
|
||||
|
||||
// SplitAfterSeq returns an iterator over substrings of s split after each instance of sep.
|
||||
// The iterator yields the same strings that would be returned by [SplitAfter](s, sep),
|
||||
// but without constructing the slice.
|
||||
// SplitAfterSeq returns an iterator over subslices of s split after each instance of sep.
|
||||
// The iterator yields the same subslices that would be returned by [SplitAfter](s, sep),
|
||||
// but without constructing a new slice containing the subslices.
|
||||
// It returns a single-use iterator.
|
||||
func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] {
|
||||
return splitSeq(s, sep, len(sep))
|
||||
}
|
||||
|
||||
// FieldsSeq returns an iterator over substrings of s split around runs of
|
||||
// FieldsSeq returns an iterator over subslices of s split around runs of
|
||||
// whitespace characters, as defined by [unicode.IsSpace].
|
||||
// The iterator yields the same strings that would be returned by [Fields](s),
|
||||
// but without constructing the slice.
|
||||
// The iterator yields the same subslices that would be returned by [Fields](s),
|
||||
// but without constructing a new slice containing the subslices.
|
||||
func FieldsSeq(s []byte) iter.Seq[[]byte] {
|
||||
return func(yield func([]byte) bool) {
|
||||
start := -1
|
||||
@@ -116,10 +116,10 @@ func FieldsSeq(s []byte) iter.Seq[[]byte] {
|
||||
}
|
||||
}
|
||||
|
||||
// FieldsFuncSeq returns an iterator over substrings of s split around runs of
|
||||
// FieldsFuncSeq returns an iterator over subslices of s split around runs of
|
||||
// Unicode code points satisfying f(c).
|
||||
// The iterator yields the same strings that would be returned by [FieldsFunc](s),
|
||||
// but without constructing the slice.
|
||||
// The iterator yields the same subslices that would be returned by [FieldsFunc](s),
|
||||
// but without constructing a new slice containing the subslices.
|
||||
func FieldsFuncSeq(s []byte, f func(rune) bool) iter.Seq[[]byte] {
|
||||
return func(yield func([]byte) bool) {
|
||||
start := -1
|
||||
|
||||
@@ -27,6 +27,7 @@ func test42018(t *testing.T) {
|
||||
recurseHWND(400, hwnd, uintptr(unsafe.Pointer(&i)))
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func recurseHANDLE(n int, p C.HANDLE, v uintptr) {
|
||||
if n > 0 {
|
||||
recurseHANDLE(n-1, p, v)
|
||||
@@ -36,6 +37,7 @@ func recurseHANDLE(n int, p C.HANDLE, v uintptr) {
|
||||
}
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func recurseHWND(n int, p C.HWND, v uintptr) {
|
||||
if n > 0 {
|
||||
recurseHWND(n-1, p, v)
|
||||
|
||||
@@ -42,6 +42,8 @@ func TestASAN(t *testing.T) {
|
||||
{src: "asan_global3_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global3_fail.go:13"},
|
||||
{src: "asan_global4_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global4_fail.go:21"},
|
||||
{src: "asan_global5.go"},
|
||||
{src: "asan_global_asm"},
|
||||
{src: "asan_global_asm2_fail", memoryAccessError: "global-buffer-overflow", errorLocation: "main.go:17"},
|
||||
{src: "arena_fail.go", memoryAccessError: "use-after-poison", errorLocation: "arena_fail.go:26", experiments: []string{"arenas"}},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
|
||||
@@ -536,7 +536,7 @@ func (c *config) checkRuntime() (skip bool, err error) {
|
||||
|
||||
// srcPath returns the path to the given file relative to this test's source tree.
|
||||
func srcPath(path string) string {
|
||||
return filepath.Join("testdata", path)
|
||||
return "./testdata/" + path
|
||||
}
|
||||
|
||||
// A tempDir manages a temporary directory within a test.
|
||||
|
||||
8
src/cmd/cgo/internal/testsanitizers/testdata/asan_global_asm/asm.s
vendored
Normal file
8
src/cmd/cgo/internal/testsanitizers/testdata/asan_global_asm/asm.s
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2025 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.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
DATA ·x(SB)/8, $123
|
||||
GLOBL ·x(SB), NOPTR, $8
|
||||
11
src/cmd/cgo/internal/testsanitizers/testdata/asan_global_asm/main.go
vendored
Normal file
11
src/cmd/cgo/internal/testsanitizers/testdata/asan_global_asm/main.go
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2025 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
|
||||
|
||||
var x uint64
|
||||
|
||||
func main() {
|
||||
println(x)
|
||||
}
|
||||
8
src/cmd/cgo/internal/testsanitizers/testdata/asan_global_asm2_fail/asm.s
vendored
Normal file
8
src/cmd/cgo/internal/testsanitizers/testdata/asan_global_asm2_fail/asm.s
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2025 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.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
DATA ·x(SB)/8, $123
|
||||
GLOBL ·x(SB), NOPTR, $8
|
||||
20
src/cmd/cgo/internal/testsanitizers/testdata/asan_global_asm2_fail/main.go
vendored
Normal file
20
src/cmd/cgo/internal/testsanitizers/testdata/asan_global_asm2_fail/main.go
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2025 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 "unsafe"
|
||||
|
||||
var x uint64
|
||||
|
||||
func main() {
|
||||
bar(&x)
|
||||
}
|
||||
|
||||
func bar(a *uint64) {
|
||||
p := (*uint64)(unsafe.Add(unsafe.Pointer(a), 1*unsafe.Sizeof(uint64(1))))
|
||||
if *p == 10 { // BOOM
|
||||
println("its value is 10")
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ import (
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/pgo"
|
||||
"cmd/internal/src"
|
||||
)
|
||||
|
||||
// Inlining budget parameters, gathered in one place
|
||||
@@ -169,19 +170,8 @@ func CanInlineFuncs(funcs []*ir.Func, profile *pgoir.Profile) {
|
||||
}
|
||||
|
||||
ir.VisitFuncsBottomUp(funcs, func(funcs []*ir.Func, recursive bool) {
|
||||
numfns := numNonClosures(funcs)
|
||||
|
||||
for _, fn := range funcs {
|
||||
if !recursive || numfns > 1 {
|
||||
// We allow inlining if there is no
|
||||
// recursion, or the recursion cycle is
|
||||
// across more than one function.
|
||||
CanInline(fn, profile)
|
||||
} else {
|
||||
if base.Flag.LowerM > 1 && fn.OClosure == nil {
|
||||
fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(fn), fn.Nname)
|
||||
}
|
||||
}
|
||||
CanInline(fn, profile)
|
||||
if inlheur.Enabled() {
|
||||
analyzeFuncProps(fn, profile)
|
||||
}
|
||||
@@ -974,6 +964,16 @@ func inlineCostOK(n *ir.CallExpr, caller, callee *ir.Func, bigCaller, closureCal
|
||||
return true, 0, metric, hot
|
||||
}
|
||||
|
||||
// parsePos returns all the inlining positions and the innermost position.
|
||||
func parsePos(pos src.XPos, posTmp []src.Pos) ([]src.Pos, src.Pos) {
|
||||
ctxt := base.Ctxt
|
||||
ctxt.AllPos(pos, func(p src.Pos) {
|
||||
posTmp = append(posTmp, p)
|
||||
})
|
||||
l := len(posTmp) - 1
|
||||
return posTmp[:l], posTmp[l]
|
||||
}
|
||||
|
||||
// canInlineCallExpr returns true if the call n from caller to callee
|
||||
// can be inlined, plus the score computed for the call expr in question,
|
||||
// and whether the callee is hot according to PGO.
|
||||
@@ -1001,12 +1001,15 @@ func canInlineCallExpr(callerfn *ir.Func, n *ir.CallExpr, callee *ir.Func, bigCa
|
||||
return false, 0, false
|
||||
}
|
||||
|
||||
if callee == callerfn {
|
||||
// Can't recursively inline a function into itself.
|
||||
if log && logopt.Enabled() {
|
||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to %s", ir.FuncName(callerfn)))
|
||||
callees, calleeInner := parsePos(n.Pos(), make([]src.Pos, 0, 10))
|
||||
|
||||
for _, p := range callees {
|
||||
if p.Line() == calleeInner.Line() && p.Col() == calleeInner.Col() && p.AbsFilename() == calleeInner.AbsFilename() {
|
||||
if log && logopt.Enabled() {
|
||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to %s", ir.FuncName(callerfn)))
|
||||
}
|
||||
return false, 0, false
|
||||
}
|
||||
return false, 0, false
|
||||
}
|
||||
|
||||
if base.Flag.Cfg.Instrumenting && types.IsNoInstrumentPkg(callee.Sym().Pkg) {
|
||||
|
||||
@@ -253,7 +253,7 @@ func (s *inlClosureState) mark(n ir.Node) ir.Node {
|
||||
|
||||
if isTestingBLoop(n) {
|
||||
// No inlining nor devirtualization performed on b.Loop body
|
||||
if base.Flag.LowerM > 1 {
|
||||
if base.Flag.LowerM > 0 {
|
||||
fmt.Printf("%v: skip inlining within testing.B.loop for %v\n", ir.Line(n), n)
|
||||
}
|
||||
// We still want to explore inlining opportunities in other parts of ForStmt.
|
||||
|
||||
@@ -886,8 +886,8 @@ func init() {
|
||||
inputs: []regMask{buildReg("DI")},
|
||||
clobbers: buildReg("DI"),
|
||||
},
|
||||
faultOnNilArg0: true,
|
||||
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
|
||||
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
|
||||
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
|
||||
},
|
||||
|
||||
// arg0 = address of memory to zero
|
||||
@@ -924,10 +924,10 @@ func init() {
|
||||
inputs: []regMask{buildReg("DI"), buildReg("SI")},
|
||||
clobbers: buildReg("DI SI X0"), // uses X0 as a temporary
|
||||
},
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
faultOnNilArg1: true,
|
||||
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
|
||||
clobberFlags: true,
|
||||
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
|
||||
//faultOnNilArg1: true,
|
||||
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
|
||||
},
|
||||
|
||||
// arg0 = destination pointer
|
||||
|
||||
@@ -1148,10 +1148,12 @@
|
||||
(SUB a l:(MNEGW x y)) && v.Type.Size() <= 4 && l.Uses==1 && clobber(l) => (MADDW a x y)
|
||||
|
||||
// madd/msub can't take constant arguments, so do a bit of reordering if a non-constant is available.
|
||||
(ADD a p:(ADDconst [c] m:((MUL|MULW|MNEG|MNEGW) _ _))) && p.Uses==1 && m.Uses==1 => (ADDconst [c] (ADD <v.Type> a m))
|
||||
(ADD a p:(SUBconst [c] m:((MUL|MULW|MNEG|MNEGW) _ _))) && p.Uses==1 && m.Uses==1 => (SUBconst [c] (ADD <v.Type> a m))
|
||||
(SUB a p:(ADDconst [c] m:((MUL|MULW|MNEG|MNEGW) _ _))) && p.Uses==1 && m.Uses==1 => (SUBconst [c] (SUB <v.Type> a m))
|
||||
(SUB a p:(SUBconst [c] m:((MUL|MULW|MNEG|MNEGW) _ _))) && p.Uses==1 && m.Uses==1 => (ADDconst [c] (SUB <v.Type> a m))
|
||||
// Note: don't reorder arithmetic concerning pointers, as we must ensure that
|
||||
// no intermediate computations are invalid pointers.
|
||||
(ADD <t> a p:(ADDconst [c] m:((MUL|MULW|MNEG|MNEGW) _ _))) && p.Uses==1 && m.Uses==1 && !t.IsPtrShaped() => (ADDconst [c] (ADD <v.Type> a m))
|
||||
(ADD <t> a p:(SUBconst [c] m:((MUL|MULW|MNEG|MNEGW) _ _))) && p.Uses==1 && m.Uses==1 && !t.IsPtrShaped() => (SUBconst [c] (ADD <v.Type> a m))
|
||||
(SUB <t> a p:(ADDconst [c] m:((MUL|MULW|MNEG|MNEGW) _ _))) && p.Uses==1 && m.Uses==1 && !t.IsPtrShaped() => (SUBconst [c] (SUB <v.Type> a m))
|
||||
(SUB <t> a p:(SUBconst [c] m:((MUL|MULW|MNEG|MNEGW) _ _))) && p.Uses==1 && m.Uses==1 && !t.IsPtrShaped() => (ADDconst [c] (SUB <v.Type> a m))
|
||||
|
||||
// optimize ADCSflags, SBCSflags and friends
|
||||
(ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] (ADCzerocarry <typ.UInt64> c)))) => (ADCSflags x y c)
|
||||
|
||||
@@ -536,8 +536,8 @@ func init() {
|
||||
inputs: []regMask{buildReg("R20")},
|
||||
clobbers: buildReg("R16 R17 R20 R30"),
|
||||
},
|
||||
faultOnNilArg0: true,
|
||||
unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts
|
||||
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
|
||||
unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts
|
||||
},
|
||||
|
||||
// large zeroing
|
||||
@@ -577,9 +577,9 @@ func init() {
|
||||
inputs: []regMask{buildReg("R21"), buildReg("R20")},
|
||||
clobbers: buildReg("R16 R17 R20 R21 R26 R30"),
|
||||
},
|
||||
faultOnNilArg0: true,
|
||||
faultOnNilArg1: true,
|
||||
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
|
||||
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
|
||||
//faultOnNilArg1: true,
|
||||
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
|
||||
},
|
||||
|
||||
// large move
|
||||
|
||||
@@ -41,11 +41,12 @@ type Func struct {
|
||||
ABISelf *abi.ABIConfig // ABI for function being compiled
|
||||
ABIDefault *abi.ABIConfig // ABI for rtcall and other no-parsed-signature/pragma functions.
|
||||
|
||||
scheduled bool // Values in Blocks are in final order
|
||||
laidout bool // Blocks are ordered
|
||||
NoSplit bool // true if function is marked as nosplit. Used by schedule check pass.
|
||||
dumpFileSeq uint8 // the sequence numbers of dump file. (%s_%02d__%s.dump", funcname, dumpFileSeq, phaseName)
|
||||
IsPgoHot bool
|
||||
scheduled bool // Values in Blocks are in final order
|
||||
laidout bool // Blocks are ordered
|
||||
NoSplit bool // true if function is marked as nosplit. Used by schedule check pass.
|
||||
dumpFileSeq uint8 // the sequence numbers of dump file. (%s_%02d__%s.dump", funcname, dumpFileSeq, phaseName)
|
||||
IsPgoHot bool
|
||||
HasDeferRangeFunc bool // if true, needs a deferreturn so deferrangefunc can use it for recover() return PC
|
||||
|
||||
// when register allocation is done, maps value ids to locations
|
||||
RegAlloc []Location
|
||||
|
||||
@@ -13777,11 +13777,10 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DUFFZERO",
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
faultOnNilArg0: true,
|
||||
unsafePoint: true,
|
||||
name: "DUFFZERO",
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
unsafePoint: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 128}, // DI
|
||||
@@ -13851,13 +13850,11 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DUFFCOPY",
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
faultOnNilArg1: true,
|
||||
unsafePoint: true,
|
||||
name: "DUFFCOPY",
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
unsafePoint: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 128}, // DI
|
||||
@@ -22970,11 +22967,10 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DUFFZERO",
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
faultOnNilArg0: true,
|
||||
unsafePoint: true,
|
||||
name: "DUFFZERO",
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
unsafePoint: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 1048576}, // R20
|
||||
@@ -22996,12 +22992,10 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DUFFCOPY",
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
faultOnNilArg0: true,
|
||||
faultOnNilArg1: true,
|
||||
unsafePoint: true,
|
||||
name: "DUFFCOPY",
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
unsafePoint: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 2097152}, // R21
|
||||
|
||||
@@ -552,8 +552,9 @@ func (ft *factsTable) newLimit(v *Value, newLim limit) bool {
|
||||
}
|
||||
|
||||
if lim.unsat() {
|
||||
r := !ft.unsat
|
||||
ft.unsat = true
|
||||
return true
|
||||
return r
|
||||
}
|
||||
|
||||
// Check for recursion. This normally happens because in unsatisfiable
|
||||
|
||||
@@ -1670,6 +1670,7 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||
}
|
||||
tmpReg = s.allocReg(m, &tmpVal)
|
||||
s.nospill |= regMask(1) << tmpReg
|
||||
s.tmpused |= regMask(1) << tmpReg
|
||||
}
|
||||
|
||||
// Now that all args are in regs, we're ready to issue the value itself.
|
||||
|
||||
@@ -1470,6 +1470,11 @@ func GetPPC64Shiftme(auxint int64) int64 {
|
||||
// operation. Masks can also extend from the msb and wrap to
|
||||
// the lsb too. That is, the valid masks are 32 bit strings
|
||||
// of the form: 0..01..10..0 or 1..10..01..1 or 1...1
|
||||
//
|
||||
// Note: This ignores the upper 32 bits of the input. When a
|
||||
// zero extended result is desired (e.g a 64 bit result), the
|
||||
// user must verify the upper 32 bits are 0 and the mask is
|
||||
// contiguous (that is, non-wrapping).
|
||||
func isPPC64WordRotateMask(v64 int64) bool {
|
||||
// Isolate rightmost 1 (if none 0) and add.
|
||||
v := uint32(v64)
|
||||
@@ -1480,6 +1485,16 @@ func isPPC64WordRotateMask(v64 int64) bool {
|
||||
return (v&vp == 0 || vn&vpn == 0) && v != 0
|
||||
}
|
||||
|
||||
// Test if this mask is a valid, contiguous bitmask which can be
|
||||
// represented by a RLWNM mask and also clears the upper 32 bits
|
||||
// of the register.
|
||||
func isPPC64WordRotateMaskNonWrapping(v64 int64) bool {
|
||||
// Isolate rightmost 1 (if none 0) and add.
|
||||
v := uint32(v64)
|
||||
vp := (v & -v) + v
|
||||
return (v&vp == 0) && v != 0 && uint64(uint32(v64)) == uint64(v64)
|
||||
}
|
||||
|
||||
// Compress mask and shift into single value of the form
|
||||
// me | mb<<8 | rotate<<16 | nbits<<24 where me and mb can
|
||||
// be used to regenerate the input mask.
|
||||
@@ -1589,7 +1604,7 @@ func mergePPC64AndSrdi(m, s int64) int64 {
|
||||
if rv&uint64(mask) != 0 {
|
||||
return 0
|
||||
}
|
||||
if !isPPC64WordRotateMask(mask) {
|
||||
if !isPPC64WordRotateMaskNonWrapping(mask) {
|
||||
return 0
|
||||
}
|
||||
return encodePPC64RotateMask((32-s)&31, mask, 32)
|
||||
@@ -1604,7 +1619,7 @@ func mergePPC64AndSldi(m, s int64) int64 {
|
||||
if rv&uint64(mask) != 0 {
|
||||
return 0
|
||||
}
|
||||
if !isPPC64WordRotateMask(mask) {
|
||||
if !isPPC64WordRotateMaskNonWrapping(mask) {
|
||||
return 0
|
||||
}
|
||||
return encodePPC64RotateMask(s&31, mask, 32)
|
||||
|
||||
@@ -1331,10 +1331,11 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (ADD a p:(ADDconst [c] m:(MUL _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (ADD <t> a p:(ADDconst [c] m:(MUL _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (ADDconst [c] (ADD <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||
a := v_0
|
||||
p := v_1
|
||||
@@ -1343,7 +1344,7 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MUL || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MUL || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
continue
|
||||
}
|
||||
v.reset(OpARM64ADDconst)
|
||||
@@ -1355,10 +1356,11 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (ADD a p:(ADDconst [c] m:(MULW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (ADD <t> a p:(ADDconst [c] m:(MULW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (ADDconst [c] (ADD <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||
a := v_0
|
||||
p := v_1
|
||||
@@ -1367,7 +1369,7 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MULW || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MULW || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
continue
|
||||
}
|
||||
v.reset(OpARM64ADDconst)
|
||||
@@ -1379,10 +1381,11 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (ADD a p:(ADDconst [c] m:(MNEG _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (ADD <t> a p:(ADDconst [c] m:(MNEG _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (ADDconst [c] (ADD <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||
a := v_0
|
||||
p := v_1
|
||||
@@ -1391,7 +1394,7 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MNEG || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MNEG || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
continue
|
||||
}
|
||||
v.reset(OpARM64ADDconst)
|
||||
@@ -1403,10 +1406,11 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (ADD a p:(ADDconst [c] m:(MNEGW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (ADD <t> a p:(ADDconst [c] m:(MNEGW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (ADDconst [c] (ADD <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||
a := v_0
|
||||
p := v_1
|
||||
@@ -1415,7 +1419,7 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MNEGW || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MNEGW || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
continue
|
||||
}
|
||||
v.reset(OpARM64ADDconst)
|
||||
@@ -1427,10 +1431,11 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (ADD a p:(SUBconst [c] m:(MUL _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (ADD <t> a p:(SUBconst [c] m:(MUL _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (SUBconst [c] (ADD <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||
a := v_0
|
||||
p := v_1
|
||||
@@ -1439,7 +1444,7 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MUL || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MUL || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
continue
|
||||
}
|
||||
v.reset(OpARM64SUBconst)
|
||||
@@ -1451,10 +1456,11 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (ADD a p:(SUBconst [c] m:(MULW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (ADD <t> a p:(SUBconst [c] m:(MULW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (SUBconst [c] (ADD <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||
a := v_0
|
||||
p := v_1
|
||||
@@ -1463,7 +1469,7 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MULW || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MULW || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
continue
|
||||
}
|
||||
v.reset(OpARM64SUBconst)
|
||||
@@ -1475,10 +1481,11 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (ADD a p:(SUBconst [c] m:(MNEG _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (ADD <t> a p:(SUBconst [c] m:(MNEG _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (SUBconst [c] (ADD <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||
a := v_0
|
||||
p := v_1
|
||||
@@ -1487,7 +1494,7 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MNEG || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MNEG || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
continue
|
||||
}
|
||||
v.reset(OpARM64SUBconst)
|
||||
@@ -1499,10 +1506,11 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (ADD a p:(SUBconst [c] m:(MNEGW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (ADD <t> a p:(SUBconst [c] m:(MNEGW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (SUBconst [c] (ADD <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||
a := v_0
|
||||
p := v_1
|
||||
@@ -1511,7 +1519,7 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MNEGW || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MNEGW || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
continue
|
||||
}
|
||||
v.reset(OpARM64SUBconst)
|
||||
@@ -16604,10 +16612,11 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
v.AddArg3(a, x, y)
|
||||
return true
|
||||
}
|
||||
// match: (SUB a p:(ADDconst [c] m:(MUL _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (SUB <t> a p:(ADDconst [c] m:(MUL _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (SUBconst [c] (SUB <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
a := v_0
|
||||
p := v_1
|
||||
if p.Op != OpARM64ADDconst {
|
||||
@@ -16615,7 +16624,7 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MUL || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MUL || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64SUBconst)
|
||||
@@ -16625,10 +16634,11 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (SUB a p:(ADDconst [c] m:(MULW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (SUB <t> a p:(ADDconst [c] m:(MULW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (SUBconst [c] (SUB <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
a := v_0
|
||||
p := v_1
|
||||
if p.Op != OpARM64ADDconst {
|
||||
@@ -16636,7 +16646,7 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MULW || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MULW || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64SUBconst)
|
||||
@@ -16646,10 +16656,11 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (SUB a p:(ADDconst [c] m:(MNEG _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (SUB <t> a p:(ADDconst [c] m:(MNEG _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (SUBconst [c] (SUB <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
a := v_0
|
||||
p := v_1
|
||||
if p.Op != OpARM64ADDconst {
|
||||
@@ -16657,7 +16668,7 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MNEG || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MNEG || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64SUBconst)
|
||||
@@ -16667,10 +16678,11 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (SUB a p:(ADDconst [c] m:(MNEGW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (SUB <t> a p:(ADDconst [c] m:(MNEGW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (SUBconst [c] (SUB <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
a := v_0
|
||||
p := v_1
|
||||
if p.Op != OpARM64ADDconst {
|
||||
@@ -16678,7 +16690,7 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MNEGW || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MNEGW || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64SUBconst)
|
||||
@@ -16688,10 +16700,11 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (SUB a p:(SUBconst [c] m:(MUL _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (SUB <t> a p:(SUBconst [c] m:(MUL _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (ADDconst [c] (SUB <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
a := v_0
|
||||
p := v_1
|
||||
if p.Op != OpARM64SUBconst {
|
||||
@@ -16699,7 +16712,7 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MUL || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MUL || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64ADDconst)
|
||||
@@ -16709,10 +16722,11 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (SUB a p:(SUBconst [c] m:(MULW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (SUB <t> a p:(SUBconst [c] m:(MULW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (ADDconst [c] (SUB <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
a := v_0
|
||||
p := v_1
|
||||
if p.Op != OpARM64SUBconst {
|
||||
@@ -16720,7 +16734,7 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MULW || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MULW || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64ADDconst)
|
||||
@@ -16730,10 +16744,11 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (SUB a p:(SUBconst [c] m:(MNEG _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (SUB <t> a p:(SUBconst [c] m:(MNEG _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (ADDconst [c] (SUB <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
a := v_0
|
||||
p := v_1
|
||||
if p.Op != OpARM64SUBconst {
|
||||
@@ -16741,7 +16756,7 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MNEG || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MNEG || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64ADDconst)
|
||||
@@ -16751,10 +16766,11 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (SUB a p:(SUBconst [c] m:(MNEGW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1
|
||||
// match: (SUB <t> a p:(SUBconst [c] m:(MNEGW _ _)))
|
||||
// cond: p.Uses==1 && m.Uses==1 && !t.IsPtrShaped()
|
||||
// result: (ADDconst [c] (SUB <v.Type> a m))
|
||||
for {
|
||||
t := v.Type
|
||||
a := v_0
|
||||
p := v_1
|
||||
if p.Op != OpARM64SUBconst {
|
||||
@@ -16762,7 +16778,7 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool {
|
||||
}
|
||||
c := auxIntToInt64(p.AuxInt)
|
||||
m := p.Args[0]
|
||||
if m.Op != OpARM64MNEGW || !(p.Uses == 1 && m.Uses == 1) {
|
||||
if m.Op != OpARM64MNEGW || !(p.Uses == 1 && m.Uses == 1 && !t.IsPtrShaped()) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64ADDconst)
|
||||
|
||||
@@ -4433,6 +4433,9 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool, deferExt
|
||||
callABI = s.f.ABI1
|
||||
}
|
||||
}
|
||||
if fn := n.Fun.Sym().Name; n.Fun.Sym().Pkg == ir.Pkgs.Runtime && fn == "deferrangefunc" {
|
||||
s.f.HasDeferRangeFunc = true
|
||||
}
|
||||
break
|
||||
}
|
||||
closure = s.expr(fn)
|
||||
@@ -6566,10 +6569,13 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
|
||||
// nop (which will never execute) after the call.
|
||||
Arch.Ginsnop(s.pp)
|
||||
}
|
||||
if openDeferInfo != nil {
|
||||
if openDeferInfo != nil || f.HasDeferRangeFunc {
|
||||
// When doing open-coded defers, generate a disconnected call to
|
||||
// deferreturn and a return. This will be used to during panic
|
||||
// recovery to unwind the stack and return back to the runtime.
|
||||
//
|
||||
// deferrangefunc needs to be sure that at least one of these exists;
|
||||
// if all returns are dead-code eliminated, there might not be.
|
||||
s.pp.NextLive = s.livenessMap.DeferReturn
|
||||
p := s.pp.Prog(obj.ACALL)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
|
||||
@@ -230,6 +230,9 @@ func TestIntendedInlining(t *testing.T) {
|
||||
"(*Pointer[go.shape.int]).Store",
|
||||
"(*Pointer[go.shape.int]).Swap",
|
||||
},
|
||||
"testing": {
|
||||
"(*B).Loop",
|
||||
},
|
||||
}
|
||||
|
||||
if !goexperiment.SwissMap {
|
||||
|
||||
@@ -204,7 +204,7 @@ func (check *Checker) lhsVar(lhs syntax.Expr) Type {
|
||||
// dot-imported variables.
|
||||
if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
|
||||
v = w
|
||||
v_used = v.used
|
||||
v_used = check.usedVars[v]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ func (check *Checker) lhsVar(lhs syntax.Expr) Type {
|
||||
check.expr(nil, &x, lhs)
|
||||
|
||||
if v != nil {
|
||||
v.used = v_used // restore v.used
|
||||
check.usedVars[v] = v_used // restore v.used
|
||||
}
|
||||
|
||||
if x.mode == invalid || !isValid(x.typ) {
|
||||
|
||||
@@ -687,7 +687,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *TypeName
|
||||
if pname, _ := obj.(*PkgName); pname != nil {
|
||||
assert(pname.pkg == check.pkg)
|
||||
check.recordUse(ident, pname)
|
||||
pname.used = true
|
||||
check.usedPkgNames[pname] = true
|
||||
pkg := pname.imported
|
||||
|
||||
var exp Object
|
||||
@@ -972,13 +972,13 @@ func (check *Checker) use1(e syntax.Expr, lhs bool) bool {
|
||||
// dot-imported variables.
|
||||
if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
|
||||
v = w
|
||||
v_used = v.used
|
||||
v_used = check.usedVars[v]
|
||||
}
|
||||
}
|
||||
}
|
||||
check.exprOrType(&x, n, true)
|
||||
if v != nil {
|
||||
v.used = v_used // restore v.used
|
||||
check.usedVars[v] = v_used // restore v.used
|
||||
}
|
||||
case *syntax.ListExpr:
|
||||
return check.useN(n.ElemList, lhs)
|
||||
|
||||
@@ -162,6 +162,8 @@ type Checker struct {
|
||||
dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through
|
||||
brokenAliases map[*TypeName]bool // set of aliases with broken (not yet determined) types
|
||||
unionTypeSets map[*Union]*_TypeSet // computed type sets for union types
|
||||
usedVars map[*Var]bool // set of used variables
|
||||
usedPkgNames map[*PkgName]bool // set of used package names
|
||||
mono monoGraph // graph for detecting non-monomorphizable instantiation loops
|
||||
|
||||
firstErr error // first error encountered
|
||||
@@ -285,12 +287,14 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
|
||||
// (previously, pkg.goVersion was mutated here: go.dev/issue/61212)
|
||||
|
||||
return &Checker{
|
||||
conf: conf,
|
||||
ctxt: conf.Context,
|
||||
pkg: pkg,
|
||||
Info: info,
|
||||
objMap: make(map[Object]*declInfo),
|
||||
impMap: make(map[importKey]*Package),
|
||||
conf: conf,
|
||||
ctxt: conf.Context,
|
||||
pkg: pkg,
|
||||
Info: info,
|
||||
objMap: make(map[Object]*declInfo),
|
||||
impMap: make(map[importKey]*Package),
|
||||
usedVars: make(map[*Var]bool),
|
||||
usedPkgNames: make(map[*PkgName]bool),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,6 +302,8 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
|
||||
// The provided files must all belong to the same package.
|
||||
func (check *Checker) initFiles(files []*syntax.File) {
|
||||
// start with a clean slate (check.Files may be called multiple times)
|
||||
// TODO(gri): what determines which fields are zeroed out here, vs at the end
|
||||
// of checkFiles?
|
||||
check.files = nil
|
||||
check.imports = nil
|
||||
check.dotImportMap = nil
|
||||
@@ -309,6 +315,13 @@ func (check *Checker) initFiles(files []*syntax.File) {
|
||||
check.objPath = nil
|
||||
check.cleaners = nil
|
||||
|
||||
// We must initialize usedVars and usedPkgNames both here and in NewChecker,
|
||||
// because initFiles is not called in the CheckExpr or Eval codepaths, yet we
|
||||
// want to free this memory at the end of Files ('used' predicates are
|
||||
// only needed in the context of a given file).
|
||||
check.usedVars = make(map[*Var]bool)
|
||||
check.usedPkgNames = make(map[*PkgName]bool)
|
||||
|
||||
// determine package name and collect valid files
|
||||
pkg := check.pkg
|
||||
for _, file := range files {
|
||||
@@ -482,8 +495,11 @@ func (check *Checker) checkFiles(files []*syntax.File) {
|
||||
check.seenPkgMap = nil
|
||||
check.brokenAliases = nil
|
||||
check.unionTypeSets = nil
|
||||
check.usedVars = nil
|
||||
check.usedPkgNames = nil
|
||||
check.ctxt = nil
|
||||
|
||||
// TODO(gri): shouldn't the cleanup above occur after the bailout?
|
||||
// TODO(gri) There's more memory we should release at this point.
|
||||
}
|
||||
|
||||
|
||||
@@ -242,13 +242,12 @@ func (a *object) cmp(b *object) int {
|
||||
type PkgName struct {
|
||||
object
|
||||
imported *Package
|
||||
used bool // set if the package was used
|
||||
}
|
||||
|
||||
// NewPkgName returns a new PkgName object representing an imported package.
|
||||
// The remaining arguments set the attributes found with all Objects.
|
||||
func NewPkgName(pos syntax.Pos, pkg *Package, name string, imported *Package) *PkgName {
|
||||
return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, nopos}, imported, false}
|
||||
return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, nopos}, imported}
|
||||
}
|
||||
|
||||
// Imported returns the package that was imported.
|
||||
@@ -331,10 +330,10 @@ func (obj *TypeName) IsAlias() bool {
|
||||
// A Variable represents a declared variable (including function parameters and results, and struct fields).
|
||||
type Var struct {
|
||||
object
|
||||
origin *Var // if non-nil, the Var from which this one was instantiated
|
||||
embedded bool // if set, the variable is an embedded struct field, and name is the type name
|
||||
isField bool // var is struct field
|
||||
used bool // set if the variable was used
|
||||
origin *Var // if non-nil, the Var from which this one was instantiated
|
||||
isParam bool // var is a param, for backport of 'used' check to go1.24 (go.dev/issue/72826)
|
||||
}
|
||||
|
||||
// NewVar returns a new variable.
|
||||
@@ -345,7 +344,7 @@ func NewVar(pos syntax.Pos, pkg *Package, name string, typ Type) *Var {
|
||||
|
||||
// NewParam returns a new variable representing a function parameter.
|
||||
func NewParam(pos syntax.Pos, pkg *Package, name string, typ Type) *Var {
|
||||
return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, used: true} // parameters are always 'used'
|
||||
return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, isParam: true}
|
||||
}
|
||||
|
||||
// NewField returns a new variable representing a struct field.
|
||||
|
||||
@@ -295,7 +295,7 @@ func (check *Checker) collectObjects() {
|
||||
|
||||
if imp.fake {
|
||||
// match 1.17 cmd/compile (not prescribed by spec)
|
||||
pkgName.used = true
|
||||
check.usedPkgNames[pkgName] = true
|
||||
}
|
||||
|
||||
// add import to file scope
|
||||
@@ -715,7 +715,7 @@ func (check *Checker) unusedImports() {
|
||||
// (initialization), use the blank identifier as explicit package name."
|
||||
|
||||
for _, obj := range check.imports {
|
||||
if !obj.used && obj.name != "_" {
|
||||
if obj.name != "_" && !check.usedPkgNames[obj] {
|
||||
check.errorUnusedPkg(obj)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestSizeof(t *testing.T) {
|
||||
{term{}, 12, 24},
|
||||
|
||||
// Objects
|
||||
{PkgName{}, 64, 104},
|
||||
{PkgName{}, 60, 96},
|
||||
{Const{}, 64, 104},
|
||||
{TypeName{}, 56, 88},
|
||||
{Var{}, 64, 104},
|
||||
|
||||
@@ -58,7 +58,7 @@ func (check *Checker) usage(scope *Scope) {
|
||||
var unused []*Var
|
||||
for name, elem := range scope.elems {
|
||||
elem = resolve(name, elem)
|
||||
if v, _ := elem.(*Var); v != nil && !v.used {
|
||||
if v, _ := elem.(*Var); v != nil && !v.isParam && !check.usedVars[v] {
|
||||
unused = append(unused, v)
|
||||
}
|
||||
}
|
||||
@@ -824,10 +824,10 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu
|
||||
if lhs != nil {
|
||||
var used bool
|
||||
for _, v := range lhsVars {
|
||||
if v.used {
|
||||
if check.usedVars[v] {
|
||||
used = true
|
||||
}
|
||||
v.used = true // avoid usage error when checking entire function
|
||||
check.usedVars[v] = true // avoid usage error when checking entire function
|
||||
}
|
||||
if !used {
|
||||
check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Value)
|
||||
@@ -934,7 +934,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
|
||||
if typ == nil || typ == Typ[Invalid] {
|
||||
// typ == Typ[Invalid] can happen if allowVersion fails.
|
||||
obj.typ = Typ[Invalid]
|
||||
obj.used = true // don't complain about unused variable
|
||||
check.usedVars[obj] = true // don't complain about unused variable
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType
|
||||
// avoid "declared but not used" errors
|
||||
// (don't use Checker.use - we don't want to evaluate too much)
|
||||
if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ {
|
||||
v.used = true
|
||||
check.usedVars[v] = true
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType
|
||||
// (This code is only needed for dot-imports. Without them,
|
||||
// we only have to mark variables, see *Var case below).
|
||||
if pkgName := check.dotImportMap[dotImportKey{scope, obj.Name()}]; pkgName != nil {
|
||||
pkgName.used = true
|
||||
check.usedPkgNames[pkgName] = true
|
||||
}
|
||||
|
||||
switch obj := obj.(type) {
|
||||
@@ -120,7 +120,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType
|
||||
// from other packages to avoid potential race conditions with
|
||||
// dot-imported variables.
|
||||
if obj.pkg == check.pkg {
|
||||
obj.used = true
|
||||
check.usedVars[obj] = true
|
||||
}
|
||||
check.addDeclDep(obj)
|
||||
if !isValid(typ) {
|
||||
|
||||
@@ -128,7 +128,8 @@ func runGoAuth(client *http.Client, res *http.Response, url string) {
|
||||
// If no GOAUTH command provided a credential for the given url
|
||||
// and an error occurred, log the error.
|
||||
if cfg.BuildX && url != "" {
|
||||
if ok := loadCredential(&http.Request{}, url); !ok && len(cmdErrs) > 0 {
|
||||
req := &http.Request{Header: make(http.Header)}
|
||||
if ok := loadCredential(req, url); !ok && len(cmdErrs) > 0 {
|
||||
log.Printf("GOAUTH encountered errors for %s:", url)
|
||||
for _, err := range cmdErrs {
|
||||
log.Printf(" %v", err)
|
||||
|
||||
@@ -114,7 +114,11 @@ func Init() {
|
||||
fsys.Bind(Dir(), filepath.Join(cfg.GOROOT, "src/crypto/internal/fips140"))
|
||||
}
|
||||
|
||||
if cfg.Experiment.BoringCrypto && Enabled() {
|
||||
// ExperimentErr != nil if GOEXPERIMENT failed to parse. Typically
|
||||
// cmd/go main will exit in this case, but it is allowed during
|
||||
// toolchain selection, as the GOEXPERIMENT may be valid for the
|
||||
// selected toolchain version.
|
||||
if cfg.ExperimentErr == nil && cfg.Experiment.BoringCrypto && Enabled() {
|
||||
base.Fatalf("go: cannot use GOFIPS140 with GOEXPERIMENT=boringcrypto")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2474,7 +2474,6 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
|
||||
var repoDir string
|
||||
var vcsCmd *vcs.Cmd
|
||||
var err error
|
||||
const allowNesting = true
|
||||
|
||||
wantVCS := false
|
||||
switch cfg.BuildBuildvcs {
|
||||
@@ -2494,7 +2493,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
|
||||
// (so the bootstrap toolchain packages don't even appear to be in GOROOT).
|
||||
goto omitVCS
|
||||
}
|
||||
repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting)
|
||||
repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "")
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
setVCSError(err)
|
||||
return
|
||||
@@ -2517,10 +2516,11 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
|
||||
}
|
||||
if repoDir != "" && vcsCmd.Status != nil {
|
||||
// Check that the current directory, package, and module are in the same
|
||||
// repository. vcs.FromDir allows nested Git repositories, but nesting
|
||||
// is not allowed for other VCS tools. The current directory may be outside
|
||||
// p.Module.Dir when a workspace is used.
|
||||
pkgRepoDir, _, err := vcs.FromDir(p.Dir, "", allowNesting)
|
||||
// repository. vcs.FromDir disallows nested VCS and multiple VCS in the
|
||||
// same repository, unless the GODEBUG allowmultiplevcs is set. The
|
||||
// current directory may be outside p.Module.Dir when a workspace is
|
||||
// used.
|
||||
pkgRepoDir, _, err := vcs.FromDir(p.Dir, "")
|
||||
if err != nil {
|
||||
setVCSError(err)
|
||||
return
|
||||
@@ -2532,7 +2532,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
|
||||
}
|
||||
goto omitVCS
|
||||
}
|
||||
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting)
|
||||
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "")
|
||||
if err != nil {
|
||||
setVCSError(err)
|
||||
return
|
||||
@@ -2571,7 +2571,12 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
|
||||
vers := revInfo.Version
|
||||
if vers != "" {
|
||||
if st.Uncommitted {
|
||||
vers += "+dirty"
|
||||
// SemVer build metadata is dot-separated https://semver.org/#spec-item-10
|
||||
if strings.HasSuffix(vers, "+incompatible") {
|
||||
vers += ".dirty"
|
||||
} else {
|
||||
vers += "+dirty"
|
||||
}
|
||||
}
|
||||
info.Main.Version = vers
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ func LookupLocal(ctx context.Context, path string) Repo {
|
||||
|
||||
return lookupLocalCache.Do(path, func() Repo {
|
||||
return newCachingRepo(ctx, path, func(ctx context.Context) (Repo, error) {
|
||||
repoDir, vcsCmd, err := vcs.FromDir(path, "", true)
|
||||
repoDir, vcsCmd, err := vcs.FromDir(path, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"internal/godebug"
|
||||
"internal/lazyregexp"
|
||||
"internal/singleflight"
|
||||
"io/fs"
|
||||
@@ -839,11 +840,13 @@ type vcsPath struct {
|
||||
schemelessRepo bool // if true, the repo pattern lacks a scheme
|
||||
}
|
||||
|
||||
var allowmultiplevcs = godebug.New("allowmultiplevcs")
|
||||
|
||||
// FromDir inspects dir and its parents to determine the
|
||||
// version control system and code repository to use.
|
||||
// If no repository is found, FromDir returns an error
|
||||
// equivalent to os.ErrNotExist.
|
||||
func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cmd, err error) {
|
||||
func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) {
|
||||
// Clean and double-check that dir is in (a subdirectory of) srcRoot.
|
||||
dir = filepath.Clean(dir)
|
||||
if srcRoot != "" {
|
||||
@@ -857,21 +860,28 @@ func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cm
|
||||
for len(dir) > len(srcRoot) {
|
||||
for _, vcs := range vcsList {
|
||||
if isVCSRoot(dir, vcs.RootNames) {
|
||||
// Record first VCS we find.
|
||||
// If allowNesting is false (as it is in GOPATH), keep looking for
|
||||
// repositories in parent directories and report an error if one is
|
||||
// found to mitigate VCS injection attacks.
|
||||
if vcsCmd == nil {
|
||||
// Record first VCS we find.
|
||||
vcsCmd = vcs
|
||||
repoDir = dir
|
||||
if allowNesting {
|
||||
if allowmultiplevcs.Value() == "1" {
|
||||
allowmultiplevcs.IncNonDefault()
|
||||
return repoDir, vcsCmd, nil
|
||||
}
|
||||
// If allowmultiplevcs is not set, keep looking for
|
||||
// repositories in current and parent directories and report
|
||||
// an error if one is found to mitigate VCS injection
|
||||
// attacks.
|
||||
continue
|
||||
}
|
||||
// Otherwise, we have one VCS inside a different VCS.
|
||||
return "", nil, fmt.Errorf("directory %q uses %s, but parent %q uses %s",
|
||||
repoDir, vcsCmd.Cmd, dir, vcs.Cmd)
|
||||
if vcsCmd == vcsGit && vcs == vcsGit {
|
||||
// Nested Git is allowed, as this is how things like
|
||||
// submodules work. Git explicitly protects against
|
||||
// injection against itself.
|
||||
continue
|
||||
}
|
||||
return "", nil, fmt.Errorf("multiple VCS detected: %s in %q, and %s in %q",
|
||||
vcsCmd.Cmd, repoDir, vcs.Cmd, dir)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ func TestFromDir(t *testing.T) {
|
||||
}
|
||||
|
||||
wantRepoDir := filepath.Dir(dir)
|
||||
gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false)
|
||||
gotRepoDir, gotVCS, err := FromDir(dir, tempDir)
|
||||
if err != nil {
|
||||
t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err)
|
||||
continue
|
||||
|
||||
@@ -227,21 +227,6 @@ var validLinkerFlags = []*lazyregexp.Regexp{
|
||||
re(`\./.*\.(a|o|obj|dll|dylib|so|tbd)`),
|
||||
}
|
||||
|
||||
var validLinkerFlagsOnDarwin = []*lazyregexp.Regexp{
|
||||
// The GNU linker interprets `@file` as "read command-line options from
|
||||
// file". Thus, we forbid values starting with `@` on linker flags.
|
||||
// However, this causes a problem when targeting Darwin.
|
||||
// `@executable_path`, `@loader_path`, and `@rpath` are special values
|
||||
// used in Mach-O to change the library search path and can be used in
|
||||
// conjunction with the `-install_name` and `-rpath` linker flags.
|
||||
// Since the GNU linker does not support Mach-O, targeting Darwin
|
||||
// implies not using the GNU linker. Therefore, we allow @ in the linker
|
||||
// flags if and only if cfg.Goos == "darwin" || cfg.Goos == "ios".
|
||||
re(`-Wl,-dylib_install_name,@rpath(/[^,]*)?`),
|
||||
re(`-Wl,-install_name,@rpath(/[^,]*)?`),
|
||||
re(`-Wl,-rpath,@(executable_path|loader_path)(/[^,]*)?`),
|
||||
}
|
||||
|
||||
var validLinkerFlagsWithNextArg = []string{
|
||||
"-arch",
|
||||
"-F",
|
||||
@@ -264,13 +249,8 @@ func checkCompilerFlags(name, source string, list []string) error {
|
||||
}
|
||||
|
||||
func checkLinkerFlags(name, source string, list []string) error {
|
||||
validLinkerFlagsForPlatform := validLinkerFlags
|
||||
if cfg.Goos == "darwin" || cfg.Goos == "ios" {
|
||||
validLinkerFlagsForPlatform = append(validLinkerFlags, validLinkerFlagsOnDarwin...)
|
||||
}
|
||||
|
||||
checkOverrides := true
|
||||
return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlagsForPlatform, validLinkerFlagsWithNextArg, checkOverrides)
|
||||
return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides)
|
||||
}
|
||||
|
||||
// checkCompilerFlagsForInternalLink returns an error if 'list'
|
||||
|
||||
@@ -8,8 +8,6 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"cmd/go/internal/cfg"
|
||||
)
|
||||
|
||||
var goodCompilerFlags = [][]string{
|
||||
@@ -247,8 +245,6 @@ var badLinkerFlags = [][]string{
|
||||
{"-Wl,--hash-style=foo"},
|
||||
{"-x", "--c"},
|
||||
{"-x", "@obj"},
|
||||
{"-Wl,-dylib_install_name,@foo"},
|
||||
{"-Wl,-install_name,@foo"},
|
||||
{"-Wl,-rpath,@foo"},
|
||||
{"-Wl,-R,foo,bar"},
|
||||
{"-Wl,-R,@foo"},
|
||||
@@ -265,21 +261,6 @@ var badLinkerFlags = [][]string{
|
||||
{"./-Wl,--push-state,-R.c"},
|
||||
}
|
||||
|
||||
var goodLinkerFlagsOnDarwin = [][]string{
|
||||
{"-Wl,-dylib_install_name,@rpath"},
|
||||
{"-Wl,-dylib_install_name,@rpath/"},
|
||||
{"-Wl,-dylib_install_name,@rpath/foo"},
|
||||
{"-Wl,-install_name,@rpath"},
|
||||
{"-Wl,-install_name,@rpath/"},
|
||||
{"-Wl,-install_name,@rpath/foo"},
|
||||
{"-Wl,-rpath,@executable_path"},
|
||||
{"-Wl,-rpath,@executable_path/"},
|
||||
{"-Wl,-rpath,@executable_path/foo"},
|
||||
{"-Wl,-rpath,@loader_path"},
|
||||
{"-Wl,-rpath,@loader_path/"},
|
||||
{"-Wl,-rpath,@loader_path/foo"},
|
||||
}
|
||||
|
||||
func TestCheckLinkerFlags(t *testing.T) {
|
||||
for _, f := range goodLinkerFlags {
|
||||
if err := checkLinkerFlags("test", "test", f); err != nil {
|
||||
@@ -291,31 +272,6 @@ func TestCheckLinkerFlags(t *testing.T) {
|
||||
t.Errorf("missing error for %q", f)
|
||||
}
|
||||
}
|
||||
|
||||
goos := cfg.Goos
|
||||
|
||||
cfg.Goos = "darwin"
|
||||
for _, f := range goodLinkerFlagsOnDarwin {
|
||||
if err := checkLinkerFlags("test", "test", f); err != nil {
|
||||
t.Errorf("unexpected error for %q: %v", f, err)
|
||||
}
|
||||
}
|
||||
|
||||
cfg.Goos = "ios"
|
||||
for _, f := range goodLinkerFlagsOnDarwin {
|
||||
if err := checkLinkerFlags("test", "test", f); err != nil {
|
||||
t.Errorf("unexpected error for %q: %v", f, err)
|
||||
}
|
||||
}
|
||||
|
||||
cfg.Goos = "linux"
|
||||
for _, f := range goodLinkerFlagsOnDarwin {
|
||||
if err := checkLinkerFlags("test", "test", f); err == nil {
|
||||
t.Errorf("missing error for %q", f)
|
||||
}
|
||||
}
|
||||
|
||||
cfg.Goos = goos
|
||||
}
|
||||
|
||||
func TestCheckFlagAllowDisallow(t *testing.T) {
|
||||
|
||||
@@ -108,6 +108,19 @@ go version -m example$GOEXE
|
||||
stdout '\s+mod\s+example\s+v1.0.3-0.20220719150703-2e239bf29c13\s+'
|
||||
rm example$GOEXE
|
||||
|
||||
# Create +incompatible module
|
||||
exec git checkout v1.0.4
|
||||
exec git rm go.mod
|
||||
exec git commit -m 'commit 6'
|
||||
exec git tag v2.0.0
|
||||
exec git checkout HEAD^ go.mod
|
||||
# And make the tree +dirty
|
||||
mv README4 README5
|
||||
go build
|
||||
go version -m example$GOEXE
|
||||
stdout '\s+mod\s+example\s+v2.0.0\+incompatible.dirty\s+'
|
||||
rm example$GOEXE
|
||||
|
||||
-- $WORK/repo/go.mod --
|
||||
module example
|
||||
|
||||
|
||||
2
src/cmd/go/testdata/script/goauth_git.txt
vendored
2
src/cmd/go/testdata/script/goauth_git.txt
vendored
@@ -49,6 +49,8 @@ go get vcs-test.golang.org/auth/or401
|
||||
go mod tidy
|
||||
go list all
|
||||
stdout vcs-test.golang.org/auth/or404
|
||||
# With cached credentials, re-downloading in debug mode should succeed.
|
||||
go get -x vcs-test.golang.org/auth/or401
|
||||
|
||||
# Clearing GOAUTH credentials should result in failures.
|
||||
env GOAUTH='off'
|
||||
|
||||
54
src/cmd/go/testdata/script/test_multivcs.txt
vendored
Normal file
54
src/cmd/go/testdata/script/test_multivcs.txt
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
# To avoid VCS injection attacks, we should not accept multiple different VCS metadata
|
||||
# folders within a single module (either in the same directory, or nested in different
|
||||
# directories.)
|
||||
#
|
||||
# This behavior should be disabled by setting the allowmultiplevcs GODEBUG.
|
||||
|
||||
[short] skip
|
||||
[!git] skip
|
||||
|
||||
cd samedir
|
||||
|
||||
exec git init .
|
||||
|
||||
# Without explicitly requesting buildvcs, the go command should silently continue
|
||||
# without determining the correct VCS.
|
||||
go test -c -o $devnull .
|
||||
|
||||
# If buildvcs is explicitly requested, we expect the go command to fail
|
||||
! go test -buildvcs -c -o $devnull .
|
||||
stderr '^error obtaining VCS status: multiple VCS detected:'
|
||||
|
||||
env GODEBUG=allowmultiplevcs=1
|
||||
go test -buildvcs -c -o $devnull .
|
||||
|
||||
env GODEBUG=
|
||||
cd ../nested
|
||||
exec git init .
|
||||
# cd a
|
||||
go test -c -o $devnull ./a
|
||||
! go test -buildvcs -c -o $devnull ./a
|
||||
stderr '^error obtaining VCS status: multiple VCS detected:'
|
||||
# allowmultiplevcs doesn't disable the check that the current directory, package, and
|
||||
# module are in the same repository.
|
||||
env GODEBUG=allowmultiplevcs=1
|
||||
! go test -buildvcs -c -o $devnull ./a
|
||||
stderr '^error obtaining VCS status: main package is in repository'
|
||||
|
||||
-- samedir/go.mod --
|
||||
module example
|
||||
|
||||
go 1.18
|
||||
-- samedir/example.go --
|
||||
package main
|
||||
-- samedir/.bzr/test --
|
||||
hello
|
||||
|
||||
-- nested/go.mod --
|
||||
module example
|
||||
|
||||
go 1.18
|
||||
-- nested/a/example.go --
|
||||
package main
|
||||
-- nested/a/.bzr/test --
|
||||
hello
|
||||
@@ -9,25 +9,35 @@ cd root
|
||||
go mod init example.com/root
|
||||
exec git init
|
||||
|
||||
# Nesting repositories in parent directories are ignored, as the current
|
||||
# directory main package, and containing main module are in the same repository.
|
||||
# This is an error in GOPATH mode (to prevent VCS injection), but for modules,
|
||||
# we assume users have control over repositories they've checked out.
|
||||
|
||||
# Nesting repositories in parent directories are an error, to prevent VCS injection.
|
||||
# This can be disabled with the allowmultiplevcs GODEBUG.
|
||||
mkdir hgsub
|
||||
cd hgsub
|
||||
exec hg init
|
||||
cp ../../main.go main.go
|
||||
! go build
|
||||
stderr '^error obtaining VCS status: multiple VCS detected: hg in ".*hgsub", and git in ".*root"$'
|
||||
stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
|
||||
env GODEBUG=allowmultiplevcs=1
|
||||
! go build
|
||||
stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*hgsub"$'
|
||||
stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
|
||||
go build -buildvcs=false
|
||||
env GODEBUG=
|
||||
go mod init example.com/root/hgsub
|
||||
! go build
|
||||
stderr '^error obtaining VCS status: multiple VCS detected: hg in ".*hgsub", and git in ".*root"$'
|
||||
stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
|
||||
env GODEBUG=allowmultiplevcs=1
|
||||
go build
|
||||
env GODEBUG=
|
||||
cd ..
|
||||
|
||||
# It's an error to build a package from a nested Git repository if the package
|
||||
# is in a separate repository from the current directory or from the module
|
||||
# root directory.
|
||||
# root directory. Otherwise nested Git repositories are allowed, as this is
|
||||
# how Git implements submodules (and protects against Git based VCS injection.)
|
||||
mkdir gitsub
|
||||
cd gitsub
|
||||
exec git init
|
||||
|
||||
@@ -1006,9 +1006,10 @@ func genWasmExportWrapper(s *obj.LSym, appendp func(p *obj.Prog, as obj.As, args
|
||||
// In the unwinding case, we call wasm_pc_f_loop_export to handle stack switch and rewinding,
|
||||
// until a normal return (non-unwinding) back to this function.
|
||||
p = appendp(p, AIf)
|
||||
p = appendp(p, AI32Const, retAddr)
|
||||
p = appendp(p, AI32Const, constAddr(16))
|
||||
p = appendp(p, AI32ShrU)
|
||||
p = appendp(p, AI64Const, retAddr)
|
||||
p = appendp(p, AI64Const, constAddr(16))
|
||||
p = appendp(p, AI64ShrU)
|
||||
p = appendp(p, AI32WrapI64)
|
||||
p = appendp(p, ACall, obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: wasm_pc_f_loop_export})
|
||||
p = appendp(p, AEnd)
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ type PkgSpecial struct {
|
||||
}
|
||||
|
||||
var runtimePkgs = []string{
|
||||
// TODO(panjf2000): consider syncing the list inside the
|
||||
// isAsyncSafePoint in preempt.go based on this list?
|
||||
|
||||
"runtime",
|
||||
|
||||
"internal/runtime/atomic",
|
||||
|
||||
@@ -253,6 +253,12 @@ type Loader struct {
|
||||
|
||||
WasmExports []Sym
|
||||
|
||||
// sizeFixups records symbols that we need to fix up the size
|
||||
// after loading. It is very rarely needed, only for a DATA symbol
|
||||
// and a BSS symbol with the same name, and the BSS symbol has
|
||||
// larger size.
|
||||
sizeFixups []symAndSize
|
||||
|
||||
flags uint32
|
||||
|
||||
strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled
|
||||
@@ -432,16 +438,16 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
|
||||
return i
|
||||
}
|
||||
// symbol already exists
|
||||
// Fix for issue #47185 -- given two dupok or BSS symbols with
|
||||
// different sizes, favor symbol with larger size. See also
|
||||
// issue #46653 and #72032.
|
||||
oldsz := l.SymSize(oldi)
|
||||
sz := int64(r.Sym(li).Siz())
|
||||
if osym.Dupok() {
|
||||
if l.flags&FlagStrictDups != 0 {
|
||||
l.checkdup(name, r, li, oldi)
|
||||
}
|
||||
// Fix for issue #47185 -- given two dupok symbols with
|
||||
// different sizes, favor symbol with larger size. See
|
||||
// also issue #46653.
|
||||
szdup := l.SymSize(oldi)
|
||||
sz := int64(r.Sym(li).Siz())
|
||||
if szdup < sz {
|
||||
if oldsz < sz {
|
||||
// new symbol overwrites old symbol.
|
||||
l.objSyms[oldi] = objSym{r.objidx, li}
|
||||
}
|
||||
@@ -452,20 +458,65 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
|
||||
if oldsym.Dupok() {
|
||||
return oldi
|
||||
}
|
||||
overwrite := r.DataSize(li) != 0
|
||||
if overwrite {
|
||||
// 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.
|
||||
//
|
||||
// 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
|
||||
// -------------------------------------------------------
|
||||
// TEXT BSS new wins
|
||||
// DATA DATA ERROR
|
||||
// DATA lg/eq BSS sm/eq new wins
|
||||
// DATA small BSS large merge: new with larger size
|
||||
// BSS large DATA small merge: old with larger size
|
||||
// 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())]
|
||||
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,
|
||||
newIsBSS && oldIsBSS && sz > oldsz:
|
||||
// new symbol overwrites old symbol.
|
||||
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
|
||||
if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) {
|
||||
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)
|
||||
if oldsz > sz {
|
||||
// If the BSS symbol has a larger size, expand the data
|
||||
// symbol's size so access from the BSS side cannot overrun.
|
||||
// It is hard to modify the symbol size until all Go objects
|
||||
// (potentially read-only) are loaded, so we record it in
|
||||
// a fixup table and apply them later. This is very rare.
|
||||
// One case is a global variable with a Go declaration and an
|
||||
// assembly definition, which typically have the same size,
|
||||
// but in ASAN mode the Go declaration has a larger size due
|
||||
// to the inserted red zone.
|
||||
l.sizeFixups = append(l.sizeFixups, symAndSize{oldi, uint32(oldsz)})
|
||||
}
|
||||
case newIsBSS:
|
||||
// old win, just ignore the new symbol.
|
||||
if sz > oldsz {
|
||||
// See the comment above for sizeFixups.
|
||||
l.sizeFixups = append(l.sizeFixups, symAndSize{oldi, uint32(sz)})
|
||||
}
|
||||
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
|
||||
}
|
||||
@@ -2255,6 +2306,10 @@ func (l *Loader) LoadSyms(arch *sys.Arch) {
|
||||
st.preloadSyms(r, hashedDef)
|
||||
st.preloadSyms(r, nonPkgDef)
|
||||
}
|
||||
for _, sf := range l.sizeFixups {
|
||||
pp := l.cloneToExternal(sf.sym)
|
||||
pp.size = int64(sf.size)
|
||||
}
|
||||
for _, vr := range st.linknameVarRefs {
|
||||
l.checkLinkname(vr.pkg, vr.name, vr.sym)
|
||||
}
|
||||
@@ -2460,7 +2515,7 @@ func topLevelSym(sname string, skind sym.SymKind) bool {
|
||||
// a symbol originally discovered as part of an object file, it's
|
||||
// easier to do this if we make the updates to an external symbol
|
||||
// payload.
|
||||
func (l *Loader) cloneToExternal(symIdx Sym) {
|
||||
func (l *Loader) cloneToExternal(symIdx Sym) *extSymPayload {
|
||||
if l.IsExternal(symIdx) {
|
||||
panic("sym is already external, no need for clone")
|
||||
}
|
||||
@@ -2512,6 +2567,8 @@ func (l *Loader) cloneToExternal(symIdx Sym) {
|
||||
// Some attributes were encoded in the object file. Copy them over.
|
||||
l.SetAttrDuplicateOK(symIdx, r.Sym(li).Dupok())
|
||||
l.SetAttrShared(symIdx, r.Shared())
|
||||
|
||||
return pp
|
||||
}
|
||||
|
||||
// Copy the payload of symbol src to dst. Both src and dst must be external
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"testing"
|
||||
|
||||
imacho "cmd/internal/macho"
|
||||
"cmd/internal/objfile"
|
||||
"cmd/internal/sys"
|
||||
)
|
||||
|
||||
@@ -1511,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},
|
||||
@@ -1528,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()
|
||||
@@ -1541,3 +1545,53 @@ func TestCheckLinkname(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinknameBSS(t *testing.T) {
|
||||
// Test that the linker chooses the right one as the definition
|
||||
// for linknamed variables. See issue #72032.
|
||||
testenv.MustHaveGoBuild(t)
|
||||
t.Parallel()
|
||||
|
||||
tmpdir := t.TempDir()
|
||||
|
||||
src := filepath.Join("testdata", "linkname", "sched.go")
|
||||
exe := filepath.Join(tmpdir, "sched.exe")
|
||||
cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", exe, src)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("build failed unexpectedly: %v:\n%s", err, out)
|
||||
}
|
||||
|
||||
// Check the symbol size.
|
||||
f, err := objfile.Open(exe)
|
||||
if err != nil {
|
||||
t.Fatalf("fail to open executable: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
syms, err := f.Symbols()
|
||||
if err != nil {
|
||||
t.Fatalf("fail to get symbols: %v", err)
|
||||
}
|
||||
found := false
|
||||
for _, s := range syms {
|
||||
if s.Name == "runtime.sched" || s.Name == "_runtime.sched" {
|
||||
found = true
|
||||
if s.Size < 100 {
|
||||
// As of Go 1.25 (Mar 2025), runtime.sched has 6848 bytes on
|
||||
// darwin/arm64. It should always be larger than 100 bytes on
|
||||
// all platforms.
|
||||
t.Errorf("runtime.sched symbol size too small: want > 100, got %d", s.Size)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("runtime.sched symbol not found")
|
||||
}
|
||||
|
||||
// Executable should run.
|
||||
cmd = testenv.Command(t, exe)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Errorf("executable failed to run: %v\n%s", err, out)
|
||||
}
|
||||
}
|
||||
|
||||
19
src/cmd/link/testdata/linkname/sched.go
vendored
Normal file
19
src/cmd/link/testdata/linkname/sched.go
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2025 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 _ "unsafe"
|
||||
|
||||
type schedt struct{}
|
||||
|
||||
//go:linkname sched runtime.sched
|
||||
var sched schedt
|
||||
|
||||
func main() {
|
||||
select {
|
||||
default:
|
||||
println("hello")
|
||||
}
|
||||
}
|
||||
6
src/cmd/link/testdata/linkname/textvar/asm.s
vendored
Normal file
6
src/cmd/link/testdata/linkname/textvar/asm.s
vendored
Normal 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
|
||||
17
src/cmd/link/testdata/linkname/textvar/main.go
vendored
Normal file
17
src/cmd/link/testdata/linkname/textvar/main.go
vendored
Normal 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
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"internal/godebug"
|
||||
)
|
||||
|
||||
var fips140GODEBUG = godebug.New("#fips140")
|
||||
var fips140GODEBUG = godebug.New("fips140")
|
||||
|
||||
// Enabled reports whether the cryptography libraries are operating in FIPS
|
||||
// 140-3 mode.
|
||||
|
||||
@@ -100,7 +100,7 @@ func init() {
|
||||
clear(nbuf[:])
|
||||
h.Reset()
|
||||
|
||||
if godebug.Value("#fips140") == "debug" {
|
||||
if godebug.Value("fips140") == "debug" {
|
||||
println("fips140: verified code+data")
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
// Enabled reports whether FIPS 140-only mode is enabled, in which non-approved
|
||||
// cryptography returns an error or panics.
|
||||
var Enabled = godebug.New("#fips140").Value() == "only"
|
||||
var Enabled = godebug.New("fips140").Value() == "only"
|
||||
|
||||
func ApprovedHash(h hash.Hash) bool {
|
||||
switch h.(type) {
|
||||
|
||||
@@ -26,7 +26,7 @@ func TestFIPSCheckVerify(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
if godebug.New("#fips140").Value() == "on" {
|
||||
if godebug.New("fips140").Value() == "on" {
|
||||
t.Fatalf("GODEBUG=fips140=on but verification did not run")
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,8 @@ var defaultCipherSuitesTLS13NoAES = []uint16{
|
||||
}
|
||||
|
||||
// The FIPS-only policies below match BoringSSL's
|
||||
// ssl_compliance_policy_fips_202205, which is based on NIST SP 800-52r2.
|
||||
// ssl_compliance_policy_fips_202205, which is based on NIST SP 800-52r2, with
|
||||
// minor changes per https://go.dev/issue/71757.
|
||||
// https://cs.opensource.google/boringssl/boringssl/+/master:ssl/ssl_lib.cc;l=3289;drc=ea7a88fa
|
||||
|
||||
var defaultSupportedVersionsFIPS = []uint16{
|
||||
@@ -102,7 +103,7 @@ var defaultSupportedVersionsFIPS = []uint16{
|
||||
|
||||
// defaultCurvePreferencesFIPS are the FIPS-allowed curves,
|
||||
// in preference order (most preferable first).
|
||||
var defaultCurvePreferencesFIPS = []CurveID{CurveP256, CurveP384}
|
||||
var defaultCurvePreferencesFIPS = []CurveID{CurveP256, CurveP384, CurveP521}
|
||||
|
||||
// defaultSupportedSignatureAlgorithmsFIPS currently are a subset of
|
||||
// defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1.
|
||||
@@ -115,6 +116,7 @@ var defaultSupportedSignatureAlgorithmsFIPS = []SignatureScheme{
|
||||
PKCS1WithSHA384,
|
||||
ECDSAWithP384AndSHA384,
|
||||
PKCS1WithSHA512,
|
||||
ECDSAWithP521AndSHA512,
|
||||
}
|
||||
|
||||
// defaultCipherSuitesFIPS are the FIPS-allowed cipher suites.
|
||||
|
||||
@@ -381,8 +381,28 @@ func decodeInnerClientHello(outer *clientHelloMsg, encoded []byte) (*clientHello
|
||||
return nil, errInvalidECHExt
|
||||
}
|
||||
|
||||
if len(inner.supportedVersions) != 1 || (len(inner.supportedVersions) >= 1 && inner.supportedVersions[0] != VersionTLS13) {
|
||||
return nil, errors.New("tls: client sent encrypted_client_hello extension and offered incompatible versions")
|
||||
hasTLS13 := false
|
||||
for _, v := range inner.supportedVersions {
|
||||
// Skip GREASE values (values of the form 0x?A0A).
|
||||
// GREASE (Generate Random Extensions And Sustain Extensibility) is a mechanism used by
|
||||
// browsers like Chrome to ensure TLS implementations correctly ignore unknown values.
|
||||
// GREASE values follow a specific pattern: 0x?A0A, where ? can be any hex digit.
|
||||
// These values should be ignored when processing supported TLS versions.
|
||||
if v&0x0F0F == 0x0A0A && v&0xff == v>>8 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure at least TLS 1.3 is offered.
|
||||
if v == VersionTLS13 {
|
||||
hasTLS13 = true
|
||||
} else if v < VersionTLS13 {
|
||||
// Reject if any non-GREASE value is below TLS 1.3, as ECH requires TLS 1.3+.
|
||||
return nil, errors.New("tls: client sent encrypted_client_hello extension with unsupported versions")
|
||||
}
|
||||
}
|
||||
|
||||
if !hasTLS13 {
|
||||
return nil, errors.New("tls: client sent encrypted_client_hello extension but did not offer TLS 1.3")
|
||||
}
|
||||
|
||||
return inner, nil
|
||||
|
||||
@@ -106,7 +106,7 @@ func isFIPSCipherSuite(id uint16) bool {
|
||||
|
||||
func isFIPSCurve(id CurveID) bool {
|
||||
switch id {
|
||||
case CurveP256, CurveP384:
|
||||
case CurveP256, CurveP384, CurveP521:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -130,6 +130,7 @@ func isFIPSSignatureScheme(alg SignatureScheme) bool {
|
||||
PKCS1WithSHA384,
|
||||
ECDSAWithP384AndSHA384,
|
||||
PKCS1WithSHA512,
|
||||
ECDSAWithP521AndSHA512,
|
||||
PSSWithSHA256,
|
||||
PSSWithSHA384,
|
||||
PSSWithSHA512:
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"encoding/binary"
|
||||
"flag"
|
||||
"fmt"
|
||||
"internal/obscuretestdata"
|
||||
"internal/testenv"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -275,24 +276,16 @@ func TestReadFile(t *testing.T) {
|
||||
|
||||
// Test117 verifies that parsing of the old, pre-1.18 format works.
|
||||
func Test117(t *testing.T) {
|
||||
// go117 was generated for linux-amd64 with:
|
||||
//
|
||||
// main.go:
|
||||
//
|
||||
// package main
|
||||
// func main() {}
|
||||
//
|
||||
// GOTOOLCHAIN=go1.17 go mod init example.com/go117
|
||||
// GOTOOLCHAIN=go1.17 go build
|
||||
//
|
||||
// TODO(prattmic): Ideally this would be built on the fly to better
|
||||
// cover all executable formats, but then we need a network connection
|
||||
// to download an old Go toolchain.
|
||||
info, err := buildinfo.ReadFile("testdata/go117")
|
||||
b, err := obscuretestdata.ReadFile("testdata/go117/go117.base64")
|
||||
if err != nil {
|
||||
t.Fatalf("ReadFile got err %v, want nil", err)
|
||||
}
|
||||
|
||||
info, err := buildinfo.Read(bytes.NewReader(b))
|
||||
if err != nil {
|
||||
t.Fatalf("Read got err %v, want nil", err)
|
||||
}
|
||||
|
||||
if info.GoVersion != "go1.17" {
|
||||
t.Errorf("GoVersion got %s want go1.17", info.GoVersion)
|
||||
}
|
||||
@@ -306,20 +299,14 @@ func Test117(t *testing.T) {
|
||||
|
||||
// TestNotGo verifies that parsing of a non-Go binary returns the proper error.
|
||||
func TestNotGo(t *testing.T) {
|
||||
// notgo was generated for linux-amd64 with:
|
||||
//
|
||||
// main.c:
|
||||
//
|
||||
// int main(void) { return 0; }
|
||||
//
|
||||
// cc -o notgo main.c
|
||||
//
|
||||
// TODO(prattmic): Ideally this would be built on the fly to better
|
||||
// cover all executable formats, but then we need to encode the
|
||||
// intricacies of calling each platform's C compiler.
|
||||
_, err := buildinfo.ReadFile("testdata/notgo")
|
||||
b, err := obscuretestdata.ReadFile("testdata/notgo/notgo.base64")
|
||||
if err != nil {
|
||||
t.Fatalf("ReadFile got err %v, want nil", err)
|
||||
}
|
||||
|
||||
_, err = buildinfo.Read(bytes.NewReader(b))
|
||||
if err == nil {
|
||||
t.Fatalf("ReadFile got nil err, want non-nil")
|
||||
t.Fatalf("Read got nil err, want non-nil")
|
||||
}
|
||||
|
||||
// The precise error text here isn't critical, but we want something
|
||||
@@ -410,13 +397,13 @@ func TestIssue54968(t *testing.T) {
|
||||
}
|
||||
|
||||
func FuzzRead(f *testing.F) {
|
||||
go117, err := os.ReadFile("testdata/go117")
|
||||
go117, err := obscuretestdata.ReadFile("testdata/go117/go117.base64")
|
||||
if err != nil {
|
||||
f.Errorf("Error reading go117: %v", err)
|
||||
}
|
||||
f.Add(go117)
|
||||
|
||||
notgo, err := os.ReadFile("testdata/notgo")
|
||||
notgo, err := obscuretestdata.ReadFile("testdata/notgo/notgo.base64")
|
||||
if err != nil {
|
||||
f.Errorf("Error reading notgo: %v", err)
|
||||
}
|
||||
|
||||
BIN
src/debug/buildinfo/testdata/go117
vendored
BIN
src/debug/buildinfo/testdata/go117
vendored
Binary file not shown.
15
src/debug/buildinfo/testdata/go117/README.md
vendored
Normal file
15
src/debug/buildinfo/testdata/go117/README.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
go117.base64 is a base64-encoded Go 1.17 hello world binary used to test
|
||||
debug/buildinfo of pre-1.18 buildinfo encoding.
|
||||
|
||||
The binary is base64 encoded to hide it from security scanners that believe a
|
||||
Go 1.17 is inherently insecure.
|
||||
|
||||
Generate go117.base64 with:
|
||||
|
||||
$ GOTOOLCHAIN=go1.17 GOOS=linux GOARCH=amd64 go build -trimpath
|
||||
$ base64 go117 > go117.base64
|
||||
$ rm go117
|
||||
|
||||
TODO(prattmic): Ideally this would be built on the fly to better cover all
|
||||
executable formats, but then we need a network connection to download an old Go
|
||||
toolchain.
|
||||
3
src/debug/buildinfo/testdata/go117/go.mod
vendored
Normal file
3
src/debug/buildinfo/testdata/go117/go.mod
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module example.com/go117
|
||||
|
||||
go 1.17
|
||||
20314
src/debug/buildinfo/testdata/go117/go117.base64
vendored
Normal file
20314
src/debug/buildinfo/testdata/go117/go117.base64
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
src/debug/buildinfo/testdata/go117/main.go
vendored
Normal file
7
src/debug/buildinfo/testdata/go117/main.go
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// Copyright 2025 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
|
||||
|
||||
func main() {}
|
||||
BIN
src/debug/buildinfo/testdata/notgo
vendored
BIN
src/debug/buildinfo/testdata/notgo
vendored
Binary file not shown.
17
src/debug/buildinfo/testdata/notgo/README.md
vendored
Normal file
17
src/debug/buildinfo/testdata/notgo/README.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
notgo.base64 is a base64-encoded C hello world binary used to test
|
||||
debug/buildinfo errors on non-Go binaries.
|
||||
|
||||
The binary is base64 encoded to hide it from security scanners that might not
|
||||
like it.
|
||||
|
||||
Generate notgo.base64 on linux-amd64 with:
|
||||
|
||||
$ cc -o notgo main.c
|
||||
$ base64 notgo > notgo.base64
|
||||
$ rm notgo
|
||||
|
||||
The current binary was built with "gcc version 14.2.0 (Debian 14.2.0-3+build4)".
|
||||
|
||||
TODO(prattmic): Ideally this would be built on the fly to better cover all
|
||||
executable formats, but then we need to encode the intricacies of calling each
|
||||
platform's C compiler.
|
||||
7
src/debug/buildinfo/testdata/notgo/main.c
vendored
Normal file
7
src/debug/buildinfo/testdata/notgo/main.c
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// Copyright 2025 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.
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}
|
||||
278
src/debug/buildinfo/testdata/notgo/notgo.base64
vendored
Normal file
278
src/debug/buildinfo/testdata/notgo/notgo.base64
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAQBAAAAAAAABAAAAAAAAAAGA2AAAAAAAAAAAAAEAAOAAN
|
||||
AEAAHgAdAAYAAAAEAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAA2AIAAAAAAADYAgAAAAAAAAgA
|
||||
AAAAAAAAAwAAAAQAAAAYAwAAAAAAABgDAAAAAAAAGAMAAAAAAAAcAAAAAAAAABwAAAAAAAAAAQAA
|
||||
AAAAAAABAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAFAAAAAAAA4AUAAAAAAAAAEAAA
|
||||
AAAAAAEAAAAFAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAPQEAAAAAAAA9AQAAAAAAAAAQAAAA
|
||||
AAAAAQAAAAQAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAADcAAAAAAAAANwAAAAAAAAAABAAAAAA
|
||||
AAABAAAABgAAAAAuAAAAAAAAAD4AAAAAAAAAPgAAAAAAABACAAAAAAAAGAIAAAAAAAAAEAAAAAAA
|
||||
AAIAAAAGAAAAEC4AAAAAAAAQPgAAAAAAABA+AAAAAAAAsAEAAAAAAACwAQAAAAAAAAgAAAAAAAAA
|
||||
BAAAAAQAAAA4AwAAAAAAADgDAAAAAAAAOAMAAAAAAAAgAAAAAAAAACAAAAAAAAAACAAAAAAAAAAE
|
||||
AAAABAAAAFgDAAAAAAAAWAMAAAAAAABYAwAAAAAAAEQAAAAAAAAARAAAAAAAAAAEAAAAAAAAAFPl
|
||||
dGQEAAAAOAMAAAAAAAA4AwAAAAAAADgDAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAgAAAAAAAAAUOV0
|
||||
ZAQAAAAEIAAAAAAAAAQgAAAAAAAABCAAAAAAAAAsAAAAAAAAACwAAAAAAAAABAAAAAAAAABR5XRk
|
||||
BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAFLldGQE
|
||||
AAAAAC4AAAAAAAAAPgAAAAAAAAA+AAAAAAAAAAIAAAAAAAAAAgAAAAAAAAEAAAAAAAAAL2xpYjY0
|
||||
L2xkLWxpbnV4LXg4Ni02NC5zby4yAAAAAAAEAAAAEAAAAAUAAABHTlUAAoAAwAQAAAABAAAAAAAA
|
||||
AAQAAAAUAAAAAwAAAEdOVQB5fSf98eWTEBscIbS6nrsfguPLDgQAAAAQAAAAAQAAAEdOVQAAAAAA
|
||||
AwAAAAIAAAAAAAAAAAAAAAIAAAAFAAAAAQAAAAYAAAAAAIEAAAAAAAUAAAAAAAAA0WXObQAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAEgAAAAAAAAAAAAAAAAAAAAAAAABDAAAAIAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAABfAAAAIAAAAAAAAAAAAAAAAAAAAAAAAABuAAAAIAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAATAAAAIgAAAAAAAAAAAAAAAAAAAAAAAAAAX19saWJjX3N0YXJ0X21haW4AX19jeGFfZmlu
|
||||
YWxpemUAbGliYy5zby42AEdMSUJDXzIuMi41AEdMSUJDXzIuMzQAX0lUTV9kZXJlZ2lzdGVyVE1D
|
||||
bG9uZVRhYmxlAF9fZ21vbl9zdGFydF9fAF9JVE1fcmVnaXN0ZXJUTUNsb25lVGFibGUAAAACAAEA
|
||||
AQABAAMAAAAAAAEAAgAiAAAAEAAAAAAAAAB1GmkJAAADACwAAAAQAAAAtJGWBgAAAgA4AAAAAAAA
|
||||
AAA+AAAAAAAACAAAAAAAAAAgEQAAAAAAAAg+AAAAAAAACAAAAAAAAADgEAAAAAAAAAhAAAAAAAAA
|
||||
CAAAAAAAAAAIQAAAAAAAAMA/AAAAAAAABgAAAAEAAAAAAAAAAAAAAMg/AAAAAAAABgAAAAIAAAAA
|
||||
AAAAAAAAANA/AAAAAAAABgAAAAMAAAAAAAAAAAAAANg/AAAAAAAABgAAAAQAAAAAAAAAAAAAAOA/
|
||||
AAAAAAAABgAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEiD7AhIiwXF
|
||||
LwAASIXAdAL/0EiDxAjDAAAAAAAAAAAA/zXKLwAA/yXMLwAADx9AAP8lqi8AAGaQAAAAAAAAAAAx
|
||||
7UmJ0V5IieJIg+TwUFRFMcAxyUiNPc4AAAD/FV8vAAD0Zi4PH4QAAAAAAA8fQABIjT2ZLwAASI0F
|
||||
ki8AAEg5+HQVSIsFPi8AAEiFwHQJ/+APH4AAAAAAww8fgAAAAABIjT1pLwAASI01Yi8AAEgp/kiJ
|
||||
8EjB7j9IwfgDSAHGSNH+dBRIiwUNLwAASIXAdAj/4GYPH0QAAMMPH4AAAAAA8w8e+oA9JS8AAAB1
|
||||
K1VIgz3qLgAAAEiJ5XQMSIs9Bi8AAOgp////6GT////GBf0uAAABXcMPHwDDDx+AAAAAAPMPHvrp
|
||||
d////1VIieW4AAAAAF3DSIPsCEiDxAjDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAIAARsDOygAAAAEAAAA
|
||||
HPD//3QAAAAs8P//nAAAADzw//9EAAAAJfH//7QAAAAUAAAAAAAAAAF6UgABeBABGwwHCJABBxAU
|
||||
AAAAHAAAAPDv//8iAAAAAAAAAAAAAAAUAAAAAAAAAAF6UgABeBABGwwHCJABAAAkAAAAHAAAAKDv
|
||||
//8QAAAAAA4QRg4YSg8LdwiAAD8aOyozJCIAAAAAFAAAAEQAAACI7///CAAAAAAAAAAAAAAAHAAA
|
||||
AFwAAABp8P//CwAAAABBDhCGAkMNBkYMBwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACARAAAAAAAA4BAAAAAAAAABAAAAAAAA
|
||||
ACIAAAAAAAAADAAAAAAAAAAAEAAAAAAAAA0AAAAAAAAANBEAAAAAAAAZAAAAAAAAAAA+AAAAAAAA
|
||||
GwAAAAAAAAAIAAAAAAAAABoAAAAAAAAACD4AAAAAAAAcAAAAAAAAAAgAAAAAAAAA9f7/bwAAAACg
|
||||
AwAAAAAAAAUAAAAAAAAAWAQAAAAAAAAGAAAAAAAAAMgDAAAAAAAACgAAAAAAAACIAAAAAAAAAAsA
|
||||
AAAAAAAAGAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAwAAAAAAAADoPwAAAAAAAAcAAAAAAAAAIAUA
|
||||
AAAAAAAIAAAAAAAAAMAAAAAAAAAACQAAAAAAAAAYAAAAAAAAAPv//28AAAAAAAAACAAAAAD+//9v
|
||||
AAAAAPAEAAAAAAAA////bwAAAAABAAAAAAAAAPD//28AAAAA4AQAAAAAAAD5//9vAAAAAAMAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAED4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQAAAAAAAAEdDQzogKERl
|
||||
YmlhbiAxNC4yLjAtMytidWlsZDQpIDE0LjIuMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
|
||||
AAAABADx/wAAAAAAAAAAAAAAAAAAAAAJAAAAAQAEAHwDAAAAAAAAIAAAAAAAAAATAAAABADx/wAA
|
||||
AAAAAAAAAAAAAAAAAAAeAAAAAgAOAHAQAAAAAAAAAAAAAAAAAAAgAAAAAgAOAKAQAAAAAAAAAAAA
|
||||
AAAAAAAzAAAAAgAOAOAQAAAAAAAAAAAAAAAAAABJAAAAAQAZABBAAAAAAAAAAQAAAAAAAABVAAAA
|
||||
AQAUAAg+AAAAAAAAAAAAAAAAAAB8AAAAAgAOACARAAAAAAAAAAAAAAAAAACIAAAAAQATAAA+AAAA
|
||||
AAAAAAAAAAAAAACnAAAABADx/wAAAAAAAAAAAAAAAAAAAAATAAAABADx/wAAAAAAAAAAAAAAAAAA
|
||||
AACuAAAAAQASANggAAAAAAAAAAAAAAAAAAAAAAAABADx/wAAAAAAAAAAAAAAAAAAAAC8AAAAAQAV
|
||||
ABA+AAAAAAAAAAAAAAAAAADFAAAAAAARAAQgAAAAAAAAAAAAAAAAAADYAAAAAQAXAOg/AAAAAAAA
|
||||
AAAAAAAAAADuAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAALAQAAIAAAAAAAAAAAAAAAAAAAAAAAAAA2
|
||||
AQAAIAAYAABAAAAAAAAAAAAAAAAAAAAnAQAAEAAYABBAAAAAAAAAAAAAAAAAAAAuAQAAEgIPADQR
|
||||
AAAAAAAAAAAAAAAAAAA0AQAAEAAYAABAAAAAAAAAAAAAAAAAAABBAQAAIAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAABQAQAAEQIYAAhAAAAAAAAAAAAAAAAAAABdAQAAEQAQAAAgAAAAAAAABAAAAAAAAABsAQAA
|
||||
EAAZABhAAAAAAAAAAAAAAAAAAAA6AQAAEgAOAEAQAAAAAAAAIgAAAAAAAABxAQAAEAAZABBAAAAA
|
||||
AAAAAAAAAAAAAAB9AQAAEgAOACkRAAAAAAAACwAAAAAAAACCAQAAEQIYABBAAAAAAAAAAAAAAAAA
|
||||
AACOAQAAIAAAAAAAAAAAAAAAAAAAAAAAAACoAQAAIgAAAAAAAAAAAAAAAAAAAAAAAADDAQAAEgIL
|
||||
AAAQAAAAAAAAAAAAAAAAAAAAU2NydDEubwBfX2FiaV90YWcAY3J0c3R1ZmYuYwBkZXJlZ2lzdGVy
|
||||
X3RtX2Nsb25lcwBfX2RvX2dsb2JhbF9kdG9yc19hdXgAY29tcGxldGVkLjAAX19kb19nbG9iYWxf
|
||||
ZHRvcnNfYXV4X2ZpbmlfYXJyYXlfZW50cnkAZnJhbWVfZHVtbXkAX19mcmFtZV9kdW1teV9pbml0
|
||||
X2FycmF5X2VudHJ5AG1haW4uYwBfX0ZSQU1FX0VORF9fAF9EWU5BTUlDAF9fR05VX0VIX0ZSQU1F
|
||||
X0hEUgBfR0xPQkFMX09GRlNFVF9UQUJMRV8AX19saWJjX3N0YXJ0X21haW5AR0xJQkNfMi4zNABf
|
||||
SVRNX2RlcmVnaXN0ZXJUTUNsb25lVGFibGUAX2VkYXRhAF9maW5pAF9fZGF0YV9zdGFydABfX2dt
|
||||
b25fc3RhcnRfXwBfX2Rzb19oYW5kbGUAX0lPX3N0ZGluX3VzZWQAX2VuZABfX2Jzc19zdGFydABt
|
||||
YWluAF9fVE1DX0VORF9fAF9JVE1fcmVnaXN0ZXJUTUNsb25lVGFibGUAX19jeGFfZmluYWxpemVA
|
||||
R0xJQkNfMi4yLjUAX2luaXQAAC5zeW10YWIALnN0cnRhYgAuc2hzdHJ0YWIALmludGVycAAubm90
|
||||
ZS5nbnUucHJvcGVydHkALm5vdGUuZ251LmJ1aWxkLWlkAC5ub3RlLkFCSS10YWcALmdudS5oYXNo
|
||||
AC5keW5zeW0ALmR5bnN0cgAuZ251LnZlcnNpb24ALmdudS52ZXJzaW9uX3IALnJlbGEuZHluAC5p
|
||||
bml0AC5wbHQuZ290AC50ZXh0AC5maW5pAC5yb2RhdGEALmVoX2ZyYW1lX2hkcgAuZWhfZnJhbWUA
|
||||
LmluaXRfYXJyYXkALmZpbmlfYXJyYXkALmR5bmFtaWMALmdvdC5wbHQALmRhdGEALmJzcwAuY29t
|
||||
bWVudAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAABsAAAABAAAAAgAAAAAAAAAYAwAAAAAAABgDAAAAAAAAHAAAAAAA
|
||||
AAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAjAAAABwAAAAIAAAAAAAAAOAMAAAAAAAA4AwAAAAAA
|
||||
ACAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAANgAAAAcAAAACAAAAAAAAAFgDAAAAAAAA
|
||||
WAMAAAAAAAAkAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEkAAAAHAAAAAgAAAAAAAAB8
|
||||
AwAAAAAAAHwDAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABXAAAA9v//bwIA
|
||||
AAAAAAAAoAMAAAAAAACgAwAAAAAAACQAAAAAAAAABgAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAYQAA
|
||||
AAsAAAACAAAAAAAAAMgDAAAAAAAAyAMAAAAAAACQAAAAAAAAAAcAAAABAAAACAAAAAAAAAAYAAAA
|
||||
AAAAAGkAAAADAAAAAgAAAAAAAABYBAAAAAAAAFgEAAAAAAAAiAAAAAAAAAAAAAAAAAAAAAEAAAAA
|
||||
AAAAAAAAAAAAAABxAAAA////bwIAAAAAAAAA4AQAAAAAAADgBAAAAAAAAAwAAAAAAAAABgAAAAAA
|
||||
AAACAAAAAAAAAAIAAAAAAAAAfgAAAP7//28CAAAAAAAAAPAEAAAAAAAA8AQAAAAAAAAwAAAAAAAA
|
||||
AAcAAAABAAAACAAAAAAAAAAAAAAAAAAAAI0AAAAEAAAAAgAAAAAAAAAgBQAAAAAAACAFAAAAAAAA
|
||||
wAAAAAAAAAAGAAAAAAAAAAgAAAAAAAAAGAAAAAAAAACXAAAAAQAAAAYAAAAAAAAAABAAAAAAAAAA
|
||||
EAAAAAAAABcAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAA9wAAAAEAAAAGAAAAAAAAACAQ
|
||||
AAAAAAAAIBAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAJ0AAAABAAAABgAA
|
||||
AAAAAAAwEAAAAAAAADAQAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAAAAAAAACmAAAA
|
||||
AQAAAAYAAAAAAAAAQBAAAAAAAABAEAAAAAAAAPQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAA
|
||||
AAAArAAAAAEAAAAGAAAAAAAAADQRAAAAAAAANBEAAAAAAAAJAAAAAAAAAAAAAAAAAAAABAAAAAAA
|
||||
AAAAAAAAAAAAALIAAAABAAAAEgAAAAAAAAAAIAAAAAAAAAAgAAAAAAAABAAAAAAAAAAAAAAAAAAA
|
||||
AAQAAAAAAAAABAAAAAAAAAC6AAAAAQAAAAIAAAAAAAAABCAAAAAAAAAEIAAAAAAAACwAAAAAAAAA
|
||||
AAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAyAAAAAEAAAACAAAAAAAAADAgAAAAAAAAMCAAAAAAAACs
|
||||
AAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAANIAAAAOAAAAAwAAAAAAAAAAPgAAAAAAAAAu
|
||||
AAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAAAAAAAADeAAAADwAAAAMAAAAAAAAACD4A
|
||||
AAAAAAAILgAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAA6gAAAAYAAAADAAAA
|
||||
AAAAABA+AAAAAAAAEC4AAAAAAACwAQAAAAAAAAcAAAAAAAAACAAAAAAAAAAQAAAAAAAAAKEAAAAB
|
||||
AAAAAwAAAAAAAADAPwAAAAAAAMAvAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAAAAAA
|
||||
AADzAAAAAQAAAAMAAAAAAAAA6D8AAAAAAADoLwAAAAAAABgAAAAAAAAAAAAAAAAAAAAIAAAAAAAA
|
||||
AAgAAAAAAAAA/AAAAAEAAAADAAAAAAAAAABAAAAAAAAAADAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA
|
||||
CAAAAAAAAAAAAAAAAAAAAAIBAAAIAAAAAwAAAAAAAAAQQAAAAAAAABAwAAAAAAAACAAAAAAAAAAA
|
||||
AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAHAQAAAQAAADAAAAAAAAAAAAAAAAAAAAAQMAAAAAAAACUA
|
||||
AAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAODAA
|
||||
AAAAAABIAwAAAAAAABwAAAASAAAACAAAAAAAAAAYAAAAAAAAAAkAAAADAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAIAzAAAAAAAAyQEAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAAwAAAAAAAAAA
|
||||
AAAAAAAAAAAAAABJNQAAAAAAABABAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA
|
||||
@@ -4,7 +4,7 @@ go 1.24
|
||||
|
||||
require (
|
||||
golang.org/x/crypto v0.30.0
|
||||
golang.org/x/net v0.32.1-0.20250121202134-9a960c88dd98
|
||||
golang.org/x/net v0.32.1-0.20250304185419-76f9bf3279ef
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
|
||||
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/net v0.32.1-0.20250121202134-9a960c88dd98 h1:36bTiCRO7f/J3t+LumnLTJDXqxsp1x6Q7754SsRD9u4=
|
||||
golang.org/x/net v0.32.1-0.20250121202134-9a960c88dd98/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
||||
golang.org/x/net v0.32.1-0.20250304185419-76f9bf3279ef h1:oQtTn7aH5kyi7dPmG2Eot3aG1XBwnkrX+zIq+lNeZeM=
|
||||
golang.org/x/net v0.32.1-0.20250304185419-76f9bf3279ef/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
|
||||
@@ -207,7 +207,7 @@ func (check *Checker) lhsVar(lhs ast.Expr) Type {
|
||||
// dot-imported variables.
|
||||
if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
|
||||
v = w
|
||||
v_used = v.used
|
||||
v_used = check.usedVars[v]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,7 +216,7 @@ func (check *Checker) lhsVar(lhs ast.Expr) Type {
|
||||
check.expr(nil, &x, lhs)
|
||||
|
||||
if v != nil {
|
||||
v.used = v_used // restore v.used
|
||||
check.usedVars[v] = v_used // restore v.used
|
||||
}
|
||||
|
||||
if x.mode == invalid || !isValid(x.typ) {
|
||||
|
||||
@@ -689,7 +689,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *TypeName, w
|
||||
if pname, _ := obj.(*PkgName); pname != nil {
|
||||
assert(pname.pkg == check.pkg)
|
||||
check.recordUse(ident, pname)
|
||||
pname.used = true
|
||||
check.usedPkgNames[pname] = true
|
||||
pkg := pname.imported
|
||||
|
||||
var exp Object
|
||||
@@ -1020,13 +1020,13 @@ func (check *Checker) use1(e ast.Expr, lhs bool) bool {
|
||||
// dot-imported variables.
|
||||
if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
|
||||
v = w
|
||||
v_used = v.used
|
||||
v_used = check.usedVars[v]
|
||||
}
|
||||
}
|
||||
}
|
||||
check.exprOrType(&x, n, true)
|
||||
if v != nil {
|
||||
v.used = v_used // restore v.used
|
||||
check.usedVars[v] = v_used // restore v.used
|
||||
}
|
||||
default:
|
||||
check.rawExpr(nil, &x, e, nil, true)
|
||||
|
||||
@@ -182,6 +182,8 @@ type Checker struct {
|
||||
dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through
|
||||
brokenAliases map[*TypeName]bool // set of aliases with broken (not yet determined) types
|
||||
unionTypeSets map[*Union]*_TypeSet // computed type sets for union types
|
||||
usedVars map[*Var]bool // set of used variables
|
||||
usedPkgNames map[*PkgName]bool // set of used package names
|
||||
mono monoGraph // graph for detecting non-monomorphizable instantiation loops
|
||||
|
||||
firstErr error // first error encountered
|
||||
@@ -308,13 +310,15 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
|
||||
conf._EnableAlias = gotypesalias.Value() != "0"
|
||||
|
||||
return &Checker{
|
||||
conf: conf,
|
||||
ctxt: conf.Context,
|
||||
fset: fset,
|
||||
pkg: pkg,
|
||||
Info: info,
|
||||
objMap: make(map[Object]*declInfo),
|
||||
impMap: make(map[importKey]*Package),
|
||||
conf: conf,
|
||||
ctxt: conf.Context,
|
||||
fset: fset,
|
||||
pkg: pkg,
|
||||
Info: info,
|
||||
objMap: make(map[Object]*declInfo),
|
||||
impMap: make(map[importKey]*Package),
|
||||
usedVars: make(map[*Var]bool),
|
||||
usedPkgNames: make(map[*PkgName]bool),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +326,8 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
|
||||
// The provided files must all belong to the same package.
|
||||
func (check *Checker) initFiles(files []*ast.File) {
|
||||
// start with a clean slate (check.Files may be called multiple times)
|
||||
// TODO(gri): what determines which fields are zeroed out here, vs at the end
|
||||
// of checkFiles?
|
||||
check.files = nil
|
||||
check.imports = nil
|
||||
check.dotImportMap = nil
|
||||
@@ -333,6 +339,13 @@ func (check *Checker) initFiles(files []*ast.File) {
|
||||
check.objPath = nil
|
||||
check.cleaners = nil
|
||||
|
||||
// We must initialize usedVars and usedPkgNames both here and in NewChecker,
|
||||
// because initFiles is not called in the CheckExpr or Eval codepaths, yet we
|
||||
// want to free this memory at the end of Files ('used' predicates are
|
||||
// only needed in the context of a given file).
|
||||
check.usedVars = make(map[*Var]bool)
|
||||
check.usedPkgNames = make(map[*PkgName]bool)
|
||||
|
||||
// determine package name and collect valid files
|
||||
pkg := check.pkg
|
||||
for _, file := range files {
|
||||
@@ -507,9 +520,12 @@ func (check *Checker) checkFiles(files []*ast.File) {
|
||||
check.seenPkgMap = nil
|
||||
check.brokenAliases = nil
|
||||
check.unionTypeSets = nil
|
||||
check.usedVars = nil
|
||||
check.usedPkgNames = nil
|
||||
check.ctxt = nil
|
||||
|
||||
// TODO(rFindley) There's more memory we should release at this point.
|
||||
// TODO(gri): shouldn't the cleanup above occur after the bailout?
|
||||
// TODO(gri) There's more memory we should release at this point.
|
||||
}
|
||||
|
||||
// processDelayed processes all delayed actions pushed after top.
|
||||
|
||||
@@ -245,13 +245,12 @@ func (a *object) cmp(b *object) int {
|
||||
type PkgName struct {
|
||||
object
|
||||
imported *Package
|
||||
used bool // set if the package was used
|
||||
}
|
||||
|
||||
// NewPkgName returns a new PkgName object representing an imported package.
|
||||
// The remaining arguments set the attributes found with all Objects.
|
||||
func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
|
||||
return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, nopos}, imported, false}
|
||||
return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, nopos}, imported}
|
||||
}
|
||||
|
||||
// Imported returns the package that was imported.
|
||||
@@ -334,10 +333,10 @@ func (obj *TypeName) IsAlias() bool {
|
||||
// A Variable represents a declared variable (including function parameters and results, and struct fields).
|
||||
type Var struct {
|
||||
object
|
||||
origin *Var // if non-nil, the Var from which this one was instantiated
|
||||
embedded bool // if set, the variable is an embedded struct field, and name is the type name
|
||||
isField bool // var is struct field
|
||||
used bool // set if the variable was used
|
||||
origin *Var // if non-nil, the Var from which this one was instantiated
|
||||
isParam bool // var is a param, for backport of 'used' check to go1.24 (go.dev/issue/72826)
|
||||
}
|
||||
|
||||
// NewVar returns a new variable.
|
||||
@@ -348,7 +347,7 @@ func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
|
||||
|
||||
// NewParam returns a new variable representing a function parameter.
|
||||
func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
|
||||
return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, used: true} // parameters are always 'used'
|
||||
return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, isParam: true}
|
||||
}
|
||||
|
||||
// NewField returns a new variable representing a struct field.
|
||||
|
||||
@@ -310,7 +310,7 @@ func (check *Checker) collectObjects() {
|
||||
|
||||
if imp.fake {
|
||||
// match 1.17 cmd/compile (not prescribed by spec)
|
||||
pkgName.used = true
|
||||
check.usedPkgNames[pkgName] = true
|
||||
}
|
||||
|
||||
// add import to file scope
|
||||
@@ -710,7 +710,7 @@ func (check *Checker) unusedImports() {
|
||||
// (initialization), use the blank identifier as explicit package name."
|
||||
|
||||
for _, obj := range check.imports {
|
||||
if !obj.used && obj.name != "_" {
|
||||
if obj.name != "_" && !check.usedPkgNames[obj] {
|
||||
check.errorUnusedPkg(obj)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestSizeof(t *testing.T) {
|
||||
{term{}, 12, 24},
|
||||
|
||||
// Objects
|
||||
{PkgName{}, 48, 88},
|
||||
{PkgName{}, 44, 80},
|
||||
{Const{}, 48, 88},
|
||||
{TypeName{}, 40, 72},
|
||||
{Var{}, 48, 88},
|
||||
|
||||
@@ -59,7 +59,7 @@ func (check *Checker) usage(scope *Scope) {
|
||||
var unused []*Var
|
||||
for name, elem := range scope.elems {
|
||||
elem = resolve(name, elem)
|
||||
if v, _ := elem.(*Var); v != nil && !v.used {
|
||||
if v, _ := elem.(*Var); v != nil && !v.isParam && !check.usedVars[v] {
|
||||
unused = append(unused, v)
|
||||
}
|
||||
}
|
||||
@@ -777,13 +777,16 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
}
|
||||
|
||||
// If lhs exists, we must have at least one lhs variable that was used.
|
||||
// (We can't use check.usage because that only looks at one scope; and
|
||||
// we don't want to use the same variable for all scopes and change the
|
||||
// variable type underfoot.)
|
||||
if lhs != nil {
|
||||
var used bool
|
||||
for _, v := range lhsVars {
|
||||
if v.used {
|
||||
if check.usedVars[v] {
|
||||
used = true
|
||||
}
|
||||
v.used = true // avoid usage error when checking entire function
|
||||
check.usedVars[v] = true // avoid usage error when checking entire function
|
||||
}
|
||||
if !used {
|
||||
check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Name)
|
||||
@@ -952,7 +955,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *ast.RangeStmt) {
|
||||
if typ == nil || typ == Typ[Invalid] {
|
||||
// typ == Typ[Invalid] can happen if allowVersion fails.
|
||||
obj.typ = Typ[Invalid]
|
||||
obj.used = true // don't complain about unused variable
|
||||
check.usedVars[obj] = true // don't complain about unused variable
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bo
|
||||
// avoid "declared but not used" errors
|
||||
// (don't use Checker.use - we don't want to evaluate too much)
|
||||
if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ {
|
||||
v.used = true
|
||||
check.usedVars[v] = true
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bo
|
||||
// (This code is only needed for dot-imports. Without them,
|
||||
// we only have to mark variables, see *Var case below).
|
||||
if pkgName := check.dotImportMap[dotImportKey{scope, obj.Name()}]; pkgName != nil {
|
||||
pkgName.used = true
|
||||
check.usedPkgNames[pkgName] = true
|
||||
}
|
||||
|
||||
switch obj := obj.(type) {
|
||||
@@ -119,7 +119,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bo
|
||||
// from other packages to avoid potential race conditions with
|
||||
// dot-imported variables.
|
||||
if obj.pkg == check.pkg {
|
||||
obj.used = true
|
||||
check.usedVars[obj] = true
|
||||
}
|
||||
check.addDeclDep(obj)
|
||||
if !isValid(typ) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -46,7 +46,8 @@ func TestAll(t *testing.T) {
|
||||
if info.Old != "" && info.Changed == 0 {
|
||||
t.Errorf("Name=%s has Old, missing Changed", info.Name)
|
||||
}
|
||||
if !strings.Contains(doc, "`"+info.Name+"`") {
|
||||
if !strings.Contains(doc, "`"+info.Name+"`") &&
|
||||
!strings.Contains(doc, "`"+info.Name+"=") {
|
||||
t.Errorf("Name=%s not documented in doc/godebug.md", info.Name)
|
||||
}
|
||||
if !info.Opaque && !incs[info.Name] {
|
||||
|
||||
@@ -25,9 +25,11 @@ type Info struct {
|
||||
// Note: After adding entries to this table, update the list in doc/godebug.md as well.
|
||||
// (Otherwise the test in this package will fail.)
|
||||
var All = []Info{
|
||||
{Name: "allowmultiplevcs", Package: "cmd/go"},
|
||||
{Name: "asynctimerchan", Package: "time", Changed: 23, Old: "1"},
|
||||
{Name: "dataindependenttiming", Package: "crypto/subtle", Opaque: true},
|
||||
{Name: "execerrdot", Package: "os/exec"},
|
||||
{Name: "fips140", Package: "crypto/fips140", Opaque: true},
|
||||
{Name: "gocachehash", Package: "cmd/go"},
|
||||
{Name: "gocachetest", Package: "cmd/go"},
|
||||
{Name: "gocacheverify", Package: "cmd/go"},
|
||||
@@ -58,8 +60,8 @@ var All = []Info{
|
||||
{Name: "tlsmlkem", Package: "crypto/tls", Changed: 24, Old: "0", Opaque: true},
|
||||
{Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"},
|
||||
{Name: "tlsunsafeekm", Package: "crypto/tls", Changed: 22, Old: "1"},
|
||||
{Name: "winreadlinkvolume", Package: "os", Changed: 22, Old: "0"},
|
||||
{Name: "winsymlink", Package: "os", Changed: 22, Old: "0"},
|
||||
{Name: "winreadlinkvolume", Package: "os", Changed: 23, Old: "0"},
|
||||
{Name: "winsymlink", Package: "os", Changed: 23, Old: "0"},
|
||||
{Name: "x509keypairleaf", Package: "crypto/tls", Changed: 23, Old: "0"},
|
||||
{Name: "x509negativeserial", Package: "crypto/x509", Changed: 23, Old: "1"},
|
||||
{Name: "x509rsacrt", Package: "crypto/x509", Changed: 24, Old: "0"},
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
func runtime_mapaccess1_fast32(typ *abi.SwissMapType, m *Map, key uint32) unsafe.Pointer {
|
||||
if race.Enabled && m != nil {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess1)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess1_fast32)
|
||||
race.ReadPC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ func runtime_mapaccess1_fast32(typ *abi.SwissMapType, m *Map, key uint32) unsafe
|
||||
func runtime_mapaccess2_fast32(typ *abi.SwissMapType, m *Map, key uint32) (unsafe.Pointer, bool) {
|
||||
if race.Enabled && m != nil {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess1)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess2_fast32)
|
||||
race.ReadPC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ func runtime_mapassign_fast32(typ *abi.SwissMapType, m *Map, key uint32) unsafe.
|
||||
}
|
||||
if race.Enabled {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign_fast32)
|
||||
race.WritePC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
if m.writing != 0 {
|
||||
@@ -332,7 +332,7 @@ func runtime_mapassign_fast32ptr(typ *abi.SwissMapType, m *Map, key unsafe.Point
|
||||
}
|
||||
if race.Enabled {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign_fast32ptr)
|
||||
race.WritePC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
if m.writing != 0 {
|
||||
@@ -458,7 +458,7 @@ outer:
|
||||
func runtime_mapdelete_fast32(typ *abi.SwissMapType, m *Map, key uint32) {
|
||||
if race.Enabled {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapdelete_fast32)
|
||||
race.WritePC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
func runtime_mapaccess1_fast64(typ *abi.SwissMapType, m *Map, key uint64) unsafe.Pointer {
|
||||
if race.Enabled && m != nil {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess1)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess1_fast64)
|
||||
race.ReadPC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ func runtime_mapaccess1_fast64(typ *abi.SwissMapType, m *Map, key uint64) unsafe
|
||||
func runtime_mapaccess2_fast64(typ *abi.SwissMapType, m *Map, key uint64) (unsafe.Pointer, bool) {
|
||||
if race.Enabled && m != nil {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess1)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess2_fast64)
|
||||
race.ReadPC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ func runtime_mapassign_fast64(typ *abi.SwissMapType, m *Map, key uint64) unsafe.
|
||||
}
|
||||
if race.Enabled {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign_fast64)
|
||||
race.WritePC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
if m.writing != 0 {
|
||||
@@ -370,7 +370,7 @@ func runtime_mapassign_fast64ptr(typ *abi.SwissMapType, m *Map, key unsafe.Point
|
||||
}
|
||||
if race.Enabled {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign_fast64ptr)
|
||||
race.WritePC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
if m.writing != 0 {
|
||||
@@ -497,7 +497,7 @@ outer:
|
||||
func runtime_mapdelete_fast64(typ *abi.SwissMapType, m *Map, key uint64) {
|
||||
if race.Enabled {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapdelete_fast64)
|
||||
race.WritePC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ func stringPtr(s string) unsafe.Pointer {
|
||||
func runtime_mapaccess1_faststr(typ *abi.SwissMapType, m *Map, key string) unsafe.Pointer {
|
||||
if race.Enabled && m != nil {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess1)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess1_faststr)
|
||||
race.ReadPC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ func runtime_mapaccess1_faststr(typ *abi.SwissMapType, m *Map, key string) unsaf
|
||||
func runtime_mapaccess2_faststr(typ *abi.SwissMapType, m *Map, key string) (unsafe.Pointer, bool) {
|
||||
if race.Enabled && m != nil {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess1)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapaccess2_faststr)
|
||||
race.ReadPC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ func runtime_mapassign_faststr(typ *abi.SwissMapType, m *Map, key string) unsafe
|
||||
}
|
||||
if race.Enabled {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign_faststr)
|
||||
race.WritePC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
if m.writing != 0 {
|
||||
@@ -396,7 +396,7 @@ outer:
|
||||
func runtime_mapdelete_faststr(typ *abi.SwissMapType, m *Map, key string) {
|
||||
if race.Enabled {
|
||||
callerpc := sys.GetCallerPC()
|
||||
pc := abi.FuncPCABIInternal(runtime_mapassign)
|
||||
pc := abi.FuncPCABIInternal(runtime_mapdelete_faststr)
|
||||
race.WritePC(unsafe.Pointer(m), callerpc, pc)
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ func Mkdirat(dirfd int, path string, mode uint32) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_mkdirat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(p)), 0, 0, 0, 0)
|
||||
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_mkdirat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(p)), uintptr(mode), 0, 0, 0)
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -504,3 +504,26 @@ func ParallelOn64Bit(t *testing.T) {
|
||||
}
|
||||
t.Parallel()
|
||||
}
|
||||
|
||||
// CPUProfilingBroken returns true if CPU profiling has known issues on this
|
||||
// platform.
|
||||
func CPUProfilingBroken() bool {
|
||||
switch runtime.GOOS {
|
||||
case "plan9":
|
||||
// Profiling unimplemented.
|
||||
return true
|
||||
case "aix":
|
||||
// See https://golang.org/issue/45170.
|
||||
return true
|
||||
case "ios", "dragonfly", "netbsd", "illumos", "solaris":
|
||||
// See https://golang.org/issue/13841.
|
||||
return true
|
||||
case "openbsd":
|
||||
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
|
||||
// See https://golang.org/issue/13841.
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -164,6 +164,19 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) {
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// RFC 9112 permits parsers to accept a bare \n as a line ending in headers,
|
||||
// but not in chunked encoding lines. See https://www.rfc-editor.org/errata/eid7633,
|
||||
// which explicitly rejects a clarification permitting \n as a chunk terminator.
|
||||
//
|
||||
// Verify that the line ends in a CRLF, and that no CRs appear before the end.
|
||||
if idx := bytes.IndexByte(p, '\r'); idx == -1 {
|
||||
return nil, errors.New("chunked line ends with bare LF")
|
||||
} else if idx != len(p)-2 {
|
||||
return nil, errors.New("invalid CR in chunked line")
|
||||
}
|
||||
p = p[:len(p)-2] // trim CRLF
|
||||
|
||||
if len(p) >= maxLineLength {
|
||||
return nil, ErrLineTooLong
|
||||
}
|
||||
@@ -171,14 +184,14 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) {
|
||||
}
|
||||
|
||||
func trimTrailingWhitespace(b []byte) []byte {
|
||||
for len(b) > 0 && isASCIISpace(b[len(b)-1]) {
|
||||
for len(b) > 0 && isOWS(b[len(b)-1]) {
|
||||
b = b[:len(b)-1]
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func isASCIISpace(b byte) bool {
|
||||
return b == ' ' || b == '\t' || b == '\n' || b == '\r'
|
||||
func isOWS(b byte) bool {
|
||||
return b == ' ' || b == '\t'
|
||||
}
|
||||
|
||||
var semi = []byte(";")
|
||||
|
||||
@@ -280,6 +280,33 @@ func TestChunkReaderByteAtATime(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestChunkInvalidInputs(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
b string
|
||||
}{{
|
||||
name: "bare LF in chunk size",
|
||||
b: "1\na\r\n0\r\n",
|
||||
}, {
|
||||
name: "extra LF in chunk size",
|
||||
b: "1\r\r\na\r\n0\r\n",
|
||||
}, {
|
||||
name: "bare LF in chunk data",
|
||||
b: "1\r\na\n0\r\n",
|
||||
}, {
|
||||
name: "bare LF in chunk extension",
|
||||
b: "1;\na\r\n0\r\n",
|
||||
}} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
r := NewChunkedReader(strings.NewReader(test.b))
|
||||
got, err := io.ReadAll(r)
|
||||
if err == nil {
|
||||
t.Fatalf("unexpectedly parsed invalid chunked data:\n%q", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type funcReader struct {
|
||||
f func(iteration int) ([]byte, error)
|
||||
i int
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"compress/zlib"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -7303,3 +7304,120 @@ func testServerReadAfterHandlerAbort100Continue(t *testing.T, mode testMode) {
|
||||
readyc <- struct{}{} // server starts reading from the request body
|
||||
readyc <- struct{}{} // server finishes reading from the request body
|
||||
}
|
||||
|
||||
// Issue #72100: Verify that we don't modify the caller's TLS.Config.NextProtos slice.
|
||||
func TestServerTLSNextProtos(t *testing.T) {
|
||||
run(t, testServerTLSNextProtos, []testMode{https1Mode, http2Mode})
|
||||
}
|
||||
func testServerTLSNextProtos(t *testing.T, mode testMode) {
|
||||
CondSkipHTTP2(t)
|
||||
|
||||
cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
leafCert, err := x509.ParseCertificate(cert.Certificate[0])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
certpool := x509.NewCertPool()
|
||||
certpool.AddCert(leafCert)
|
||||
|
||||
protos := new(Protocols)
|
||||
switch mode {
|
||||
case https1Mode:
|
||||
protos.SetHTTP1(true)
|
||||
case http2Mode:
|
||||
protos.SetHTTP2(true)
|
||||
}
|
||||
|
||||
wantNextProtos := []string{"http/1.1", "h2", "other"}
|
||||
nextProtos := slices.Clone(wantNextProtos)
|
||||
|
||||
// We don't use httptest here because it overrides the tls.Config.
|
||||
srv := &Server{
|
||||
TLSConfig: &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
NextProtos: nextProtos,
|
||||
},
|
||||
Handler: HandlerFunc(func(w ResponseWriter, req *Request) {}),
|
||||
Protocols: protos,
|
||||
}
|
||||
tr := &Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: certpool,
|
||||
NextProtos: nextProtos,
|
||||
},
|
||||
Protocols: protos,
|
||||
}
|
||||
|
||||
listener := newLocalListener(t)
|
||||
srvc := make(chan error, 1)
|
||||
go func() {
|
||||
srvc <- srv.ServeTLS(listener, "", "")
|
||||
}()
|
||||
t.Cleanup(func() {
|
||||
srv.Close()
|
||||
<-srvc
|
||||
})
|
||||
|
||||
client := &Client{Transport: tr}
|
||||
resp, err := client.Get("https://" + listener.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
if !slices.Equal(nextProtos, wantNextProtos) {
|
||||
t.Fatalf("after running test: original NextProtos slice = %v, want %v", nextProtos, wantNextProtos)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidChunkedBodies(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
b string
|
||||
}{{
|
||||
name: "bare LF in chunk size",
|
||||
b: "1\na\r\n0\r\n\r\n",
|
||||
}, {
|
||||
name: "bare LF at body end",
|
||||
b: "1\r\na\r\n0\r\n\n",
|
||||
}} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
reqc := make(chan error)
|
||||
ts := newClientServerTest(t, http1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||
got, err := io.ReadAll(r.Body)
|
||||
if err == nil {
|
||||
t.Logf("read body: %q", got)
|
||||
}
|
||||
reqc <- err
|
||||
})).ts
|
||||
|
||||
serverURL, err := url.Parse(ts.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
conn, err := net.Dial("tcp", serverURL.Host)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := conn.Write([]byte(
|
||||
"POST / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Transfer-Encoding: chunked\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n" +
|
||||
test.b)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conn.(*net.TCPConn).CloseWrite()
|
||||
|
||||
if err := <-reqc; err == nil {
|
||||
t.Errorf("server handler: io.ReadAll(r.Body) succeeded, want error")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3521,6 +3521,12 @@ func (s *Server) protocols() Protocols {
|
||||
// adjustNextProtos adds or removes "http/1.1" and "h2" entries from
|
||||
// a tls.Config.NextProtos list, according to the set of protocols in protos.
|
||||
func adjustNextProtos(nextProtos []string, protos Protocols) []string {
|
||||
// Make a copy of NextProtos since it might be shared with some other tls.Config.
|
||||
// (tls.Config.Clone doesn't do a deep copy.)
|
||||
//
|
||||
// We could avoid an allocation in the common case by checking to see if the slice
|
||||
// is already in order, but this is just one small allocation per connection.
|
||||
nextProtos = slices.Clone(nextProtos)
|
||||
var have Protocols
|
||||
nextProtos = slices.DeleteFunc(nextProtos, func(s string) bool {
|
||||
switch s {
|
||||
|
||||
@@ -11,12 +11,15 @@ import (
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -24,6 +27,7 @@ import (
|
||||
|
||||
func init() {
|
||||
registerHelperCommand("pwd", cmdPwd)
|
||||
registerHelperCommand("signaltest", cmdSignalTest)
|
||||
}
|
||||
|
||||
func cmdPwd(...string) {
|
||||
@@ -274,3 +278,55 @@ func TestExplicitPWD(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 71828.
|
||||
func TestSIGCHLD(t *testing.T) {
|
||||
cmd := helperCommand(t, "signaltest")
|
||||
out, err := cmd.CombinedOutput()
|
||||
t.Logf("%s", out)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// cmdSignaltest is for TestSIGCHLD.
|
||||
// This runs in a separate process because the bug only happened
|
||||
// the first time that a child process was started.
|
||||
func cmdSignalTest(...string) {
|
||||
chSig := make(chan os.Signal, 1)
|
||||
signal.Notify(chSig, syscall.SIGCHLD)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
c := 0
|
||||
for range chSig {
|
||||
c++
|
||||
fmt.Printf("SIGCHLD %d\n", c)
|
||||
if c > 1 {
|
||||
fmt.Println("too many SIGCHLD signals")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
signal.Reset(syscall.SIGCHLD)
|
||||
close(chSig)
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
fmt.Printf("os.Executable failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cmd := exec.Command(exe, "hang", "200ms")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Printf("failed to run child process: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -3848,3 +3873,14 @@ func TestRemoveReadOnlyFile(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestOpenFileDevNull(t *testing.T) {
|
||||
// See https://go.dev/issue/71752.
|
||||
t.Parallel()
|
||||
|
||||
f, err := OpenFile(DevNull, O_WRONLY|O_CREATE|O_TRUNC, 0o644)
|
||||
if err != nil {
|
||||
t.Fatalf("OpenFile(DevNull): %v", err)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ func OpenInRoot(dir, name string) (*File, error) {
|
||||
// - When GOOS=plan9 or GOOS=js, Root does not track directories across renames.
|
||||
// On these platforms, a Root references a directory name, not a file descriptor.
|
||||
type Root struct {
|
||||
root root
|
||||
root *root
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -186,20 +186,20 @@ func (r *Root) logStat(name string) {
|
||||
//
|
||||
// "." components are removed, except in the last component.
|
||||
//
|
||||
// Path separators following the last component are preserved.
|
||||
func splitPathInRoot(s string, prefix, suffix []string) (_ []string, err error) {
|
||||
// Path separators following the last component are returned in suffixSep.
|
||||
func splitPathInRoot(s string, prefix, suffix []string) (_ []string, suffixSep string, err error) {
|
||||
if len(s) == 0 {
|
||||
return nil, errors.New("empty path")
|
||||
return nil, "", errors.New("empty path")
|
||||
}
|
||||
if IsPathSeparator(s[0]) {
|
||||
return nil, errPathEscapes
|
||||
return nil, "", errPathEscapes
|
||||
}
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
// Windows cleans paths before opening them.
|
||||
s, err = rootCleanPath(s, prefix, suffix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
prefix = nil
|
||||
suffix = nil
|
||||
@@ -215,13 +215,14 @@ func splitPathInRoot(s string, prefix, suffix []string) (_ []string, err error)
|
||||
}
|
||||
parts = append(parts, s[i:j])
|
||||
// Advance to the next component, or end of the path.
|
||||
partEnd := j
|
||||
for j < len(s) && IsPathSeparator(s[j]) {
|
||||
j++
|
||||
}
|
||||
if j == len(s) {
|
||||
// If this is the last path component,
|
||||
// preserve any trailing path separators.
|
||||
parts[len(parts)-1] = s[i:]
|
||||
suffixSep = s[partEnd:]
|
||||
break
|
||||
}
|
||||
if parts[len(parts)-1] == "." {
|
||||
@@ -235,7 +236,7 @@ func splitPathInRoot(s string, prefix, suffix []string) (_ []string, err error)
|
||||
parts = parts[:len(parts)-1]
|
||||
}
|
||||
parts = append(parts, suffix...)
|
||||
return parts, nil
|
||||
return parts, suffixSep, nil
|
||||
}
|
||||
|
||||
// FS returns a file system (an fs.FS) for the tree of files in the root.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user