mirror of https://github.com/golang/go.git
[dev.boringcrypto.go1.17] all: merge go1.17.7 into dev.boringcrypto.go1.17
Change-Id: I6abebb215a38b5df450ef12281266bef6c8e76eb
This commit is contained in:
commit
172559d22b
|
|
@ -293,3 +293,31 @@ func TestIssue44956(t *testing.T) {
|
|||
goCmd(t, "build", "-o", "issue44956.exe", "./issue44956/main.go")
|
||||
run(t, "./issue44956.exe")
|
||||
}
|
||||
|
||||
func TestForkExec(t *testing.T) {
|
||||
// Issue 38824: importing the plugin package causes it hang in forkExec on darwin.
|
||||
|
||||
t.Parallel()
|
||||
goCmd(t, "build", "-o", "forkexec.exe", "./forkexec/main.go")
|
||||
|
||||
var cmd *exec.Cmd
|
||||
done := make(chan int, 1)
|
||||
|
||||
go func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
cmd = exec.Command("./forkexec.exe", "1")
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
t.Errorf("running command failed: %v", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
done <- 1
|
||||
}()
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(5 * time.Minute):
|
||||
cmd.Process.Kill()
|
||||
t.Fatalf("subprocess hang")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2021 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 (
|
||||
"os"
|
||||
"os/exec"
|
||||
_ "plugin"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if os.Args[1] != "1" {
|
||||
return
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 8; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
// does not matter what we exec, just exec itself
|
||||
cmd := exec.Command("./forkexec.exe", "0")
|
||||
cmd.Run()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
|
@ -320,7 +320,10 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
|||
for a.Op == ssa.OpCopy || a.Op == ssa.OpMIPS64MOVVreg {
|
||||
a = a.Args[0]
|
||||
}
|
||||
if a.Op == ssa.OpLoadReg {
|
||||
if a.Op == ssa.OpLoadReg && mips.REG_R0 <= a.Reg() && a.Reg() <= mips.REG_R31 {
|
||||
// LoadReg from a narrower type does an extension, except loading
|
||||
// to a floating point register. So only eliminate the extension
|
||||
// if it is loaded to an integer register.
|
||||
t := a.Type
|
||||
switch {
|
||||
case v.Op == ssa.OpMIPS64MOVBreg && t.Size() == 1 && t.IsSigned(),
|
||||
|
|
|
|||
|
|
@ -1268,8 +1268,8 @@
|
|||
(SRLconst (SLLconst x [c]) [d]) && buildcfg.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31 => (BFXU [(d-c)|(32-d)<<8] x)
|
||||
|
||||
// comparison simplification
|
||||
((LT|LE|EQ|NE|GE|GT) (CMP x (RSBconst [0] y))) => ((LT|LE|EQ|NE|GE|GT) (CMN x y)) // sense of carry bit not preserved
|
||||
((LT|LE|EQ|NE|GE|GT) (CMN x (RSBconst [0] y))) => ((LT|LE|EQ|NE|GE|GT) (CMP x y)) // sense of carry bit not preserved
|
||||
((EQ|NE) (CMP x (RSBconst [0] y))) => ((EQ|NE) (CMN x y)) // sense of carry bit not preserved; see also #50854
|
||||
((EQ|NE) (CMN x (RSBconst [0] y))) => ((EQ|NE) (CMP x y)) // sense of carry bit not preserved; see also #50864
|
||||
(EQ (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (EQ (CMP x y) yes no)
|
||||
(EQ (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (EQ (CMP a (MUL <x.Type> x y)) yes no)
|
||||
(EQ (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (EQ (CMPconst [c] x) yes no)
|
||||
|
|
|
|||
|
|
@ -645,19 +645,13 @@
|
|||
(GT (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GTnoov (CMNW x y) yes no)
|
||||
(GE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 => (GEnoov (CMNW x y) yes no)
|
||||
|
||||
// CMP(x,-y) -> CMN(x,y) is only valid for unordered comparison, if y can be -1<<63
|
||||
(EQ (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMN x y) yes no)
|
||||
(NE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMN x y) yes no)
|
||||
(LT (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (LT (CMN x y) yes no)
|
||||
(LE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (LE (CMN x y) yes no)
|
||||
(GT (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (GT (CMN x y) yes no)
|
||||
(GE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (GE (CMN x y) yes no)
|
||||
|
||||
// CMPW(x,-y) -> CMNW(x,y) is only valid for unordered comparison, if y can be -1<<31
|
||||
(EQ (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMNW x y) yes no)
|
||||
(NE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMNW x y) yes no)
|
||||
(LT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (LT (CMNW x y) yes no)
|
||||
(LE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (LE (CMNW x y) yes no)
|
||||
(GT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (GT (CMNW x y) yes no)
|
||||
(GE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (GE (CMNW x y) yes no)
|
||||
|
||||
(EQ (CMPconst [0] x) yes no) => (Z x yes no)
|
||||
(NE (CMPconst [0] x) yes no) => (NZ x yes no)
|
||||
|
|
|
|||
|
|
@ -284,9 +284,9 @@ func init() {
|
|||
{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to auxInt
|
||||
{name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1, 32 bit
|
||||
{name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt, 32 bit
|
||||
{name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1
|
||||
{name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1, provided arg1 is not 1<<63
|
||||
{name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // arg0 compare to -auxInt
|
||||
{name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags", commutative: true}, // arg0 compare to -arg1, 32 bit
|
||||
{name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags", commutative: true}, // arg0 compare to -arg1, 32 bit, provided arg1 is not 1<<31
|
||||
{name: "CMNWconst", argLength: 1, reg: gp1flags, asm: "CMNW", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt, 32 bit
|
||||
{name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0
|
||||
{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int64", typ: "Flags"}, // arg0 & auxInt compare to 0
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ func init() {
|
|||
// comparisons
|
||||
{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
|
||||
{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt
|
||||
{name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1
|
||||
{name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1, provided arg1 is not 1<<63
|
||||
{name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt
|
||||
{name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0
|
||||
{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0
|
||||
|
|
|
|||
|
|
@ -17143,42 +17143,6 @@ func rewriteBlockARM(b *Block) bool {
|
|||
b.resetWithControl(BlockARMLE, cmp)
|
||||
return true
|
||||
}
|
||||
// match: (GE (CMP x (RSBconst [0] y)))
|
||||
// result: (GE (CMN x y))
|
||||
for b.Controls[0].Op == OpARMCMP {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
v_0_1 := v_0.Args[1]
|
||||
if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
|
||||
break
|
||||
}
|
||||
y := v_0_1.Args[0]
|
||||
v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARMGE, v0)
|
||||
return true
|
||||
}
|
||||
// match: (GE (CMN x (RSBconst [0] y)))
|
||||
// result: (GE (CMP x y))
|
||||
for b.Controls[0].Op == OpARMCMN {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
v_0_0 := v_0.Args[0]
|
||||
v_0_1 := v_0.Args[1]
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
|
||||
x := v_0_0
|
||||
if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
|
||||
continue
|
||||
}
|
||||
y := v_0_1.Args[0]
|
||||
v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARMGE, v0)
|
||||
return true
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (GE (CMPconst [0] l:(SUB x y)) yes no)
|
||||
// cond: l.Uses==1
|
||||
// result: (GEnoov (CMP x y) yes no)
|
||||
|
|
@ -18059,42 +18023,6 @@ func rewriteBlockARM(b *Block) bool {
|
|||
b.resetWithControl(BlockARMLT, cmp)
|
||||
return true
|
||||
}
|
||||
// match: (GT (CMP x (RSBconst [0] y)))
|
||||
// result: (GT (CMN x y))
|
||||
for b.Controls[0].Op == OpARMCMP {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
v_0_1 := v_0.Args[1]
|
||||
if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
|
||||
break
|
||||
}
|
||||
y := v_0_1.Args[0]
|
||||
v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARMGT, v0)
|
||||
return true
|
||||
}
|
||||
// match: (GT (CMN x (RSBconst [0] y)))
|
||||
// result: (GT (CMP x y))
|
||||
for b.Controls[0].Op == OpARMCMN {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
v_0_0 := v_0.Args[0]
|
||||
v_0_1 := v_0.Args[1]
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
|
||||
x := v_0_0
|
||||
if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
|
||||
continue
|
||||
}
|
||||
y := v_0_1.Args[0]
|
||||
v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARMGT, v0)
|
||||
return true
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (GT (CMPconst [0] l:(SUB x y)) yes no)
|
||||
// cond: l.Uses==1
|
||||
// result: (GTnoov (CMP x y) yes no)
|
||||
|
|
@ -19066,42 +18994,6 @@ func rewriteBlockARM(b *Block) bool {
|
|||
b.resetWithControl(BlockARMGE, cmp)
|
||||
return true
|
||||
}
|
||||
// match: (LE (CMP x (RSBconst [0] y)))
|
||||
// result: (LE (CMN x y))
|
||||
for b.Controls[0].Op == OpARMCMP {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
v_0_1 := v_0.Args[1]
|
||||
if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
|
||||
break
|
||||
}
|
||||
y := v_0_1.Args[0]
|
||||
v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARMLE, v0)
|
||||
return true
|
||||
}
|
||||
// match: (LE (CMN x (RSBconst [0] y)))
|
||||
// result: (LE (CMP x y))
|
||||
for b.Controls[0].Op == OpARMCMN {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
v_0_0 := v_0.Args[0]
|
||||
v_0_1 := v_0.Args[1]
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
|
||||
x := v_0_0
|
||||
if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
|
||||
continue
|
||||
}
|
||||
y := v_0_1.Args[0]
|
||||
v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARMLE, v0)
|
||||
return true
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (LE (CMPconst [0] l:(SUB x y)) yes no)
|
||||
// cond: l.Uses==1
|
||||
// result: (LEnoov (CMP x y) yes no)
|
||||
|
|
@ -19982,42 +19874,6 @@ func rewriteBlockARM(b *Block) bool {
|
|||
b.resetWithControl(BlockARMGT, cmp)
|
||||
return true
|
||||
}
|
||||
// match: (LT (CMP x (RSBconst [0] y)))
|
||||
// result: (LT (CMN x y))
|
||||
for b.Controls[0].Op == OpARMCMP {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
v_0_1 := v_0.Args[1]
|
||||
if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
|
||||
break
|
||||
}
|
||||
y := v_0_1.Args[0]
|
||||
v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARMLT, v0)
|
||||
return true
|
||||
}
|
||||
// match: (LT (CMN x (RSBconst [0] y)))
|
||||
// result: (LT (CMP x y))
|
||||
for b.Controls[0].Op == OpARMCMN {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
v_0_0 := v_0.Args[0]
|
||||
v_0_1 := v_0.Args[1]
|
||||
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
|
||||
x := v_0_0
|
||||
if v_0_1.Op != OpARMRSBconst || auxIntToInt32(v_0_1.AuxInt) != 0 {
|
||||
continue
|
||||
}
|
||||
y := v_0_1.Args[0]
|
||||
v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARMLT, v0)
|
||||
return true
|
||||
}
|
||||
break
|
||||
}
|
||||
// match: (LT (CMPconst [0] l:(SUB x y)) yes no)
|
||||
// cond: l.Uses==1
|
||||
// result: (LTnoov (CMP x y) yes no)
|
||||
|
|
|
|||
|
|
@ -27205,46 +27205,6 @@ func rewriteBlockARM64(b *Block) bool {
|
|||
}
|
||||
break
|
||||
}
|
||||
// match: (GE (CMP x z:(NEG y)) yes no)
|
||||
// cond: z.Uses == 1
|
||||
// result: (GE (CMN x y) yes no)
|
||||
for b.Controls[0].Op == OpARM64CMP {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
z := v_0.Args[1]
|
||||
if z.Op != OpARM64NEG {
|
||||
break
|
||||
}
|
||||
y := z.Args[0]
|
||||
if !(z.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARM64GE, v0)
|
||||
return true
|
||||
}
|
||||
// match: (GE (CMPW x z:(NEG y)) yes no)
|
||||
// cond: z.Uses == 1
|
||||
// result: (GE (CMNW x y) yes no)
|
||||
for b.Controls[0].Op == OpARM64CMPW {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
z := v_0.Args[1]
|
||||
if z.Op != OpARM64NEG {
|
||||
break
|
||||
}
|
||||
y := z.Args[0]
|
||||
if !(z.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARM64GE, v0)
|
||||
return true
|
||||
}
|
||||
// match: (GE (CMPconst [0] z:(MADD a x y)) yes no)
|
||||
// cond: z.Uses==1
|
||||
// result: (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
|
||||
|
|
@ -27641,46 +27601,6 @@ func rewriteBlockARM64(b *Block) bool {
|
|||
}
|
||||
break
|
||||
}
|
||||
// match: (GT (CMP x z:(NEG y)) yes no)
|
||||
// cond: z.Uses == 1
|
||||
// result: (GT (CMN x y) yes no)
|
||||
for b.Controls[0].Op == OpARM64CMP {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
z := v_0.Args[1]
|
||||
if z.Op != OpARM64NEG {
|
||||
break
|
||||
}
|
||||
y := z.Args[0]
|
||||
if !(z.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARM64GT, v0)
|
||||
return true
|
||||
}
|
||||
// match: (GT (CMPW x z:(NEG y)) yes no)
|
||||
// cond: z.Uses == 1
|
||||
// result: (GT (CMNW x y) yes no)
|
||||
for b.Controls[0].Op == OpARM64CMPW {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
z := v_0.Args[1]
|
||||
if z.Op != OpARM64NEG {
|
||||
break
|
||||
}
|
||||
y := z.Args[0]
|
||||
if !(z.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARM64GT, v0)
|
||||
return true
|
||||
}
|
||||
// match: (GT (CMPconst [0] z:(MADD a x y)) yes no)
|
||||
// cond: z.Uses==1
|
||||
// result: (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
|
||||
|
|
@ -28173,46 +28093,6 @@ func rewriteBlockARM64(b *Block) bool {
|
|||
}
|
||||
break
|
||||
}
|
||||
// match: (LE (CMP x z:(NEG y)) yes no)
|
||||
// cond: z.Uses == 1
|
||||
// result: (LE (CMN x y) yes no)
|
||||
for b.Controls[0].Op == OpARM64CMP {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
z := v_0.Args[1]
|
||||
if z.Op != OpARM64NEG {
|
||||
break
|
||||
}
|
||||
y := z.Args[0]
|
||||
if !(z.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARM64LE, v0)
|
||||
return true
|
||||
}
|
||||
// match: (LE (CMPW x z:(NEG y)) yes no)
|
||||
// cond: z.Uses == 1
|
||||
// result: (LE (CMNW x y) yes no)
|
||||
for b.Controls[0].Op == OpARM64CMPW {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
z := v_0.Args[1]
|
||||
if z.Op != OpARM64NEG {
|
||||
break
|
||||
}
|
||||
y := z.Args[0]
|
||||
if !(z.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARM64LE, v0)
|
||||
return true
|
||||
}
|
||||
// match: (LE (CMPconst [0] z:(MADD a x y)) yes no)
|
||||
// cond: z.Uses==1
|
||||
// result: (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
|
||||
|
|
@ -28585,46 +28465,6 @@ func rewriteBlockARM64(b *Block) bool {
|
|||
}
|
||||
break
|
||||
}
|
||||
// match: (LT (CMP x z:(NEG y)) yes no)
|
||||
// cond: z.Uses == 1
|
||||
// result: (LT (CMN x y) yes no)
|
||||
for b.Controls[0].Op == OpARM64CMP {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
z := v_0.Args[1]
|
||||
if z.Op != OpARM64NEG {
|
||||
break
|
||||
}
|
||||
y := z.Args[0]
|
||||
if !(z.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v0 := b.NewValue0(v_0.Pos, OpARM64CMN, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARM64LT, v0)
|
||||
return true
|
||||
}
|
||||
// match: (LT (CMPW x z:(NEG y)) yes no)
|
||||
// cond: z.Uses == 1
|
||||
// result: (LT (CMNW x y) yes no)
|
||||
for b.Controls[0].Op == OpARM64CMPW {
|
||||
v_0 := b.Controls[0]
|
||||
_ = v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
z := v_0.Args[1]
|
||||
if z.Op != OpARM64NEG {
|
||||
break
|
||||
}
|
||||
y := z.Args[0]
|
||||
if !(z.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v0 := b.NewValue0(v_0.Pos, OpARM64CMNW, types.TypeFlags)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockARM64LT, v0)
|
||||
return true
|
||||
}
|
||||
// match: (LT (CMPconst [0] z:(MADD a x y)) yes no)
|
||||
// cond: z.Uses==1
|
||||
// result: (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
|
||||
|
|
|
|||
|
|
@ -298,16 +298,13 @@ func (r *codeRepo) Latest() (*RevInfo, error) {
|
|||
// If statVers is a valid module version, it is used for the Version field.
|
||||
// Otherwise, the Version is derived from the passed-in info and recent tags.
|
||||
func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, error) {
|
||||
info2 := &RevInfo{
|
||||
Name: info.Name,
|
||||
Short: info.Short,
|
||||
Time: info.Time,
|
||||
}
|
||||
|
||||
// If this is a plain tag (no dir/ prefix)
|
||||
// and the module path is unversioned,
|
||||
// and if the underlying file tree has no go.mod,
|
||||
// then allow using the tag with a +incompatible suffix.
|
||||
//
|
||||
// (If the version is +incompatible, then the go.mod file must not exist:
|
||||
// +incompatible is not an ongoing opt-out from semantic import versioning.)
|
||||
var canUseIncompatible func() bool
|
||||
canUseIncompatible = func() bool {
|
||||
var ok bool
|
||||
|
|
@ -321,19 +318,12 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
|||
return ok
|
||||
}
|
||||
|
||||
invalidf := func(format string, args ...interface{}) error {
|
||||
return &module.ModuleError{
|
||||
Path: r.modPath,
|
||||
Err: &module.InvalidVersionError{
|
||||
Version: info2.Version,
|
||||
Err: fmt.Errorf(format, args...),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// checkGoMod verifies that the go.mod file for the module exists or does not
|
||||
// exist as required by info2.Version and the module path represented by r.
|
||||
checkGoMod := func() (*RevInfo, error) {
|
||||
// checkCanonical verifies that the canonical version v is compatible with the
|
||||
// module path represented by r, adding a "+incompatible" suffix if needed.
|
||||
//
|
||||
// If statVers is also canonical, checkCanonical also verifies that v is
|
||||
// either statVers or statVers with the added "+incompatible" suffix.
|
||||
checkCanonical := func(v string) (*RevInfo, error) {
|
||||
// If r.codeDir is non-empty, then the go.mod file must exist: the module
|
||||
// author — not the module consumer, — gets to decide how to carve up the repo
|
||||
// into modules.
|
||||
|
|
@ -344,73 +334,91 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
|||
// r.findDir verifies both of these conditions. Execute it now so that
|
||||
// r.Stat will correctly return a notExistError if the go.mod location or
|
||||
// declared module path doesn't match.
|
||||
_, _, _, err := r.findDir(info2.Version)
|
||||
_, _, _, err := r.findDir(v)
|
||||
if err != nil {
|
||||
// TODO: It would be nice to return an error like "not a module".
|
||||
// Right now we return "missing go.mod", which is a little confusing.
|
||||
return nil, &module.ModuleError{
|
||||
Path: r.modPath,
|
||||
Err: &module.InvalidVersionError{
|
||||
Version: info2.Version,
|
||||
Version: v,
|
||||
Err: notExistError{err: err},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// If the version is +incompatible, then the go.mod file must not exist:
|
||||
// +incompatible is not an ongoing opt-out from semantic import versioning.
|
||||
if strings.HasSuffix(info2.Version, "+incompatible") {
|
||||
if !canUseIncompatible() {
|
||||
if r.pathMajor != "" {
|
||||
return nil, invalidf("+incompatible suffix not allowed: module path includes a major version suffix, so major version must match")
|
||||
} else {
|
||||
return nil, invalidf("+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required")
|
||||
}
|
||||
}
|
||||
|
||||
if err := module.CheckPathMajor(strings.TrimSuffix(info2.Version, "+incompatible"), r.pathMajor); err == nil {
|
||||
return nil, invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(info2.Version))
|
||||
invalidf := func(format string, args ...interface{}) error {
|
||||
return &module.ModuleError{
|
||||
Path: r.modPath,
|
||||
Err: &module.InvalidVersionError{
|
||||
Version: v,
|
||||
Err: fmt.Errorf(format, args...),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return info2, nil
|
||||
// Add the +incompatible suffix if needed or requested explicitly, and
|
||||
// verify that its presence or absence is appropriate for this version
|
||||
// (which depends on whether it has an explicit go.mod file).
|
||||
|
||||
if v == strings.TrimSuffix(statVers, "+incompatible") {
|
||||
v = statVers
|
||||
}
|
||||
base := strings.TrimSuffix(v, "+incompatible")
|
||||
var errIncompatible error
|
||||
if !module.MatchPathMajor(base, r.pathMajor) {
|
||||
if canUseIncompatible() {
|
||||
v = base + "+incompatible"
|
||||
} else {
|
||||
if r.pathMajor != "" {
|
||||
errIncompatible = invalidf("module path includes a major version suffix, so major version must match")
|
||||
} else {
|
||||
errIncompatible = invalidf("module contains a go.mod file, so module path must match major version (%q)", path.Join(r.pathPrefix, semver.Major(v)))
|
||||
}
|
||||
}
|
||||
} else if strings.HasSuffix(v, "+incompatible") {
|
||||
errIncompatible = invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(v))
|
||||
}
|
||||
|
||||
if statVers != "" && statVers == module.CanonicalVersion(statVers) {
|
||||
// Since the caller-requested version is canonical, it would be very
|
||||
// confusing to resolve it to anything but itself, possibly with a
|
||||
// "+incompatible" suffix. Error out explicitly.
|
||||
if statBase := strings.TrimSuffix(statVers, "+incompatible"); statBase != base {
|
||||
return nil, &module.ModuleError{
|
||||
Path: r.modPath,
|
||||
Err: &module.InvalidVersionError{
|
||||
Version: statVers,
|
||||
Err: fmt.Errorf("resolves to version %v (%s is not a tag)", v, statBase),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if errIncompatible != nil {
|
||||
return nil, errIncompatible
|
||||
}
|
||||
|
||||
return &RevInfo{
|
||||
Name: info.Name,
|
||||
Short: info.Short,
|
||||
Time: info.Time,
|
||||
Version: v,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Determine version.
|
||||
//
|
||||
// If statVers is canonical, then the original call was repo.Stat(statVers).
|
||||
// Since the version is canonical, we must not resolve it to anything but
|
||||
// itself, possibly with a '+incompatible' annotation: we do not need to do
|
||||
// the work required to look for an arbitrary pseudo-version.
|
||||
if statVers != "" && statVers == module.CanonicalVersion(statVers) {
|
||||
info2.Version = statVers
|
||||
|
||||
if module.IsPseudoVersion(info2.Version) {
|
||||
if err := r.validatePseudoVersion(info, info2.Version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return checkGoMod()
|
||||
if module.IsPseudoVersion(statVers) {
|
||||
if err := r.validatePseudoVersion(info, statVers); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := module.CheckPathMajor(info2.Version, r.pathMajor); err != nil {
|
||||
if canUseIncompatible() {
|
||||
info2.Version += "+incompatible"
|
||||
return checkGoMod()
|
||||
} else {
|
||||
if vErr, ok := err.(*module.InvalidVersionError); ok {
|
||||
// We're going to describe why the version is invalid in more detail,
|
||||
// so strip out the existing “invalid version” wrapper.
|
||||
err = vErr.Err
|
||||
}
|
||||
return nil, invalidf("module contains a go.mod file, so major version must be compatible: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return checkGoMod()
|
||||
return checkCanonical(statVers)
|
||||
}
|
||||
|
||||
// statVers is empty or non-canonical, so we need to resolve it to a canonical
|
||||
// version or pseudo-version.
|
||||
// statVers is not a pseudo-version, so we need to either resolve it to a
|
||||
// canonical version or verify that it is already a canonical tag
|
||||
// (not a branch).
|
||||
|
||||
// Derive or verify a version from a code repo tag.
|
||||
// Tag must have a prefix matching codeDir.
|
||||
|
|
@ -441,71 +449,62 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
|||
if v == "" || !strings.HasPrefix(trimmed, v) {
|
||||
return "", false // Invalid or incomplete version (just vX or vX.Y).
|
||||
}
|
||||
if isRetracted(v) {
|
||||
return "", false
|
||||
}
|
||||
if v == trimmed {
|
||||
tagIsCanonical = true
|
||||
}
|
||||
|
||||
if err := module.CheckPathMajor(v, r.pathMajor); err != nil {
|
||||
if canUseIncompatible() {
|
||||
return v + "+incompatible", tagIsCanonical
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
return v, tagIsCanonical
|
||||
}
|
||||
|
||||
// If the VCS gave us a valid version, use that.
|
||||
if v, tagIsCanonical := tagToVersion(info.Version); tagIsCanonical {
|
||||
info2.Version = v
|
||||
return checkGoMod()
|
||||
if info, err := checkCanonical(v); err == nil {
|
||||
return info, err
|
||||
}
|
||||
}
|
||||
|
||||
// Look through the tags on the revision for either a usable canonical version
|
||||
// or an appropriate base for a pseudo-version.
|
||||
var pseudoBase string
|
||||
var (
|
||||
highestCanonical string
|
||||
pseudoBase string
|
||||
)
|
||||
for _, pathTag := range info.Tags {
|
||||
v, tagIsCanonical := tagToVersion(pathTag)
|
||||
if tagIsCanonical {
|
||||
if statVers != "" && semver.Compare(v, statVers) == 0 {
|
||||
// The user requested a non-canonical version, but the tag for the
|
||||
// canonical equivalent refers to the same revision. Use it.
|
||||
info2.Version = v
|
||||
return checkGoMod()
|
||||
if statVers != "" && semver.Compare(v, statVers) == 0 {
|
||||
// The tag is equivalent to the version requested by the user.
|
||||
if tagIsCanonical {
|
||||
// This tag is the canonical form of the requested version,
|
||||
// not some other form with extra build metadata.
|
||||
// Use this tag so that the resolved version will match exactly.
|
||||
// (If it isn't actually allowed, we'll error out in checkCanonical.)
|
||||
return checkCanonical(v)
|
||||
} else {
|
||||
// Save the highest canonical tag for the revision. If we don't find a
|
||||
// better match, we'll use it as the canonical version.
|
||||
// The user explicitly requested something equivalent to this tag. We
|
||||
// can't use the version from the tag directly: since the tag is not
|
||||
// canonical, it could be ambiguous. For example, tags v0.0.1+a and
|
||||
// v0.0.1+b might both exist and refer to different revisions.
|
||||
//
|
||||
// NOTE: Do not replace this with semver.Max. Despite the name,
|
||||
// semver.Max *also* canonicalizes its arguments, which uses
|
||||
// semver.Canonical instead of module.CanonicalVersion and thereby
|
||||
// strips our "+incompatible" suffix.
|
||||
if semver.Compare(info2.Version, v) < 0 {
|
||||
info2.Version = v
|
||||
}
|
||||
// The tag is otherwise valid for the module, so we can at least use it as
|
||||
// the base of an unambiguous pseudo-version.
|
||||
//
|
||||
// If multiple tags match, tagToVersion will canonicalize them to the same
|
||||
// base version.
|
||||
pseudoBase = v
|
||||
}
|
||||
}
|
||||
// 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 tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) {
|
||||
if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible() {
|
||||
highestCanonical = v
|
||||
}
|
||||
} else if v != "" && semver.Compare(v, statVers) == 0 {
|
||||
// The user explicitly requested something equivalent to this tag. We
|
||||
// can't use the version from the tag directly: since the tag is not
|
||||
// canonical, it could be ambiguous. For example, tags v0.0.1+a and
|
||||
// v0.0.1+b might both exist and refer to different revisions.
|
||||
//
|
||||
// The tag is otherwise valid for the module, so we can at least use it as
|
||||
// the base of an unambiguous pseudo-version.
|
||||
//
|
||||
// If multiple tags match, tagToVersion will canonicalize them to the same
|
||||
// base version.
|
||||
pseudoBase = v
|
||||
}
|
||||
}
|
||||
|
||||
// If we found any canonical tag for the revision, return it.
|
||||
// If we found a valid canonical tag for the revision, return it.
|
||||
// Even if we found a good pseudo-version base, a canonical version is better.
|
||||
if info2.Version != "" {
|
||||
return checkGoMod()
|
||||
if highestCanonical != "" {
|
||||
return checkCanonical(highestCanonical)
|
||||
}
|
||||
|
||||
// Find the highest tagged version in the revision's history, subject to
|
||||
|
|
@ -528,11 +527,10 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
|||
tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor("v0"))
|
||||
}
|
||||
}
|
||||
pseudoBase, _ = tagToVersion(tag) // empty if the tag is invalid
|
||||
pseudoBase, _ = tagToVersion(tag)
|
||||
}
|
||||
|
||||
info2.Version = module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short)
|
||||
return checkGoMod()
|
||||
return checkCanonical(module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short))
|
||||
}
|
||||
|
||||
// validatePseudoVersion checks that version has a major version compatible with
|
||||
|
|
@ -556,10 +554,6 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
|
|||
}
|
||||
}()
|
||||
|
||||
if err := module.CheckPathMajor(version, r.pathMajor); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rev, err := module.PseudoVersionRev(version)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -418,171 +418,204 @@ var codeRepoTests = []codeRepoTest{
|
|||
zipSum: "h1:JItBZ+gwA5WvtZEGEbuDL4lUttGtLrs53lmdurq3bOg=",
|
||||
zipFileHash: "9ea9ae1673cffcc44b7fdd3cc89953d68c102449b46c982dbf085e4f2e394da5",
|
||||
},
|
||||
{
|
||||
// Git branch with a semver name, +incompatible version, and no go.mod file.
|
||||
vcs: "git",
|
||||
path: "vcs-test.golang.org/go/mod/gitrepo1",
|
||||
rev: "v2.3.4+incompatible",
|
||||
err: `resolves to version v2.0.1+incompatible (v2.3.4 is not a tag)`,
|
||||
},
|
||||
{
|
||||
// Git branch with a semver name, matching go.mod file, and compatible version.
|
||||
vcs: "git",
|
||||
path: "vcs-test.golang.org/git/semver-branch.git",
|
||||
rev: "v1.0.0",
|
||||
err: `resolves to version v0.1.1-0.20220202191944-09c4d8f6938c (v1.0.0 is not a tag)`,
|
||||
},
|
||||
{
|
||||
// Git branch with a semver name, matching go.mod file, and disallowed +incompatible version.
|
||||
// The version/tag mismatch takes precedence over the +incompatible mismatched.
|
||||
vcs: "git",
|
||||
path: "vcs-test.golang.org/git/semver-branch.git",
|
||||
rev: "v2.0.0+incompatible",
|
||||
err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`,
|
||||
},
|
||||
{
|
||||
// Git branch with a semver name, matching go.mod file, and mismatched version.
|
||||
// The version/tag mismatch takes precedence over the +incompatible mismatched.
|
||||
vcs: "git",
|
||||
path: "vcs-test.golang.org/git/semver-branch.git",
|
||||
rev: "v2.0.0",
|
||||
err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`,
|
||||
},
|
||||
{
|
||||
// v3.0.0-devel is the same as tag v4.0.0-beta.1, but v4.0.0-beta.1 would
|
||||
// not be allowed because it is incompatible and a go.mod file exists.
|
||||
// The error message should refer to a valid pseudo-version, not the
|
||||
// unusable semver tag.
|
||||
vcs: "git",
|
||||
path: "vcs-test.golang.org/git/semver-branch.git",
|
||||
rev: "v3.0.0-devel",
|
||||
err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`,
|
||||
},
|
||||
}
|
||||
|
||||
func TestCodeRepo(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
tmpdir := t.TempDir()
|
||||
|
||||
tmpdir, err := os.MkdirTemp("", "modfetch-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
for _, tt := range codeRepoTests {
|
||||
f := func(tt codeRepoTest) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tt.vcs != "mod" {
|
||||
testenv.MustHaveExecPath(t, tt.vcs)
|
||||
}
|
||||
|
||||
t.Run("parallel", func(t *testing.T) {
|
||||
for _, tt := range codeRepoTests {
|
||||
f := func(tt codeRepoTest) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tt.vcs != "mod" {
|
||||
testenv.MustHaveExecPath(t, tt.vcs)
|
||||
}
|
||||
repo := Lookup("direct", tt.path)
|
||||
|
||||
repo := Lookup("direct", tt.path)
|
||||
if tt.mpath == "" {
|
||||
tt.mpath = tt.path
|
||||
}
|
||||
if mpath := repo.ModulePath(); mpath != tt.mpath {
|
||||
t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath)
|
||||
}
|
||||
|
||||
if tt.mpath == "" {
|
||||
tt.mpath = tt.path
|
||||
}
|
||||
if mpath := repo.ModulePath(); mpath != tt.mpath {
|
||||
t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath)
|
||||
}
|
||||
|
||||
info, err := repo.Stat(tt.rev)
|
||||
if err != nil {
|
||||
if tt.err != "" {
|
||||
if !strings.Contains(err.Error(), tt.err) {
|
||||
t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err)
|
||||
}
|
||||
return
|
||||
}
|
||||
t.Fatalf("repo.Stat(%q): %v", tt.rev, err)
|
||||
}
|
||||
info, err := repo.Stat(tt.rev)
|
||||
if err != nil {
|
||||
if tt.err != "" {
|
||||
t.Errorf("repo.Stat(%q): success, wanted error", tt.rev)
|
||||
}
|
||||
if info.Version != tt.version {
|
||||
t.Errorf("info.Version = %q, want %q", info.Version, tt.version)
|
||||
}
|
||||
if info.Name != tt.name {
|
||||
t.Errorf("info.Name = %q, want %q", info.Name, tt.name)
|
||||
}
|
||||
if info.Short != tt.short {
|
||||
t.Errorf("info.Short = %q, want %q", info.Short, tt.short)
|
||||
}
|
||||
if !info.Time.Equal(tt.time) {
|
||||
t.Errorf("info.Time = %v, want %v", info.Time, tt.time)
|
||||
if !strings.Contains(err.Error(), tt.err) {
|
||||
t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err)
|
||||
}
|
||||
return
|
||||
}
|
||||
t.Fatalf("repo.Stat(%q): %v", tt.rev, err)
|
||||
}
|
||||
if tt.err != "" {
|
||||
t.Errorf("repo.Stat(%q): success, wanted error", tt.rev)
|
||||
}
|
||||
if info.Version != tt.version {
|
||||
t.Errorf("info.Version = %q, want %q", info.Version, tt.version)
|
||||
}
|
||||
if info.Name != tt.name {
|
||||
t.Errorf("info.Name = %q, want %q", info.Name, tt.name)
|
||||
}
|
||||
if info.Short != tt.short {
|
||||
t.Errorf("info.Short = %q, want %q", info.Short, tt.short)
|
||||
}
|
||||
if !info.Time.Equal(tt.time) {
|
||||
t.Errorf("info.Time = %v, want %v", info.Time, tt.time)
|
||||
}
|
||||
|
||||
if tt.gomod != "" || tt.gomodErr != "" {
|
||||
data, err := repo.GoMod(tt.version)
|
||||
if err != nil && tt.gomodErr == "" {
|
||||
t.Errorf("repo.GoMod(%q): %v", tt.version, err)
|
||||
} else if err != nil && tt.gomodErr != "" {
|
||||
if err.Error() != tt.gomodErr {
|
||||
t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr)
|
||||
}
|
||||
} else if tt.gomodErr != "" {
|
||||
t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr)
|
||||
} else if string(data) != tt.gomod {
|
||||
t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod)
|
||||
}
|
||||
}
|
||||
|
||||
needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "")
|
||||
if tt.zip != nil || tt.zipErr != "" || needHash {
|
||||
f, err := os.CreateTemp(tmpdir, tt.version+".zip.")
|
||||
if err != nil {
|
||||
t.Fatalf("os.CreateTemp: %v", err)
|
||||
}
|
||||
zipfile := f.Name()
|
||||
defer func() {
|
||||
f.Close()
|
||||
os.Remove(zipfile)
|
||||
}()
|
||||
|
||||
var w io.Writer
|
||||
var h hash.Hash
|
||||
if needHash {
|
||||
h = sha256.New()
|
||||
w = io.MultiWriter(f, h)
|
||||
} else {
|
||||
w = f
|
||||
}
|
||||
err = repo.Zip(w, tt.version)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
if tt.zipErr != "" {
|
||||
if err.Error() == tt.zipErr {
|
||||
return
|
||||
}
|
||||
t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr)
|
||||
}
|
||||
t.Fatalf("repo.Zip(%q): %v", tt.version, err)
|
||||
}
|
||||
if tt.zipErr != "" {
|
||||
t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr)
|
||||
}
|
||||
|
||||
if tt.zip != nil {
|
||||
prefix := tt.path + "@" + tt.version + "/"
|
||||
z, err := zip.OpenReader(zipfile)
|
||||
if err != nil {
|
||||
t.Fatalf("open zip %s: %v", zipfile, err)
|
||||
}
|
||||
var names []string
|
||||
for _, file := range z.File {
|
||||
if !strings.HasPrefix(file.Name, prefix) {
|
||||
t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix)
|
||||
continue
|
||||
}
|
||||
names = append(names, file.Name[len(prefix):])
|
||||
}
|
||||
z.Close()
|
||||
if !reflect.DeepEqual(names, tt.zip) {
|
||||
t.Fatalf("zip = %v\nwant %v\n", names, tt.zip)
|
||||
}
|
||||
}
|
||||
|
||||
if needHash {
|
||||
sum, err := dirhash.HashZip(zipfile, dirhash.Hash1)
|
||||
if err != nil {
|
||||
t.Errorf("repo.Zip(%q): %v", tt.version, err)
|
||||
} else if sum != tt.zipSum {
|
||||
t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum)
|
||||
} else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash {
|
||||
t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash)
|
||||
}
|
||||
if tt.gomod != "" || tt.gomodErr != "" {
|
||||
data, err := repo.GoMod(tt.version)
|
||||
if err != nil && tt.gomodErr == "" {
|
||||
t.Errorf("repo.GoMod(%q): %v", tt.version, err)
|
||||
} else if err != nil && tt.gomodErr != "" {
|
||||
if err.Error() != tt.gomodErr {
|
||||
t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr)
|
||||
}
|
||||
} else if tt.gomodErr != "" {
|
||||
t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr)
|
||||
} else if string(data) != tt.gomod {
|
||||
t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt))
|
||||
if strings.HasPrefix(tt.path, vgotest1git) {
|
||||
for vcs, alt := range altVgotests {
|
||||
altTest := tt
|
||||
altTest.vcs = vcs
|
||||
altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git)
|
||||
if strings.HasPrefix(altTest.mpath, vgotest1git) {
|
||||
altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git)
|
||||
|
||||
needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "")
|
||||
if tt.zip != nil || tt.zipErr != "" || needHash {
|
||||
f, err := os.CreateTemp(tmpdir, tt.version+".zip.")
|
||||
if err != nil {
|
||||
t.Fatalf("os.CreateTemp: %v", err)
|
||||
}
|
||||
var m map[string]string
|
||||
if alt == vgotest1hg {
|
||||
m = hgmap
|
||||
zipfile := f.Name()
|
||||
defer func() {
|
||||
f.Close()
|
||||
os.Remove(zipfile)
|
||||
}()
|
||||
|
||||
var w io.Writer
|
||||
var h hash.Hash
|
||||
if needHash {
|
||||
h = sha256.New()
|
||||
w = io.MultiWriter(f, h)
|
||||
} else {
|
||||
w = f
|
||||
}
|
||||
err = repo.Zip(w, tt.version)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
if tt.zipErr != "" {
|
||||
if err.Error() == tt.zipErr {
|
||||
return
|
||||
}
|
||||
t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr)
|
||||
}
|
||||
t.Fatalf("repo.Zip(%q): %v", tt.version, err)
|
||||
}
|
||||
if tt.zipErr != "" {
|
||||
t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr)
|
||||
}
|
||||
|
||||
if tt.zip != nil {
|
||||
prefix := tt.path + "@" + tt.version + "/"
|
||||
z, err := zip.OpenReader(zipfile)
|
||||
if err != nil {
|
||||
t.Fatalf("open zip %s: %v", zipfile, err)
|
||||
}
|
||||
var names []string
|
||||
for _, file := range z.File {
|
||||
if !strings.HasPrefix(file.Name, prefix) {
|
||||
t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix)
|
||||
continue
|
||||
}
|
||||
names = append(names, file.Name[len(prefix):])
|
||||
}
|
||||
z.Close()
|
||||
if !reflect.DeepEqual(names, tt.zip) {
|
||||
t.Fatalf("zip = %v\nwant %v\n", names, tt.zip)
|
||||
}
|
||||
}
|
||||
|
||||
if needHash {
|
||||
sum, err := dirhash.HashZip(zipfile, dirhash.Hash1)
|
||||
if err != nil {
|
||||
t.Errorf("repo.Zip(%q): %v", tt.version, err)
|
||||
} else if sum != tt.zipSum {
|
||||
t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum)
|
||||
} else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash {
|
||||
t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash)
|
||||
}
|
||||
}
|
||||
altTest.version = remap(altTest.version, m)
|
||||
altTest.name = remap(altTest.name, m)
|
||||
altTest.short = remap(altTest.short, m)
|
||||
altTest.rev = remap(altTest.rev, m)
|
||||
altTest.err = remap(altTest.err, m)
|
||||
altTest.gomodErr = remap(altTest.gomodErr, m)
|
||||
altTest.zipErr = remap(altTest.zipErr, m)
|
||||
altTest.zipSum = ""
|
||||
altTest.zipFileHash = ""
|
||||
t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt))
|
||||
if strings.HasPrefix(tt.path, vgotest1git) {
|
||||
for vcs, alt := range altVgotests {
|
||||
altTest := tt
|
||||
altTest.vcs = vcs
|
||||
altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git)
|
||||
if strings.HasPrefix(altTest.mpath, vgotest1git) {
|
||||
altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git)
|
||||
}
|
||||
var m map[string]string
|
||||
if alt == vgotest1hg {
|
||||
m = hgmap
|
||||
}
|
||||
altTest.version = remap(altTest.version, m)
|
||||
altTest.name = remap(altTest.name, m)
|
||||
altTest.short = remap(altTest.short, m)
|
||||
altTest.rev = remap(altTest.rev, m)
|
||||
altTest.err = remap(altTest.err, m)
|
||||
altTest.gomodErr = remap(altTest.gomodErr, m)
|
||||
altTest.zipErr = remap(altTest.zipErr, m)
|
||||
altTest.zipSum = ""
|
||||
altTest.zipFileHash = ""
|
||||
t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var hgmap = map[string]string{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
package vcs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
exec "internal/execabs"
|
||||
|
|
@ -1189,8 +1188,9 @@ var vcsPaths = []*vcsPath{
|
|||
{
|
||||
pathPrefix: "bitbucket.org",
|
||||
regexp: lazyregexp.New(`^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),
|
||||
vcs: "git",
|
||||
repo: "https://{root}",
|
||||
check: bitbucketVCS,
|
||||
check: noVCSSuffix,
|
||||
},
|
||||
|
||||
// IBM DevOps Services (JazzHub)
|
||||
|
|
@ -1262,56 +1262,6 @@ func noVCSSuffix(match map[string]string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// bitbucketVCS determines the version control system for a
|
||||
// Bitbucket repository, by using the Bitbucket API.
|
||||
func bitbucketVCS(match map[string]string) error {
|
||||
if err := noVCSSuffix(match); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
SCM string `json:"scm"`
|
||||
}
|
||||
url := &urlpkg.URL{
|
||||
Scheme: "https",
|
||||
Host: "api.bitbucket.org",
|
||||
Path: expand(match, "/2.0/repositories/{bitname}"),
|
||||
RawQuery: "fields=scm",
|
||||
}
|
||||
data, err := web.GetBytes(url)
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*web.HTTPError); ok && httpErr.StatusCode == 403 {
|
||||
// this may be a private repository. If so, attempt to determine which
|
||||
// VCS it uses. See issue 5375.
|
||||
root := match["root"]
|
||||
for _, vcs := range []string{"git", "hg"} {
|
||||
if vcsByCmd(vcs).Ping("https", root) == nil {
|
||||
resp.SCM = vcs
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if resp.SCM == "" {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := json.Unmarshal(data, &resp); err != nil {
|
||||
return fmt.Errorf("decoding %s: %v", url, err)
|
||||
}
|
||||
}
|
||||
|
||||
if vcsByCmd(resp.SCM) != nil {
|
||||
match["vcs"] = resp.SCM
|
||||
if resp.SCM == "git" {
|
||||
match["repo"] += ".git"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("unable to detect version control system for bitbucket.org/ path")
|
||||
}
|
||||
|
||||
// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case,
|
||||
// "foo" could be a series name registered in Launchpad with its own branch,
|
||||
// and it could also be the name of a directory within the main project
|
||||
|
|
|
|||
|
|
@ -183,6 +183,13 @@ func TestRepoRootForImportPath(t *testing.T) {
|
|||
"chiselapp.com/user/kyle/fossilgg",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"bitbucket.org/workspace/pkgname",
|
||||
&RepoRoot{
|
||||
VCS: vcsGit,
|
||||
Repo: "https://bitbucket.org/workspace/pkgname",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
|
|||
|
|
@ -194,10 +194,10 @@ cp go.mod.orig go.mod
|
|||
go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d+incompatible
|
||||
cd outside
|
||||
! go list -m github.com/pierrec/lz4
|
||||
stderr 'go list -m: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
|
||||
stderr '^go list -m: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
|
||||
cd ..
|
||||
! go list -m github.com/pierrec/lz4
|
||||
stderr 'github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
|
||||
stderr '^go list -m: github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
|
||||
|
||||
# A +incompatible pseudo-version is valid for a revision of the module
|
||||
# that lacks a go.mod file.
|
||||
|
|
@ -222,7 +222,7 @@ stdout 'github.com/pierrec/lz4 v2.0.5\+incompatible'
|
|||
# not resolve to a pseudo-version with a different major version.
|
||||
cp go.mod.orig go.mod
|
||||
! go get -d github.com/pierrec/lz4@v2.0.8
|
||||
stderr 'go get: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2'
|
||||
stderr 'go get: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
|
||||
|
||||
# An invalid +incompatible suffix for a canonical version should error out,
|
||||
# not resolve to a pseudo-version.
|
||||
|
|
@ -233,10 +233,10 @@ cp go.mod.orig go.mod
|
|||
go mod edit -require github.com/pierrec/lz4@v2.0.8+incompatible
|
||||
cd outside
|
||||
! go list -m github.com/pierrec/lz4
|
||||
stderr 'github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
|
||||
stderr '^go list -m: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
|
||||
cd ..
|
||||
! go list -m github.com/pierrec/lz4
|
||||
stderr 'github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
|
||||
stderr '^go list -m: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$'
|
||||
|
||||
-- go.mod.orig --
|
||||
module example.com
|
||||
|
|
|
|||
|
|
@ -2170,7 +2170,7 @@ func span6(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
|||
}
|
||||
|
||||
n++
|
||||
if n > 20 {
|
||||
if n > 1000 {
|
||||
ctxt.Diag("span must be looping")
|
||||
log.Fatalf("loop")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1268,7 +1268,10 @@ func (ctxt *Link) hostlink() {
|
|||
if ctxt.DynlinkingGo() && buildcfg.GOOS != "ios" {
|
||||
// -flat_namespace is deprecated on iOS.
|
||||
// It is useful for supporting plugins. We don't support plugins on iOS.
|
||||
argv = append(argv, "-Wl,-flat_namespace")
|
||||
// -flat_namespace may cause the dynamic linker to hang at forkExec when
|
||||
// resolving a lazy binding. See issue 38824.
|
||||
// Force eager resolution to work around.
|
||||
argv = append(argv, "-Wl,-flat_namespace", "-Wl,-bind_at_load")
|
||||
}
|
||||
if !combineDwarf {
|
||||
argv = append(argv, "-Wl,-S") // suppress STAB (symbolic debugging) symbols
|
||||
|
|
|
|||
|
|
@ -86,6 +86,11 @@ func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
|
|||
return specific.IsOnCurve(x, y)
|
||||
}
|
||||
|
||||
if x.Sign() < 0 || x.Cmp(curve.P) >= 0 ||
|
||||
y.Sign() < 0 || y.Cmp(curve.P) >= 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// y² = x³ - 3x + b
|
||||
y2 := new(big.Int).Mul(y, y)
|
||||
y2.Mod(y2, curve.P)
|
||||
|
|
|
|||
|
|
@ -174,6 +174,61 @@ func testUnmarshalToLargeCoordinates(t *testing.T, curve Curve) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestInvalidCoordinates tests big.Int values that are not valid field elements
|
||||
// (negative or bigger than P). They are expected to return false from
|
||||
// IsOnCurve, all other behavior is undefined.
|
||||
func TestInvalidCoordinates(t *testing.T) {
|
||||
testAllCurves(t, testInvalidCoordinates)
|
||||
}
|
||||
|
||||
func testInvalidCoordinates(t *testing.T, curve Curve) {
|
||||
checkIsOnCurveFalse := func(name string, x, y *big.Int) {
|
||||
if curve.IsOnCurve(x, y) {
|
||||
t.Errorf("IsOnCurve(%s) unexpectedly returned true", name)
|
||||
}
|
||||
}
|
||||
|
||||
p := curve.Params().P
|
||||
_, x, y, _ := GenerateKey(curve, rand.Reader)
|
||||
xx, yy := new(big.Int), new(big.Int)
|
||||
|
||||
// Check if the sign is getting dropped.
|
||||
xx.Neg(x)
|
||||
checkIsOnCurveFalse("-x, y", xx, y)
|
||||
yy.Neg(y)
|
||||
checkIsOnCurveFalse("x, -y", x, yy)
|
||||
|
||||
// Check if negative values are reduced modulo P.
|
||||
xx.Sub(x, p)
|
||||
checkIsOnCurveFalse("x-P, y", xx, y)
|
||||
yy.Sub(y, p)
|
||||
checkIsOnCurveFalse("x, y-P", x, yy)
|
||||
|
||||
// Check if positive values are reduced modulo P.
|
||||
xx.Add(x, p)
|
||||
checkIsOnCurveFalse("x+P, y", xx, y)
|
||||
yy.Add(y, p)
|
||||
checkIsOnCurveFalse("x, y+P", x, yy)
|
||||
|
||||
// Check if the overflow is dropped.
|
||||
xx.Add(x, new(big.Int).Lsh(big.NewInt(1), 535))
|
||||
checkIsOnCurveFalse("x+2⁵³⁵, y", xx, y)
|
||||
yy.Add(y, new(big.Int).Lsh(big.NewInt(1), 535))
|
||||
checkIsOnCurveFalse("x, y+2⁵³⁵", x, yy)
|
||||
|
||||
// Check if P is treated like zero (if possible).
|
||||
// y^2 = x^3 - 3x + B
|
||||
// y = mod_sqrt(x^3 - 3x + B)
|
||||
// y = mod_sqrt(B) if x = 0
|
||||
// If there is no modsqrt, there is no point with x = 0, can't test x = P.
|
||||
if yy := new(big.Int).ModSqrt(curve.Params().B, p); yy != nil {
|
||||
if !curve.IsOnCurve(big.NewInt(0), yy) {
|
||||
t.Fatal("(0, mod_sqrt(B)) is not on the curve?")
|
||||
}
|
||||
checkIsOnCurveFalse("P, y", p, yy)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalCompressed(t *testing.T) {
|
||||
t.Run("P-256/03", func(t *testing.T) {
|
||||
data, _ := hex.DecodeString("031e3987d9f9ea9d7dd7155a56a86b2009e1e0ab332f962d10d8beb6406ab1ad79")
|
||||
|
|
|
|||
|
|
@ -48,6 +48,11 @@ func (curve p224Curve) Params() *CurveParams {
|
|||
}
|
||||
|
||||
func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool {
|
||||
if bigX.Sign() < 0 || bigX.Cmp(curve.P) >= 0 ||
|
||||
bigY.Sign() < 0 || bigY.Cmp(curve.P) >= 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var x, y p224FieldElement
|
||||
p224FromBig(&x, bigX)
|
||||
p224FromBig(&y, bigY)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,11 @@ func (curve p521Curve) Params() *CurveParams {
|
|||
}
|
||||
|
||||
func (curve p521Curve) IsOnCurve(x, y *big.Int) bool {
|
||||
if x.Sign() < 0 || x.Cmp(curve.P) >= 0 ||
|
||||
y.Sign() < 0 || y.Cmp(curve.P) >= 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
x1 := bigIntToFiatP521(x)
|
||||
y1 := bigIntToFiatP521(y)
|
||||
b := bigIntToFiatP521(curve.B) // TODO: precompute this value.
|
||||
|
|
|
|||
|
|
@ -650,10 +650,14 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Look for DWARF4 .debug_types sections.
|
||||
// Look for DWARF4 .debug_types sections and DWARF5 sections.
|
||||
for i, s := range f.Sections {
|
||||
suffix := dwarfSuffix(s)
|
||||
if suffix != "types" {
|
||||
if suffix == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := dat[suffix]; ok {
|
||||
// Already handled.
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -662,7 +666,11 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
|
||||
if suffix == "types" {
|
||||
err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
|
||||
} else {
|
||||
err = d.AddSection(".debug_"+suffix, b)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,10 +272,14 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Look for DWARF4 .debug_types sections.
|
||||
// Look for DWARF4 .debug_types sections and DWARF5 sections.
|
||||
for i, s := range f.Sections {
|
||||
suffix := dwarfSuffix(s)
|
||||
if suffix != "types" {
|
||||
if suffix == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := dat[suffix]; ok {
|
||||
// Already handled.
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -284,7 +288,11 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
|
||||
if suffix == "types" {
|
||||
err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
|
||||
} else {
|
||||
err = d.AddSection(".debug_"+suffix, b)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,6 +169,11 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
|
|||
n := exp5
|
||||
if n < 0 {
|
||||
n = -n
|
||||
if n < 0 {
|
||||
// This can occur if -n overflows. -(-1 << 63) would become
|
||||
// -1 << 63, which is still negative.
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
if n > 1e6 {
|
||||
return nil, false // avoid excessively large exponents
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ var setStringTests = []StringTest{
|
|||
{in: "4/3/"},
|
||||
{in: "4/3."},
|
||||
{in: "4/"},
|
||||
{in: "13e-9223372036854775808"}, // CVE-2022-23772
|
||||
|
||||
// valid
|
||||
{"0", "0", true},
|
||||
|
|
|
|||
|
|
@ -10,37 +10,56 @@ import "strings"
|
|||
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
|
||||
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
|
||||
// generated from src/crypto/tls:
|
||||
// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
||||
// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
||||
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
|
||||
MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS
|
||||
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
|
||||
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
|
||||
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
|
||||
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
|
||||
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
|
||||
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
|
||||
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
|
||||
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
|
||||
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
|
||||
fblo6RBxUQ==
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r
|
||||
bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U
|
||||
aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P
|
||||
YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk
|
||||
POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu
|
||||
h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE
|
||||
AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
|
||||
DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv
|
||||
bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI
|
||||
5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv
|
||||
cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2
|
||||
+tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B
|
||||
grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK
|
||||
5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/
|
||||
WkBKOclmOV2xlTVuPw==
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
// LocalhostKey is the private key for LocalhostCert.
|
||||
var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY-----
|
||||
MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
|
||||
SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
|
||||
l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
|
||||
AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
|
||||
3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
|
||||
uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
|
||||
qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
|
||||
jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
|
||||
fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
|
||||
fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
|
||||
y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
|
||||
qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
|
||||
f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDoZtrm0dXV0Aqi
|
||||
4Bpc7f95sNRTiu/AJSD8I1onY9PnEsPg3VVxvytsVJbYdcqr4w99V3AgpH/UNzMS
|
||||
gAZ/8lZBNbsSDOVesJ3euVqMRfYPvd9pYl6QPRRpSDPm+2tNdn3QFAvta9EgJ3sW
|
||||
URnoU85w+W6aLI2bNSq3AaE771p3VbkGolpEjo9h+i42TBHo1rhPNKPkGupR8/QX
|
||||
AOLMpInRdeaHyDwb2a3DE5I3dG7VAVzrVfJ6W6Q84YoFX+rpEE2SVM17SAjy6xQy
|
||||
VjKgLvK2mk0xbtfa+h0B6VK7bmODHZqeP18NVm6HsBcXn7iclLgAC3SfWU1jucZK
|
||||
x1lqzw9tAgMBAAECggEABWzxS1Y2wckblnXY57Z+sl6YdmLV+gxj2r8Qib7g4ZIk
|
||||
lIlWR1OJNfw7kU4eryib4fc6nOh6O4AWZyYqAK6tqNQSS/eVG0LQTLTTEldHyVJL
|
||||
dvBe+MsUQOj4nTndZW+QvFzbcm2D8lY5n2nBSxU5ypVoKZ1EqQzytFcLZpTN7d89
|
||||
EPj0qDyrV4NZlWAwL1AygCwnlwhMQjXEalVF1ylXwU3QzyZ/6MgvF6d3SSUlh+sq
|
||||
XefuyigXw484cQQgbzopv6niMOmGP3of+yV4JQqUSb3IDmmT68XjGd2Dkxl4iPki
|
||||
6ZwXf3CCi+c+i/zVEcufgZ3SLf8D99kUGE7v7fZ6AQKBgQD1ZX3RAla9hIhxCf+O
|
||||
3D+I1j2LMrdjAh0ZKKqwMR4JnHX3mjQI6LwqIctPWTU8wYFECSh9klEclSdCa64s
|
||||
uI/GNpcqPXejd0cAAdqHEEeG5sHMDt0oFSurL4lyud0GtZvwlzLuwEweuDtvT9cJ
|
||||
Wfvl86uyO36IW8JdvUprYDctrQKBgQDycZ697qutBieZlGkHpnYWUAeImVA878sJ
|
||||
w44NuXHvMxBPz+lbJGAg8Cn8fcxNAPqHIraK+kx3po8cZGQywKHUWsxi23ozHoxo
|
||||
+bGqeQb9U661TnfdDspIXia+xilZt3mm5BPzOUuRqlh4Y9SOBpSWRmEhyw76w4ZP
|
||||
OPxjWYAgwQKBgA/FehSYxeJgRjSdo+MWnK66tjHgDJE8bYpUZsP0JC4R9DL5oiaA
|
||||
brd2fI6Y+SbyeNBallObt8LSgzdtnEAbjIH8uDJqyOmknNePRvAvR6mP4xyuR+Bv
|
||||
m+Lgp0DMWTw5J9CKpydZDItc49T/mJ5tPhdFVd+am0NAQnmr1MCZ6nHxAoGABS3Y
|
||||
LkaC9FdFUUqSU8+Chkd/YbOkuyiENdkvl6t2e52jo5DVc1T7mLiIrRQi4SI8N9bN
|
||||
/3oJWCT+uaSLX2ouCtNFunblzWHBrhxnZzTeqVq4SLc8aESAnbslKL4i8/+vYZlN
|
||||
s8xtiNcSvL+lMsOBORSXzpj/4Ot8WwTkn1qyGgECgYBKNTypzAHeLE6yVadFp3nQ
|
||||
Ckq9yzvP/ib05rvgbvrne00YeOxqJ9gtTrzgh7koqJyX1L4NwdkEza4ilDWpucn0
|
||||
xiUZS4SoaJq6ZvcBYS62Yr1t8n09iG47YL8ibgtmH3L+svaotvpVxVK+d7BLevA/
|
||||
ZboOWVe3icTy64BT3OQhmg==
|
||||
-----END RSA TESTING KEY-----`))
|
||||
|
||||
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
|
||||
|
|
|
|||
|
|
@ -1543,3 +1543,38 @@ func TestTryAdd(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeVDSO(t *testing.T) {
|
||||
// Test that time functions have the right stack trace. In particular,
|
||||
// it shouldn't be recursive.
|
||||
|
||||
if runtime.GOOS == "android" {
|
||||
// Flaky on Android, issue 48655. VDSO may not be enabled.
|
||||
testenv.SkipFlaky(t, 48655)
|
||||
}
|
||||
|
||||
p := testCPUProfile(t, stackContains, []string{"time.now"}, avoidFunctions(), func(dur time.Duration) {
|
||||
t0 := time.Now()
|
||||
for {
|
||||
t := time.Now()
|
||||
if t.Sub(t0) >= dur {
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Check for recursive time.now sample.
|
||||
for _, sample := range p.Sample {
|
||||
var seenNow bool
|
||||
for _, loc := range sample.Location {
|
||||
for _, line := range loc.Line {
|
||||
if line.Function.Name == "time.now" {
|
||||
if seenNow {
|
||||
t.Fatalf("unexpected recursive time.now")
|
||||
}
|
||||
seenNow = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,8 +259,9 @@ TEXT runtime·walltime(SB),NOSPLIT,$8-12
|
|||
MOVW R1, 4(R13)
|
||||
MOVW R2, 8(R13)
|
||||
|
||||
MOVW $ret-4(FP), R2 // caller's SP
|
||||
MOVW LR, m_vdsoPC(R5)
|
||||
MOVW R13, m_vdsoSP(R5)
|
||||
MOVW R2, m_vdsoSP(R5)
|
||||
|
||||
MOVW m_curg(R5), R0
|
||||
|
||||
|
|
@ -351,8 +352,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$8-8
|
|||
MOVW R1, 4(R13)
|
||||
MOVW R2, 8(R13)
|
||||
|
||||
MOVW $ret-4(FP), R2 // caller's SP
|
||||
MOVW LR, m_vdsoPC(R5)
|
||||
MOVW R13, m_vdsoSP(R5)
|
||||
MOVW R2, m_vdsoSP(R5)
|
||||
|
||||
MOVW m_curg(R5), R0
|
||||
|
||||
|
|
|
|||
|
|
@ -221,8 +221,9 @@ TEXT runtime·walltime(SB),NOSPLIT,$24-12
|
|||
MOVD R2, 8(RSP)
|
||||
MOVD R3, 16(RSP)
|
||||
|
||||
MOVD $ret-8(FP), R2 // caller's SP
|
||||
MOVD LR, m_vdsoPC(R21)
|
||||
MOVD R20, m_vdsoSP(R21)
|
||||
MOVD R2, m_vdsoSP(R21)
|
||||
|
||||
MOVD m_curg(R21), R0
|
||||
CMP g, R0
|
||||
|
|
@ -304,8 +305,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$24-8
|
|||
MOVD R2, 8(RSP)
|
||||
MOVD R3, 16(RSP)
|
||||
|
||||
MOVD $ret-8(FP), R2 // caller's SP
|
||||
MOVD LR, m_vdsoPC(R21)
|
||||
MOVD R20, m_vdsoSP(R21)
|
||||
MOVD R2, m_vdsoSP(R21)
|
||||
|
||||
MOVD m_curg(R21), R0
|
||||
CMP g, R0
|
||||
|
|
|
|||
|
|
@ -229,8 +229,9 @@ TEXT runtime·walltime(SB),NOSPLIT,$16-12
|
|||
MOVV R2, 8(R29)
|
||||
MOVV R3, 16(R29)
|
||||
|
||||
MOVV $ret-8(FP), R2 // caller's SP
|
||||
MOVV R31, m_vdsoPC(R17)
|
||||
MOVV R29, m_vdsoSP(R17)
|
||||
MOVV R2, m_vdsoSP(R17)
|
||||
|
||||
MOVV m_curg(R17), R4
|
||||
MOVV g, R5
|
||||
|
|
@ -298,8 +299,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
|
|||
MOVV R2, 8(R29)
|
||||
MOVV R3, 16(R29)
|
||||
|
||||
MOVV $ret-8(FP), R2 // caller's SP
|
||||
MOVV R31, m_vdsoPC(R17)
|
||||
MOVV R29, m_vdsoSP(R17)
|
||||
MOVV R2, m_vdsoSP(R17)
|
||||
|
||||
MOVV m_curg(R17), R4
|
||||
MOVV g, R5
|
||||
|
|
|
|||
|
|
@ -205,8 +205,9 @@ TEXT runtime·walltime(SB),NOSPLIT,$16-12
|
|||
MOVD R5, 40(R1)
|
||||
|
||||
MOVD LR, R14
|
||||
MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP
|
||||
MOVD R14, m_vdsoPC(R21)
|
||||
MOVD R15, m_vdsoSP(R21)
|
||||
MOVD R5, m_vdsoSP(R21)
|
||||
|
||||
MOVD m_curg(R21), R6
|
||||
CMP g, R6
|
||||
|
|
@ -297,9 +298,10 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
|
|||
MOVD R4, 32(R1)
|
||||
MOVD R5, 40(R1)
|
||||
|
||||
MOVD LR, R14 // R14 is unchanged by C code
|
||||
MOVD LR, R14 // R14 is unchanged by C code
|
||||
MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP
|
||||
MOVD R14, m_vdsoPC(R21)
|
||||
MOVD R15, m_vdsoSP(R21)
|
||||
MOVD R5, m_vdsoSP(R21)
|
||||
|
||||
MOVD m_curg(R21), R6
|
||||
CMP g, R6
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// 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 50671: sign extension eliminated incorrectly on MIPS64.
|
||||
|
||||
package main
|
||||
|
||||
//go:noinline
|
||||
func F(x int32) (float64, int64) {
|
||||
a := float64(x)
|
||||
b := int64(x)
|
||||
return a, b
|
||||
}
|
||||
|
||||
var a, b, c float64
|
||||
|
||||
// Poison some floating point registers with non-zero high bits.
|
||||
//
|
||||
//go:noinline
|
||||
func poison(x float64) {
|
||||
a = x - 123.45
|
||||
b = a * 1.2
|
||||
c = b + 3.4
|
||||
}
|
||||
|
||||
func main() {
|
||||
poison(333.3)
|
||||
_, b := F(123)
|
||||
if b != 123 {
|
||||
panic("FAIL")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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.
|
||||
|
||||
package main
|
||||
|
||||
// This checks for incorrect application of CMP(-x,y) -> CMN(x,y) in arm and arm64
|
||||
|
||||
//go:noinline
|
||||
func f(p int64, x, y int64) bool { return -x <= p && p <= y }
|
||||
|
||||
//go:noinline
|
||||
func g(p int32, x, y int32) bool { return -x <= p && p <= y }
|
||||
|
||||
// There are some more complicated patterns involving compares and shifts, try to trigger those.
|
||||
|
||||
//go:noinline
|
||||
func h(p int64, x, y int64) bool { return -(x<<1) <= p && p <= y }
|
||||
|
||||
//go:noinline
|
||||
func k(p int32, x, y int32) bool { return -(1<<x) <= p && p <= y }
|
||||
|
||||
//go:noinline
|
||||
func check(b bool) {
|
||||
if b {
|
||||
return
|
||||
}
|
||||
panic("FAILURE")
|
||||
}
|
||||
|
||||
func main() {
|
||||
check(f(1, -1<<63, 1<<63-1))
|
||||
check(g(1, -1<<31, 1<<31-1))
|
||||
check(h(1, -1<<62, 1<<63-1))
|
||||
check(k(1, 31, 1<<31-1))
|
||||
}
|
||||
Loading…
Reference in New Issue