mirror of
https://github.com/golang/go.git
synced 2026-02-01 08:32:04 +03:00
Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d41a822213 | ||
|
|
86c5e2d025 | ||
|
|
94ca1d97b4 | ||
|
|
fe83d4bcad | ||
|
|
7f36edc26d | ||
|
|
83b4a5db24 | ||
|
|
0f5133b742 | ||
|
|
6e1c4529e4 | ||
|
|
731de13dc3 | ||
|
|
390ffce7d6 | ||
|
|
b454859a8a | ||
|
|
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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,9 @@ func ModIsPrefix(path, vers string) bool {
|
||||
// The caller is assumed to have checked that ModIsValid(path, vers) is true.
|
||||
func ModIsPrerelease(path, vers string) bool {
|
||||
if IsToolchain(path) {
|
||||
if path == "toolchain" {
|
||||
return IsPrerelease(FromToolchain(vers))
|
||||
}
|
||||
return IsPrerelease(vers)
|
||||
}
|
||||
return semver.Prerelease(vers) != ""
|
||||
|
||||
@@ -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'
|
||||
|
||||
10
src/cmd/go/testdata/script/mod_get_toolchain.txt
vendored
10
src/cmd/go/testdata/script/mod_get_toolchain.txt
vendored
@@ -89,12 +89,14 @@ stderr '^go: added toolchain go1.24rc1$'
|
||||
grep 'go 1.22.9' go.mod # no longer implied
|
||||
grep 'toolchain go1.24rc1' go.mod
|
||||
|
||||
# go get toolchain@latest finds go1.999testmod.
|
||||
# go get toolchain@latest finds go1.23.9.
|
||||
cp go.mod.orig go.mod
|
||||
go get toolchain@latest
|
||||
stderr '^go: added toolchain go1.999testmod$'
|
||||
stderr '^go: added toolchain go1.23.9$'
|
||||
grep 'go 1.21' go.mod
|
||||
grep 'toolchain go1.999testmod' go.mod
|
||||
grep 'toolchain go1.23.9' go.mod
|
||||
|
||||
|
||||
|
||||
# Bug fixes.
|
||||
|
||||
@@ -110,7 +112,7 @@ stderr '^go: upgraded go 1.19 => 1.21.0'
|
||||
|
||||
# go get toolchain@1.24rc1 is OK too.
|
||||
go get toolchain@1.24rc1
|
||||
stderr '^go: downgraded toolchain go1.999testmod => go1.24rc1$'
|
||||
stderr '^go: downgraded toolchain go1.99rc1 => go1.24rc1$'
|
||||
|
||||
# go get go@1.21 should work if we are the Go 1.21 language version,
|
||||
# even though there's no toolchain for it.
|
||||
|
||||
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
|
||||
|
||||
@@ -907,18 +907,49 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||
p.To.Reg = REGFP
|
||||
p.To.Offset = REGLINK
|
||||
|
||||
// ADD $aoffset, RSP, RSP
|
||||
q = newprog()
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(aoffset)
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Spadj = -aoffset
|
||||
q.Pos = p.Pos
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
p = q
|
||||
if aoffset < 1<<12 {
|
||||
// ADD $aoffset, RSP, RSP
|
||||
q = newprog()
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(aoffset)
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Spadj = -aoffset
|
||||
q.Pos = p.Pos
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
p = q
|
||||
} else {
|
||||
// Put frame size in a separate register and
|
||||
// add it in with a single instruction,
|
||||
// so we never have a partial frame during
|
||||
// the epilog. See issue 73259.
|
||||
|
||||
// MOVD $aoffset, REGTMP
|
||||
q = newprog()
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(aoffset)
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGTMP
|
||||
q.Pos = p.Pos
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
p = q
|
||||
// ADD REGTMP, RSP, RSP
|
||||
q = newprog()
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REGTMP
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Spadj = -aoffset
|
||||
q.Pos = p.Pos
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
p = q
|
||||
}
|
||||
}
|
||||
|
||||
// If enabled, this code emits 'MOV PC, R27' before every 'MOV LR, PC',
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,6 @@ func convertAssignRows(dest, src any, rows *Rows) error {
|
||||
if rows == nil {
|
||||
return errors.New("invalid context to convert cursor rows, missing parent *Rows")
|
||||
}
|
||||
rows.closemu.Lock()
|
||||
*d = Rows{
|
||||
dc: rows.dc,
|
||||
releaseConn: func(error) {},
|
||||
@@ -351,7 +350,6 @@ func convertAssignRows(dest, src any, rows *Rows) error {
|
||||
parentCancel()
|
||||
}
|
||||
}
|
||||
rows.closemu.Unlock()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
@@ -15,7 +16,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -91,8 +91,6 @@ func (cc *fakeDriverCtx) OpenConnector(name string) (driver.Connector, error) {
|
||||
type fakeDB struct {
|
||||
name string
|
||||
|
||||
useRawBytes atomic.Bool
|
||||
|
||||
mu sync.Mutex
|
||||
tables map[string]*table
|
||||
badConn bool
|
||||
@@ -684,8 +682,6 @@ func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stm
|
||||
switch cmd {
|
||||
case "WIPE":
|
||||
// Nothing
|
||||
case "USE_RAWBYTES":
|
||||
c.db.useRawBytes.Store(true)
|
||||
case "SELECT":
|
||||
stmt, err = c.prepareSelect(stmt, parts)
|
||||
case "CREATE":
|
||||
@@ -789,9 +785,6 @@ func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (d
|
||||
case "WIPE":
|
||||
db.wipe()
|
||||
return driver.ResultNoRows, nil
|
||||
case "USE_RAWBYTES":
|
||||
s.c.db.useRawBytes.Store(true)
|
||||
return driver.ResultNoRows, nil
|
||||
case "CREATE":
|
||||
if err := db.createTable(s.table, s.colName, s.colType); err != nil {
|
||||
return nil, err
|
||||
@@ -1076,10 +1069,9 @@ type rowsCursor struct {
|
||||
errPos int
|
||||
err error
|
||||
|
||||
// a clone of slices to give out to clients, indexed by the
|
||||
// original slice's first byte address. we clone them
|
||||
// just so we're able to corrupt them on close.
|
||||
bytesClone map[*byte][]byte
|
||||
// Data returned to clients.
|
||||
// We clone and stash it here so it can be invalidated by Close and Next.
|
||||
driverOwnedMemory [][]byte
|
||||
|
||||
// Every operation writes to line to enable the race detector
|
||||
// check for data races.
|
||||
@@ -1096,9 +1088,19 @@ func (rc *rowsCursor) touchMem() {
|
||||
rc.line++
|
||||
}
|
||||
|
||||
func (rc *rowsCursor) invalidateDriverOwnedMemory() {
|
||||
for _, buf := range rc.driverOwnedMemory {
|
||||
for i := range buf {
|
||||
buf[i] = 'x'
|
||||
}
|
||||
}
|
||||
rc.driverOwnedMemory = nil
|
||||
}
|
||||
|
||||
func (rc *rowsCursor) Close() error {
|
||||
rc.touchMem()
|
||||
rc.parentMem.touchMem()
|
||||
rc.invalidateDriverOwnedMemory()
|
||||
rc.closed = true
|
||||
return rc.closeErr
|
||||
}
|
||||
@@ -1129,6 +1131,8 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
|
||||
if rc.posRow >= len(rc.rows[rc.posSet]) {
|
||||
return io.EOF // per interface spec
|
||||
}
|
||||
// Corrupt any previously returned bytes.
|
||||
rc.invalidateDriverOwnedMemory()
|
||||
for i, v := range rc.rows[rc.posSet][rc.posRow].cols {
|
||||
// TODO(bradfitz): convert to subset types? naah, I
|
||||
// think the subset types should only be input to
|
||||
@@ -1136,20 +1140,13 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
|
||||
// a wider range of types coming out of drivers. all
|
||||
// for ease of drivers, and to prevent drivers from
|
||||
// messing up conversions or doing them differently.
|
||||
dest[i] = v
|
||||
|
||||
if bs, ok := v.([]byte); ok && !rc.db.useRawBytes.Load() {
|
||||
if rc.bytesClone == nil {
|
||||
rc.bytesClone = make(map[*byte][]byte)
|
||||
}
|
||||
clone, ok := rc.bytesClone[&bs[0]]
|
||||
if !ok {
|
||||
clone = make([]byte, len(bs))
|
||||
copy(clone, bs)
|
||||
rc.bytesClone[&bs[0]] = clone
|
||||
}
|
||||
dest[i] = clone
|
||||
if bs, ok := v.([]byte); ok {
|
||||
// Clone []bytes and stash for later invalidation.
|
||||
bs = bytes.Clone(bs)
|
||||
rc.driverOwnedMemory = append(rc.driverOwnedMemory, bs)
|
||||
v = bs
|
||||
}
|
||||
dest[i] = v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3368,38 +3368,36 @@ func (rs *Rows) Scan(dest ...any) error {
|
||||
// without calling Next.
|
||||
return fmt.Errorf("sql: Scan called without calling Next (closemuScanHold)")
|
||||
}
|
||||
|
||||
rs.closemu.RLock()
|
||||
|
||||
if rs.lasterr != nil && rs.lasterr != io.EOF {
|
||||
rs.closemu.RUnlock()
|
||||
return rs.lasterr
|
||||
}
|
||||
if rs.closed {
|
||||
err := rs.lasterrOrErrLocked(errRowsClosed)
|
||||
rs.closemu.RUnlock()
|
||||
return err
|
||||
}
|
||||
|
||||
if scanArgsContainRawBytes(dest) {
|
||||
rs.raw = rs.raw[:0]
|
||||
err := rs.scanLocked(dest...)
|
||||
if err == nil && scanArgsContainRawBytes(dest) {
|
||||
rs.closemuScanHold = true
|
||||
rs.raw = rs.raw[:0]
|
||||
} else {
|
||||
rs.closemu.RUnlock()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (rs *Rows) scanLocked(dest ...any) error {
|
||||
if rs.lasterr != nil && rs.lasterr != io.EOF {
|
||||
return rs.lasterr
|
||||
}
|
||||
if rs.closed {
|
||||
return rs.lasterrOrErrLocked(errRowsClosed)
|
||||
}
|
||||
|
||||
if rs.lastcols == nil {
|
||||
rs.closemuRUnlockIfHeldByScan()
|
||||
return errors.New("sql: Scan called without calling Next")
|
||||
}
|
||||
if len(dest) != len(rs.lastcols) {
|
||||
rs.closemuRUnlockIfHeldByScan()
|
||||
return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
|
||||
}
|
||||
|
||||
for i, sv := range rs.lastcols {
|
||||
err := convertAssignRows(dest[i], sv, rs)
|
||||
if err != nil {
|
||||
rs.closemuRUnlockIfHeldByScan()
|
||||
return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
@@ -4446,10 +4447,6 @@ func testContextCancelDuringRawBytesScan(t *testing.T, mode string) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
||||
if _, err := db.Exec("USE_RAWBYTES"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// cancel used to call close asynchronously.
|
||||
// This test checks that it waits so as not to interfere with RawBytes.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -4541,6 +4538,61 @@ func TestContextCancelBetweenNextAndErr(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type testScanner struct {
|
||||
scanf func(src any) error
|
||||
}
|
||||
|
||||
func (ts testScanner) Scan(src any) error { return ts.scanf(src) }
|
||||
|
||||
func TestContextCancelDuringScan(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
scanStart := make(chan any)
|
||||
scanEnd := make(chan error)
|
||||
scanner := &testScanner{
|
||||
scanf: func(src any) error {
|
||||
scanStart <- src
|
||||
return <-scanEnd
|
||||
},
|
||||
}
|
||||
|
||||
// Start a query, and pause it mid-scan.
|
||||
want := []byte("Alice")
|
||||
r, err := db.QueryContext(ctx, "SELECT|people|name|name=?", string(want))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !r.Next() {
|
||||
t.Fatalf("r.Next() = false, want true")
|
||||
}
|
||||
go func() {
|
||||
r.Scan(scanner)
|
||||
}()
|
||||
got := <-scanStart
|
||||
defer close(scanEnd)
|
||||
gotBytes, ok := got.([]byte)
|
||||
if !ok {
|
||||
t.Fatalf("r.Scan returned %T, want []byte", got)
|
||||
}
|
||||
if !bytes.Equal(gotBytes, want) {
|
||||
t.Fatalf("before cancel: r.Scan returned %q, want %q", gotBytes, want)
|
||||
}
|
||||
|
||||
// Cancel the query.
|
||||
// Sleep to give it a chance to finish canceling.
|
||||
cancel()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// Cancelling the query should not have changed the result.
|
||||
if !bytes.Equal(gotBytes, want) {
|
||||
t.Fatalf("after cancel: r.Scan result is now %q, want %q", gotBytes, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNilErrorAfterClose(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
@@ -4574,10 +4626,6 @@ func TestRawBytesReuse(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
||||
if _, err := db.Exec("USE_RAWBYTES"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var raw RawBytes
|
||||
|
||||
// The RawBytes in this query aliases driver-owned memory.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user