mirror of
https://github.com/golang/go
synced 2024-11-23 08:00:05 -07:00
[dev.boringcrypto.go1.16] all: merge go1.16.15 into dev.boringcrypto.go1.16
Change-Id: I574f47761ceb4e224a2a31b5096e27126f171238
This commit is contained in:
commit
649671b08f
@ -249,7 +249,7 @@
|
|||||||
(Leq64F ...) => (FLED ...)
|
(Leq64F ...) => (FLED ...)
|
||||||
(Leq32F ...) => (FLES ...)
|
(Leq32F ...) => (FLES ...)
|
||||||
|
|
||||||
(EqPtr x y) => (SEQZ (SUB <x.Type> x y))
|
(EqPtr x y) => (SEQZ (SUB <typ.Uintptr> x y))
|
||||||
(Eq64 x y) => (SEQZ (SUB <x.Type> x y))
|
(Eq64 x y) => (SEQZ (SUB <x.Type> x y))
|
||||||
(Eq32 x y) => (SEQZ (SUBW <x.Type> x y))
|
(Eq32 x y) => (SEQZ (SUBW <x.Type> x y))
|
||||||
(Eq16 x y) => (SEQZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
|
(Eq16 x y) => (SEQZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
|
||||||
@ -257,7 +257,7 @@
|
|||||||
(Eq64F ...) => (FEQD ...)
|
(Eq64F ...) => (FEQD ...)
|
||||||
(Eq32F ...) => (FEQS ...)
|
(Eq32F ...) => (FEQS ...)
|
||||||
|
|
||||||
(NeqPtr x y) => (SNEZ (SUB <x.Type> x y))
|
(NeqPtr x y) => (SNEZ (SUB <typ.Uintptr> x y))
|
||||||
(Neq64 x y) => (SNEZ (SUB <x.Type> x y))
|
(Neq64 x y) => (SNEZ (SUB <x.Type> x y))
|
||||||
(Neq32 x y) => (SNEZ (SUBW <x.Type> x y))
|
(Neq32 x y) => (SNEZ (SUBW <x.Type> x y))
|
||||||
(Neq16 x y) => (SNEZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
|
(Neq16 x y) => (SNEZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
|
||||||
|
@ -960,13 +960,14 @@ func rewriteValueRISCV64_OpEqPtr(v *Value) bool {
|
|||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
b := v.Block
|
b := v.Block
|
||||||
|
typ := &b.Func.Config.Types
|
||||||
// match: (EqPtr x y)
|
// match: (EqPtr x y)
|
||||||
// result: (SEQZ (SUB <x.Type> x y))
|
// result: (SEQZ (SUB <typ.Uintptr> x y))
|
||||||
for {
|
for {
|
||||||
x := v_0
|
x := v_0
|
||||||
y := v_1
|
y := v_1
|
||||||
v.reset(OpRISCV64SEQZ)
|
v.reset(OpRISCV64SEQZ)
|
||||||
v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
|
v0 := b.NewValue0(v.Pos, OpRISCV64SUB, typ.Uintptr)
|
||||||
v0.AddArg2(x, y)
|
v0.AddArg2(x, y)
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
@ -2519,13 +2520,14 @@ func rewriteValueRISCV64_OpNeqPtr(v *Value) bool {
|
|||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
b := v.Block
|
b := v.Block
|
||||||
|
typ := &b.Func.Config.Types
|
||||||
// match: (NeqPtr x y)
|
// match: (NeqPtr x y)
|
||||||
// result: (SNEZ (SUB <x.Type> x y))
|
// result: (SNEZ (SUB <typ.Uintptr> x y))
|
||||||
for {
|
for {
|
||||||
x := v_0
|
x := v_0
|
||||||
y := v_1
|
y := v_1
|
||||||
v.reset(OpRISCV64SNEZ)
|
v.reset(OpRISCV64SNEZ)
|
||||||
v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
|
v0 := b.NewValue0(v.Pos, OpRISCV64SUB, typ.Uintptr)
|
||||||
v0.AddArg2(x, y)
|
v0.AddArg2(x, y)
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
|
@ -305,17 +305,46 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
|||||||
//
|
//
|
||||||
// (If the version is +incompatible, then the go.mod file must not exist:
|
// (If the version is +incompatible, then the go.mod file must not exist:
|
||||||
// +incompatible is not an ongoing opt-out from semantic import versioning.)
|
// +incompatible is not an ongoing opt-out from semantic import versioning.)
|
||||||
var canUseIncompatible func() bool
|
incompatibleOk := map[string]bool{}
|
||||||
canUseIncompatible = func() bool {
|
canUseIncompatible := func(v string) bool {
|
||||||
var ok bool
|
if r.codeDir != "" || r.pathMajor != "" {
|
||||||
if r.codeDir == "" && r.pathMajor == "" {
|
// A non-empty codeDir indicates a module within a subdirectory,
|
||||||
|
// which necessarily has a go.mod file indicating the module boundary.
|
||||||
|
// A non-empty pathMajor indicates a module path with a major-version
|
||||||
|
// suffix, which must match.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
ok, seen := incompatibleOk[""]
|
||||||
|
if !seen {
|
||||||
_, errGoMod := r.code.ReadFile(info.Name, "go.mod", codehost.MaxGoMod)
|
_, errGoMod := r.code.ReadFile(info.Name, "go.mod", codehost.MaxGoMod)
|
||||||
if errGoMod != nil {
|
ok = (errGoMod != nil)
|
||||||
ok = true
|
incompatibleOk[""] = ok
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
// A go.mod file exists at the repo root.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per https://go.dev/issue/51324, previous versions of the 'go' command
|
||||||
|
// didn't always check for go.mod files in subdirectories, so if the user
|
||||||
|
// requests a +incompatible version explicitly, we should continue to allow
|
||||||
|
// it. Otherwise, if vN/go.mod exists, expect that release tags for that
|
||||||
|
// major version are intended for the vN module.
|
||||||
|
if v != "" && !strings.HasSuffix(statVers, "+incompatible") {
|
||||||
|
major := semver.Major(v)
|
||||||
|
ok, seen = incompatibleOk[major]
|
||||||
|
if !seen {
|
||||||
|
_, errGoModSub := r.code.ReadFile(info.Name, path.Join(major, "go.mod"), codehost.MaxGoMod)
|
||||||
|
ok = (errGoModSub != nil)
|
||||||
|
incompatibleOk[major] = ok
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
canUseIncompatible = func() bool { return ok }
|
|
||||||
return ok
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkCanonical verifies that the canonical version v is compatible with the
|
// checkCanonical verifies that the canonical version v is compatible with the
|
||||||
@ -367,7 +396,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
|||||||
base := strings.TrimSuffix(v, "+incompatible")
|
base := strings.TrimSuffix(v, "+incompatible")
|
||||||
var errIncompatible error
|
var errIncompatible error
|
||||||
if !module.MatchPathMajor(base, r.pathMajor) {
|
if !module.MatchPathMajor(base, r.pathMajor) {
|
||||||
if canUseIncompatible() {
|
if canUseIncompatible(base) {
|
||||||
v = base + "+incompatible"
|
v = base + "+incompatible"
|
||||||
} else {
|
} else {
|
||||||
if r.pathMajor != "" {
|
if r.pathMajor != "" {
|
||||||
@ -495,7 +524,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
|||||||
// Save the highest non-retracted canonical tag for the revision.
|
// Save the highest non-retracted canonical tag for the revision.
|
||||||
// If we don't find a better match, we'll use it as the canonical version.
|
// If we don't find a better match, we'll use it as the canonical version.
|
||||||
if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) {
|
if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) {
|
||||||
if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible() {
|
if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible(v) {
|
||||||
highestCanonical = v
|
highestCanonical = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,12 +542,12 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
|||||||
// retracted versions.
|
// retracted versions.
|
||||||
allowedMajor := func(major string) func(v string) bool {
|
allowedMajor := func(major string) func(v string) bool {
|
||||||
return func(v string) bool {
|
return func(v string) bool {
|
||||||
return (major == "" || semver.Major(v) == major) && !isRetracted(v)
|
return ((major == "" && canUseIncompatible(v)) || semver.Major(v) == major) && !isRetracted(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pseudoBase == "" {
|
if pseudoBase == "" {
|
||||||
var tag string
|
var tag string
|
||||||
if r.pseudoMajor != "" || canUseIncompatible() {
|
if r.pseudoMajor != "" || canUseIncompatible("") {
|
||||||
tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor(r.pseudoMajor))
|
tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor(r.pseudoMajor))
|
||||||
} else {
|
} else {
|
||||||
// Allow either v1 or v0, but not incompatible higher versions.
|
// Allow either v1 or v0, but not incompatible higher versions.
|
||||||
|
@ -458,6 +458,54 @@ var codeRepoTests = []codeRepoTest{
|
|||||||
rev: "v3.0.0-devel",
|
rev: "v3.0.0-devel",
|
||||||
err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`,
|
err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// If v2/go.mod exists, then we should prefer to match the "v2"
|
||||||
|
// pseudo-versions to the nested module, and resolve the module in the parent
|
||||||
|
// directory to only compatible versions.
|
||||||
|
//
|
||||||
|
// However (https://go.dev/issue/51324), previous versions of the 'go' command
|
||||||
|
// didn't always do so, so if the user explicitly requests a +incompatible
|
||||||
|
// version (as would be present in an existing go.mod file), we should
|
||||||
|
// continue to allow it.
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "vcs-test.golang.org/git/v2sub.git",
|
||||||
|
rev: "80beb17a1603",
|
||||||
|
version: "v0.0.0-20220222205507-80beb17a1603",
|
||||||
|
name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
|
||||||
|
short: "80beb17a1603",
|
||||||
|
time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "vcs-test.golang.org/git/v2sub.git",
|
||||||
|
rev: "v2.0.0",
|
||||||
|
err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "vcs-test.golang.org/git/v2sub.git",
|
||||||
|
rev: "v2.0.1-0.20220222205507-80beb17a1603",
|
||||||
|
err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "vcs-test.golang.org/git/v2sub.git",
|
||||||
|
rev: "v2.0.0+incompatible",
|
||||||
|
version: "v2.0.0+incompatible",
|
||||||
|
name: "5fcd3eaeeb391d399f562fd45a50dac9fc34ae8b",
|
||||||
|
short: "5fcd3eaeeb39",
|
||||||
|
time: time.Date(2022, 2, 22, 20, 53, 33, 0, time.UTC),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "vcs-test.golang.org/git/v2sub.git",
|
||||||
|
rev: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
|
||||||
|
version: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
|
||||||
|
name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
|
||||||
|
short: "80beb17a1603",
|
||||||
|
time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCodeRepo(t *testing.T) {
|
func TestCodeRepo(t *testing.T) {
|
||||||
|
@ -29,6 +29,10 @@ const (
|
|||||||
// to be used as a useTCP parameter to exchange
|
// to be used as a useTCP parameter to exchange
|
||||||
useTCPOnly = true
|
useTCPOnly = true
|
||||||
useUDPOrTCP = false
|
useUDPOrTCP = false
|
||||||
|
|
||||||
|
// Maximum DNS packet size.
|
||||||
|
// Value taken from https://dnsflagday.net/2020/.
|
||||||
|
maxDNSPacketSize = 1232
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -81,7 +85,7 @@ func dnsPacketRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte)
|
|||||||
return dnsmessage.Parser{}, dnsmessage.Header{}, err
|
return dnsmessage.Parser{}, dnsmessage.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b = make([]byte, 512) // see RFC 1035
|
b = make([]byte, maxDNSPacketSize)
|
||||||
for {
|
for {
|
||||||
n, err := c.Read(b)
|
n, err := c.Read(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -881,7 +881,7 @@ func (f *fakeDNSPacketConn) Close() error {
|
|||||||
func TestIgnoreDNSForgeries(t *testing.T) {
|
func TestIgnoreDNSForgeries(t *testing.T) {
|
||||||
c, s := Pipe()
|
c, s := Pipe()
|
||||||
go func() {
|
go func() {
|
||||||
b := make([]byte, 512)
|
b := make([]byte, maxDNSPacketSize)
|
||||||
n, err := s.Read(b)
|
n, err := s.Read(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -76,13 +76,29 @@ const (
|
|||||||
opVerticalBar
|
opVerticalBar
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// maxHeight is the maximum height of a regexp parse tree.
|
||||||
|
// It is somewhat arbitrarily chosen, but the idea is to be large enough
|
||||||
|
// that no one will actually hit in real use but at the same time small enough
|
||||||
|
// that recursion on the Regexp tree will not hit the 1GB Go stack limit.
|
||||||
|
// The maximum amount of stack for a single recursive frame is probably
|
||||||
|
// closer to 1kB, so this could potentially be raised, but it seems unlikely
|
||||||
|
// that people have regexps nested even this deeply.
|
||||||
|
// We ran a test on Google's C++ code base and turned up only
|
||||||
|
// a single use case with depth > 100; it had depth 128.
|
||||||
|
// Using depth 1000 should be plenty of margin.
|
||||||
|
// As an optimization, we don't even bother calculating heights
|
||||||
|
// until we've allocated at least maxHeight Regexp structures.
|
||||||
|
const maxHeight = 1000
|
||||||
|
|
||||||
type parser struct {
|
type parser struct {
|
||||||
flags Flags // parse mode flags
|
flags Flags // parse mode flags
|
||||||
stack []*Regexp // stack of parsed expressions
|
stack []*Regexp // stack of parsed expressions
|
||||||
free *Regexp
|
free *Regexp
|
||||||
numCap int // number of capturing groups seen
|
numCap int // number of capturing groups seen
|
||||||
wholeRegexp string
|
wholeRegexp string
|
||||||
tmpClass []rune // temporary char class work space
|
tmpClass []rune // temporary char class work space
|
||||||
|
numRegexp int // number of regexps allocated
|
||||||
|
height map[*Regexp]int // regexp height for height limit check
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) newRegexp(op Op) *Regexp {
|
func (p *parser) newRegexp(op Op) *Regexp {
|
||||||
@ -92,16 +108,52 @@ func (p *parser) newRegexp(op Op) *Regexp {
|
|||||||
*re = Regexp{}
|
*re = Regexp{}
|
||||||
} else {
|
} else {
|
||||||
re = new(Regexp)
|
re = new(Regexp)
|
||||||
|
p.numRegexp++
|
||||||
}
|
}
|
||||||
re.Op = op
|
re.Op = op
|
||||||
return re
|
return re
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) reuse(re *Regexp) {
|
func (p *parser) reuse(re *Regexp) {
|
||||||
|
if p.height != nil {
|
||||||
|
delete(p.height, re)
|
||||||
|
}
|
||||||
re.Sub0[0] = p.free
|
re.Sub0[0] = p.free
|
||||||
p.free = re
|
p.free = re
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *parser) checkHeight(re *Regexp) {
|
||||||
|
if p.numRegexp < maxHeight {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if p.height == nil {
|
||||||
|
p.height = make(map[*Regexp]int)
|
||||||
|
for _, re := range p.stack {
|
||||||
|
p.checkHeight(re)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.calcHeight(re, true) > maxHeight {
|
||||||
|
panic(ErrInternalError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) calcHeight(re *Regexp, force bool) int {
|
||||||
|
if !force {
|
||||||
|
if h, ok := p.height[re]; ok {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h := 1
|
||||||
|
for _, sub := range re.Sub {
|
||||||
|
hsub := p.calcHeight(sub, false)
|
||||||
|
if h < 1+hsub {
|
||||||
|
h = 1 + hsub
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.height[re] = h
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
// Parse stack manipulation.
|
// Parse stack manipulation.
|
||||||
|
|
||||||
// push pushes the regexp re onto the parse stack and returns the regexp.
|
// push pushes the regexp re onto the parse stack and returns the regexp.
|
||||||
@ -137,6 +189,7 @@ func (p *parser) push(re *Regexp) *Regexp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.stack = append(p.stack, re)
|
p.stack = append(p.stack, re)
|
||||||
|
p.checkHeight(re)
|
||||||
return re
|
return re
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,6 +299,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (
|
|||||||
re.Sub = re.Sub0[:1]
|
re.Sub = re.Sub0[:1]
|
||||||
re.Sub[0] = sub
|
re.Sub[0] = sub
|
||||||
p.stack[n-1] = re
|
p.stack[n-1] = re
|
||||||
|
p.checkHeight(re)
|
||||||
|
|
||||||
if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
|
if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
|
||||||
return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
|
return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
|
||||||
@ -693,6 +747,21 @@ func literalRegexp(s string, flags Flags) *Regexp {
|
|||||||
// Flags, and returns a regular expression parse tree. The syntax is
|
// Flags, and returns a regular expression parse tree. The syntax is
|
||||||
// described in the top-level comment.
|
// described in the top-level comment.
|
||||||
func Parse(s string, flags Flags) (*Regexp, error) {
|
func Parse(s string, flags Flags) (*Regexp, error) {
|
||||||
|
return parse(s, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse(s string, flags Flags) (_ *Regexp, err error) {
|
||||||
|
defer func() {
|
||||||
|
switch r := recover(); r {
|
||||||
|
default:
|
||||||
|
panic(r)
|
||||||
|
case nil:
|
||||||
|
// ok
|
||||||
|
case ErrInternalError:
|
||||||
|
err = &Error{Code: ErrInternalError, Expr: s}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if flags&Literal != 0 {
|
if flags&Literal != 0 {
|
||||||
// Trivial parser for literal string.
|
// Trivial parser for literal string.
|
||||||
if err := checkUTF8(s); err != nil {
|
if err := checkUTF8(s); err != nil {
|
||||||
@ -704,7 +773,6 @@ func Parse(s string, flags Flags) (*Regexp, error) {
|
|||||||
// Otherwise, must do real work.
|
// Otherwise, must do real work.
|
||||||
var (
|
var (
|
||||||
p parser
|
p parser
|
||||||
err error
|
|
||||||
c rune
|
c rune
|
||||||
op Op
|
op Op
|
||||||
lastRepeat string
|
lastRepeat string
|
||||||
|
@ -207,6 +207,11 @@ var parseTests = []parseTest{
|
|||||||
// Valid repetitions.
|
// Valid repetitions.
|
||||||
{`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``},
|
{`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``},
|
||||||
{`((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})`, ``},
|
{`((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})`, ``},
|
||||||
|
|
||||||
|
// Valid nesting.
|
||||||
|
{strings.Repeat("(", 999) + strings.Repeat(")", 999), ``},
|
||||||
|
{strings.Repeat("(?:", 999) + strings.Repeat(")*", 999), ``},
|
||||||
|
{"(" + strings.Repeat("|", 12345) + ")", ``}, // not nested at all
|
||||||
}
|
}
|
||||||
|
|
||||||
const testFlags = MatchNL | PerlX | UnicodeGroups
|
const testFlags = MatchNL | PerlX | UnicodeGroups
|
||||||
@ -482,6 +487,8 @@ var invalidRegexps = []string{
|
|||||||
`a{100000}`,
|
`a{100000}`,
|
||||||
`a{100000,}`,
|
`a{100000,}`,
|
||||||
"((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
|
"((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
|
||||||
|
strings.Repeat("(", 1000) + strings.Repeat(")", 1000),
|
||||||
|
strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000),
|
||||||
`\Q\E*`,
|
`\Q\E*`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,3 +1226,5 @@ func (th *TimeHistogram) Count(bucket, subBucket uint) (uint64, bool) {
|
|||||||
func (th *TimeHistogram) Record(duration int64) {
|
func (th *TimeHistogram) Record(duration int64) {
|
||||||
(*timeHistogram)(th).record(duration)
|
(*timeHistogram)(th).record(duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var TimeHistogramMetricsBuckets = timeHistogramMetricsBuckets
|
||||||
|
@ -47,7 +47,7 @@ const (
|
|||||||
// │ └---- Next 4 bits -> sub-bucket 1
|
// │ └---- Next 4 bits -> sub-bucket 1
|
||||||
// └------- Bit 5 set -> super-bucket 2
|
// └------- Bit 5 set -> super-bucket 2
|
||||||
//
|
//
|
||||||
// Following this pattern, bucket 45 will have the bit 48 set. We don't
|
// Following this pattern, super-bucket 44 will have the bit 47 set. We don't
|
||||||
// have any buckets for higher values, so the highest sub-bucket will
|
// have any buckets for higher values, so the highest sub-bucket will
|
||||||
// contain values of 2^48-1 nanoseconds or approx. 3 days. This range is
|
// contain values of 2^48-1 nanoseconds or approx. 3 days. This range is
|
||||||
// more than enough to handle durations produced by the runtime.
|
// more than enough to handle durations produced by the runtime.
|
||||||
@ -135,36 +135,30 @@ func float64NegInf() float64 {
|
|||||||
func timeHistogramMetricsBuckets() []float64 {
|
func timeHistogramMetricsBuckets() []float64 {
|
||||||
b := make([]float64, timeHistTotalBuckets+1)
|
b := make([]float64, timeHistTotalBuckets+1)
|
||||||
b[0] = float64NegInf()
|
b[0] = float64NegInf()
|
||||||
for i := 0; i < timeHistNumSuperBuckets; i++ {
|
// Super-bucket 0 has no bits above timeHistSubBucketBits
|
||||||
superBucketMin := uint64(0)
|
// set, so just iterate over each bucket and assign the
|
||||||
// The (inclusive) minimum for the first non-negative bucket is 0.
|
// incrementing bucket.
|
||||||
if i > 0 {
|
for i := 0; i < timeHistNumSubBuckets; i++ {
|
||||||
// The minimum for the second bucket will be
|
bucketNanos := uint64(i)
|
||||||
// 1 << timeHistSubBucketBits, indicating that all
|
b[i+1] = float64(bucketNanos) / 1e9
|
||||||
// sub-buckets are represented by the next timeHistSubBucketBits
|
}
|
||||||
// bits.
|
// Generate the rest of the super-buckets. It's easier to reason
|
||||||
// Thereafter, we shift up by 1 each time, so we can represent
|
// about if we cut out the 0'th bucket, so subtract one since
|
||||||
// this pattern as (i-1)+timeHistSubBucketBits.
|
// we just handled that bucket.
|
||||||
superBucketMin = uint64(1) << uint(i-1+timeHistSubBucketBits)
|
for i := 0; i < timeHistNumSuperBuckets-1; i++ {
|
||||||
}
|
|
||||||
// subBucketShift is the amount that we need to shift the sub-bucket
|
|
||||||
// index to combine it with the bucketMin.
|
|
||||||
subBucketShift := uint(0)
|
|
||||||
if i > 1 {
|
|
||||||
// The first two super buckets are exact with respect to integers,
|
|
||||||
// so we'll never have to shift the sub-bucket index. Thereafter,
|
|
||||||
// we shift up by 1 with each subsequent bucket.
|
|
||||||
subBucketShift = uint(i - 2)
|
|
||||||
}
|
|
||||||
for j := 0; j < timeHistNumSubBuckets; j++ {
|
for j := 0; j < timeHistNumSubBuckets; j++ {
|
||||||
// j is the sub-bucket index. By shifting the index into position to
|
// Set the super-bucket bit.
|
||||||
// combine with the bucket minimum, we obtain the minimum value for that
|
bucketNanos := uint64(1) << (i + timeHistSubBucketBits)
|
||||||
// sub-bucket.
|
// Set the sub-bucket bits.
|
||||||
subBucketMin := superBucketMin + (uint64(j) << subBucketShift)
|
bucketNanos |= uint64(j) << i
|
||||||
|
// The index for this bucket is going to be the (i+1)'th super bucket
|
||||||
// Convert the subBucketMin which is in nanoseconds to a float64 seconds value.
|
// (note that we're starting from zero, but handled the first super-bucket
|
||||||
|
// earlier, so we need to compensate), and the j'th sub bucket.
|
||||||
|
// Add 1 because we left space for -Inf.
|
||||||
|
bucketIndex := (i+1)*timeHistNumSubBuckets + j + 1
|
||||||
|
// Convert nanoseconds to seconds via a division.
|
||||||
// These values will all be exactly representable by a float64.
|
// These values will all be exactly representable by a float64.
|
||||||
b[i*timeHistNumSubBuckets+j+1] = float64(subBucketMin) / 1e9
|
b[bucketIndex] = float64(bucketNanos) / 1e9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b[len(b)-1] = float64Inf()
|
b[len(b)-1] = float64Inf()
|
||||||
|
@ -68,3 +68,43 @@ func TestTimeHistogram(t *testing.T) {
|
|||||||
|
|
||||||
dummyTimeHistogram = TimeHistogram{}
|
dummyTimeHistogram = TimeHistogram{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTimeHistogramMetricsBuckets(t *testing.T) {
|
||||||
|
buckets := TimeHistogramMetricsBuckets()
|
||||||
|
|
||||||
|
nonInfBucketsLen := TimeHistNumSubBuckets * TimeHistNumSuperBuckets
|
||||||
|
expBucketsLen := nonInfBucketsLen + 2 // Count -Inf and +Inf.
|
||||||
|
if len(buckets) != expBucketsLen {
|
||||||
|
t.Fatalf("unexpected length of buckets: got %d, want %d", len(buckets), expBucketsLen)
|
||||||
|
}
|
||||||
|
// Check the first non-Inf 2*TimeHistNumSubBuckets buckets in order, skipping the
|
||||||
|
// first bucket which should be -Inf (checked later).
|
||||||
|
//
|
||||||
|
// Because of the way this scheme works, the bottom TimeHistNumSubBuckets
|
||||||
|
// buckets are fully populated, and then the next TimeHistNumSubBuckets
|
||||||
|
// have the TimeHistSubBucketBits'th bit set, while the bottom are once
|
||||||
|
// again fully populated.
|
||||||
|
for i := 1; i <= 2*TimeHistNumSubBuckets+1; i++ {
|
||||||
|
if got, want := buckets[i], float64(i-1)/1e9; got != want {
|
||||||
|
t.Errorf("expected bucket %d to have value %e, got %e", i, want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check some values.
|
||||||
|
idxToBucket := map[int]float64{
|
||||||
|
0: math.Inf(-1),
|
||||||
|
33: float64(0x10<<1) / 1e9,
|
||||||
|
34: float64(0x11<<1) / 1e9,
|
||||||
|
49: float64(0x10<<2) / 1e9,
|
||||||
|
58: float64(0x19<<2) / 1e9,
|
||||||
|
65: float64(0x10<<3) / 1e9,
|
||||||
|
513: float64(0x10<<31) / 1e9,
|
||||||
|
519: float64(0x16<<31) / 1e9,
|
||||||
|
expBucketsLen - 2: float64(0x1f<<43) / 1e9,
|
||||||
|
expBucketsLen - 1: math.Inf(1),
|
||||||
|
}
|
||||||
|
for idx, bucket := range idxToBucket {
|
||||||
|
if got, want := buckets[idx], bucket; got != want {
|
||||||
|
t.Errorf("expected bucket %d to have value %e, got %e", idx, want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
36
test/fixedbugs/issue51101.go
Normal file
36
test/fixedbugs/issue51101.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// run
|
||||||
|
|
||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Issue 51101: on RISCV64, difference of two pointers
|
||||||
|
// was marked as pointer and crashes GC.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
var a, b int
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
F(&b, &a)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func F(a, b *int) bool {
|
||||||
|
x := a == b
|
||||||
|
G(x)
|
||||||
|
y := a != b
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func G(bool) {
|
||||||
|
grow([1000]int{20})
|
||||||
|
}
|
||||||
|
|
||||||
|
func grow(x [1000]int) {
|
||||||
|
if x[0] != 0 {
|
||||||
|
x[0]--
|
||||||
|
grow(x)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user