[release-branch.go1.14] all: merge release-branch.go1.14-security into release-branch.go1.14

Change-Id: I32a354618306a72315048c3b5943ed46e1036e25
This commit is contained in:
Roland Shoemaker 2021-01-19 15:50:32 -08:00
commit f1f01bfa33
41 changed files with 582 additions and 66 deletions

View File

@ -1 +1 @@
go1.14.13
go1.14.14

View File

@ -16,11 +16,11 @@ import (
"go/parser"
"go/token"
"go/types"
exec "internal/execabs"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"

View File

@ -10,9 +10,9 @@ package main
import (
"fmt"
exec "internal/execabs"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"

View File

@ -13,11 +13,11 @@ import (
"go/ast"
"go/printer"
"go/token"
exec "internal/execabs"
"internal/xcoff"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"sort"

View File

@ -8,9 +8,9 @@ import (
"bytes"
"fmt"
"go/token"
exec "internal/execabs"
"io/ioutil"
"os"
"os/exec"
)
// run runs the command argv, feeding in stdin on standard input.
@ -63,7 +63,7 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
p.Env = append(os.Environ(), "TERM=dumb")
err := p.Run()
if _, ok := err.(*exec.ExitError); err != nil && !ok {
fatalf("%s", err)
fatalf("exec %s: %s", argv[0], err)
}
ok = p.ProcessState.Success()
stdout, stderr = bout.Bytes(), berr.Bytes()
@ -88,7 +88,7 @@ func fatalf(msg string, args ...interface{}) {
// If we've already printed other errors, they might have
// caused the fatal condition. Assume they're enough.
if nerrors == 0 {
fmt.Fprintf(os.Stderr, msg+"\n", args...)
fmt.Fprintf(os.Stderr, "cgo: "+msg+"\n", args...)
}
os.Exit(2)
}

View File

@ -9,9 +9,9 @@ import (
"cmd/internal/src"
"fmt"
"html"
exec "internal/execabs"
"io"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"

View File

@ -15,9 +15,9 @@ import (
"go/ast"
"go/parser"
"go/token"
exec "internal/execabs"
"io"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"

View File

@ -16,7 +16,7 @@ package main
import (
"os"
"os/exec"
exec "internal/execabs"
"strings"
)

View File

@ -298,8 +298,10 @@ func bootstrapFixImports(srcFile string) string {
continue
}
if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) {
inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"") || strings.HasPrefix(line, "\texec \"")) {
line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1)
// During bootstrap, must use plain os/exec.
line = strings.Replace(line, `exec "internal/execabs"`, `"os/exec"`, -1)
for _, dir := range bootstrapDirs {
if strings.HasPrefix(dir, "cmd/") {
continue

View File

@ -7,9 +7,9 @@ package main
import (
"bytes"
"fmt"
exec "internal/execabs"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"

View File

@ -9,9 +9,9 @@ import (
"go/ast"
"go/parser"
"go/token"
exec "internal/execabs"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"reflect"
"runtime"

View File

@ -12,9 +12,9 @@ import (
"flag"
"fmt"
"go/scanner"
exec "internal/execabs"
"log"
"os"
"os/exec"
"strings"
"sync"

View File

@ -8,11 +8,11 @@ package bug
import (
"bytes"
"fmt"
exec "internal/execabs"
"io"
"io/ioutil"
urlpkg "net/url"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"

View File

@ -9,10 +9,10 @@ import (
"bufio"
"bytes"
"fmt"
exec "internal/execabs"
"io"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"

View File

@ -10,10 +10,10 @@ import (
"bytes"
"crypto/sha256"
"fmt"
exec "internal/execabs"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"

View File

@ -8,11 +8,11 @@ import (
"bytes"
"errors"
"fmt"
exec "internal/execabs"
"io"
"io/ioutil"
"net/url"
"os"
"os/exec"
"path/filepath"
"sort"
"strconv"

View File

@ -10,10 +10,10 @@ import (
"errors"
"fmt"
"go/build"
exec "internal/execabs"
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"

View File

@ -7,8 +7,8 @@ package tool
import (
"fmt"
exec "internal/execabs"
"os"
"os/exec"
"sort"
"strings"

View File

@ -9,9 +9,9 @@ import (
"encoding/json"
"flag"
"fmt"
exec "internal/execabs"
"log"
"os"
"os/exec"
"path/filepath"
"strings"

View File

@ -56,6 +56,9 @@ type Builder struct {
id sync.Mutex
toolIDCache map[string]string // tool name -> tool ID
buildIDCache map[string]string // file name -> build ID
cgoEnvOnce sync.Once
cgoEnvCache []string
}
// NOTE: Much of Action would not need to be exported if not for test.

View File

@ -8,8 +8,8 @@ import (
"errors"
"fmt"
"go/build"
exec "internal/execabs"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"

View File

@ -7,9 +7,9 @@ package work
import (
"bytes"
"fmt"
exec "internal/execabs"
"io/ioutil"
"os"
"os/exec"
"strings"
"cmd/go/internal/base"

View File

@ -16,13 +16,13 @@ import (
"encoding/json"
"errors"
"fmt"
exec "internal/execabs"
"internal/lazyregexp"
"io"
"io/ioutil"
"log"
"math/rand"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
@ -1075,10 +1075,8 @@ func (b *Builder) vet(a *Action) error {
return err
}
env := b.cCompilerEnv()
if cfg.BuildToolchainName == "gccgo" {
env = append(env, "GCCGO="+BuildToolchain.compiler())
}
// TODO(rsc): Why do we pass $GCCGO to go vet?
env := b.cgoEnv()
p := a.Package
tool := VetTool
@ -1920,6 +1918,9 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...interfa
var buf bytes.Buffer
cmd := exec.Command(cmdline[0], cmdline[1:]...)
if cmd.Path != "" {
cmd.Args[0] = cmd.Path
}
cmd.Stdout = &buf
cmd.Stderr = &buf
cleanup := passLongArgsInResponseFiles(cmd)
@ -1979,6 +1980,24 @@ func (b *Builder) cCompilerEnv() []string {
return []string{"TERM=dumb"}
}
// cgoEnv returns environment variables to set when running cgo.
// Some of these pass through to cgo running the C compiler,
// so it includes cCompilerEnv.
func (b *Builder) cgoEnv() []string {
b.cgoEnvOnce.Do(func() {
cc, err := exec.LookPath(b.ccExe()[0])
if err != nil || filepath.Base(cc) == cc { // reject relative path
cc = "/missing-cc"
}
gccgo := GccgoBin
if filepath.Base(gccgo) == gccgo { // reject relative path
gccgo = "/missing-gccgo"
}
b.cgoEnvCache = append(b.cCompilerEnv(), "CC="+cc, "GCCGO="+gccgo)
})
return b.cgoEnvCache
}
// mkdir makes the named directory.
func (b *Builder) Mkdir(dir string) error {
// Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "".
@ -2524,13 +2543,13 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
// along to the host linker. At this point in the code, cgoLDFLAGS
// consists of the original $CGO_LDFLAGS (unchecked) and all the
// flags put together from source code (checked).
cgoenv := b.cCompilerEnv()
cgoenv := b.cgoEnv()
if len(cgoLDFLAGS) > 0 {
flags := make([]string, len(cgoLDFLAGS))
for i, f := range cgoLDFLAGS {
flags[i] = strconv.Quote(f)
}
cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
cgoenv = append(cgoenv, "CGO_LDFLAGS="+strings.Join(flags, " "))
}
if cfg.BuildToolchainName == "gccgo" {
@ -2745,7 +2764,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe
if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = []string{"-dynlinker"} // record path to dynamic linker
}
return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
return b.run(a, p.Dir, p.ImportPath, b.cgoEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
}
// Run SWIG on all SWIG input files.

View File

@ -6,9 +6,9 @@ package work
import (
"fmt"
exec "internal/execabs"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"

View File

@ -25,7 +25,7 @@ import (
"io/ioutil"
"log"
"os"
"os/exec"
exec "internal/execabs"
"path/filepath"
"strings"

35
src/cmd/go/testdata/script/cgo_path.txt vendored Normal file
View File

@ -0,0 +1,35 @@
[!cgo] skip
env GOCACHE=$WORK/gocache # Looking for compile flags, so need a clean cache.
[!windows] env PATH=.:$PATH
[!windows] chmod 0777 p/gcc p/clang
[!windows] exists p/gcc p/clang
[windows] exists p/gcc.bat p/clang.bat
! exists p/bug.txt
go build -x
! exists p/bug.txt
-- go.mod --
module m
-- m.go --
package m
import _ "m/p"
-- p/p.go --
package p
// #define X 1
import "C"
-- p/gcc --
#!/bin/sh
echo ran gcc >bug.txt
-- p/clang --
#!/bin/sh
echo ran clang >bug.txt
-- p/gcc.bat --
echo ran gcc >bug.txt
-- p/clang.bat --
echo ran clang >bug.txt

View File

@ -6,8 +6,8 @@
package browser
import (
exec "internal/execabs"
"os"
"os/exec"
"runtime"
"time"
)

View File

@ -7,9 +7,9 @@
package diff
import (
exec "internal/execabs"
"io/ioutil"
"os"
"os/exec"
"runtime"
)

View File

@ -12,7 +12,7 @@ import (
"cmd/internal/objabi"
"errors"
"fmt"
"os/exec"
exec "internal/execabs"
"sort"
"strconv"
"strings"

View File

@ -7,8 +7,8 @@
package ld
import (
exec "internal/execabs"
"os"
"os/exec"
"path/filepath"
"syscall"
)

View File

@ -51,11 +51,11 @@ import (
"encoding/binary"
"encoding/hex"
"fmt"
exec "internal/execabs"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"sort"

View File

@ -82,9 +82,9 @@ package main
import (
"flag"
"fmt"
exec "internal/execabs"
"io"
"os"
"os/exec"
"cmd/internal/test2json"
)

View File

@ -9,12 +9,12 @@ package main
import (
"bufio"
"fmt"
exec "internal/execabs"
"internal/trace"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"sort"

View File

@ -386,10 +386,11 @@ func p224Invert(out, in *p224FieldElement) {
// p224Contract converts a FieldElement to its unique, minimal form.
//
// On entry, in[i] < 2**29
// On exit, in[i] < 2**28
// On exit, out[i] < 2**28 and out < p
func p224Contract(out, in *p224FieldElement) {
copy(out[:], in[:])
// First, carry the bits above 28 to the higher limb.
for i := 0; i < 7; i++ {
out[i+1] += out[i] >> 28
out[i] &= bottom28Bits
@ -397,10 +398,13 @@ func p224Contract(out, in *p224FieldElement) {
top := out[7] >> 28
out[7] &= bottom28Bits
// Use the reduction identity to carry the overflow.
//
// a + top * 2²²⁴ = a + top * 2⁹⁶ - top
out[0] -= top
out[3] += top << 12
// We may just have made out[i] negative. So we carry down. If we made
// We may just have made out[0] negative. So we carry down. If we made
// out[0] negative then we know that out[3] is sufficiently positive
// because we just added to it.
for i := 0; i < 3; i++ {
@ -425,13 +429,12 @@ func p224Contract(out, in *p224FieldElement) {
// There are two cases to consider for out[3]:
// 1) The first time that we eliminated top, we didn't push out[3] over
// 2**28. In this case, the partial carry chain didn't change any values
// and top is zero.
// and top is now zero.
// 2) We did push out[3] over 2**28 the first time that we eliminated top.
// The first value of top was in [0..16), therefore, prior to eliminating
// the first top, 0xfff1000 <= out[3] <= 0xfffffff. Therefore, after
// overflowing and being reduced by the second carry chain, out[3] <=
// 0xf000. Thus it cannot have overflowed when we eliminated top for the
// second time.
// The first value of top was in [0..2], therefore, after overflowing
// and being reduced by the second carry chain, out[3] <= 2<<12 - 1.
// In both cases, out[3] cannot have overflowed when we eliminated top for
// the second time.
// Again, we may just have made out[0] negative, so do the same carry down.
// As before, if we made out[0] negative then we know that out[3] is
@ -470,12 +473,11 @@ func p224Contract(out, in *p224FieldElement) {
bottom3NonZero |= bottom3NonZero >> 1
bottom3NonZero = uint32(int32(bottom3NonZero<<31) >> 31)
// Everything depends on the value of out[3].
// If it's > 0xffff000 and top4AllOnes != 0 then the whole value is >= p
// If it's = 0xffff000 and top4AllOnes != 0 and bottom3NonZero != 0,
// then the whole value is >= p
// Assuming top4AllOnes != 0, everything depends on the value of out[3].
// If it's > 0xffff000 then the whole value is > p
// If it's = 0xffff000 and bottom3NonZero != 0, then the whole value is >= p
// If it's < 0xffff000, then the whole value is < p
n := out[3] - 0xffff000
n := 0xffff000 - out[3]
out3Equal := n
out3Equal |= out3Equal >> 16
out3Equal |= out3Equal >> 8
@ -484,8 +486,8 @@ func p224Contract(out, in *p224FieldElement) {
out3Equal |= out3Equal >> 1
out3Equal = ^uint32(int32(out3Equal<<31) >> 31)
// If out[3] > 0xffff000 then n's MSB will be zero.
out3GT := ^uint32(int32(n) >> 31)
// If out[3] > 0xffff000 then n's MSB will be one.
out3GT := uint32(int32(n) >> 31)
mask := top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT)
out[0] -= 1 & mask
@ -494,6 +496,15 @@ func p224Contract(out, in *p224FieldElement) {
out[5] -= 0xfffffff & mask
out[6] -= 0xfffffff & mask
out[7] -= 0xfffffff & mask
// Do one final carry down, in case we made out[0] negative. One of
// out[0..3] needs to be positive and able to absorb the -1 or the value
// would have been < p, and the subtraction wouldn't have happened.
for i := 0; i < 3; i++ {
mask := uint32(int32(out[i]) >> 31)
out[i] += (1 << 28) & mask
out[i+1] -= 1 & mask
}
}
// Group element functions.

View File

@ -6,7 +6,11 @@ package elliptic
import (
"math/big"
"math/bits"
"math/rand"
"reflect"
"testing"
"testing/quick"
)
var toFromBigTests = []string{
@ -21,16 +25,16 @@ func p224AlternativeToBig(in *p224FieldElement) *big.Int {
ret := new(big.Int)
tmp := new(big.Int)
for i := uint(0); i < 8; i++ {
for i := len(in) - 1; i >= 0; i-- {
ret.Lsh(ret, 28)
tmp.SetInt64(int64(in[i]))
tmp.Lsh(tmp, 28*i)
ret.Add(ret, tmp)
}
ret.Mod(ret, p224.P)
ret.Mod(ret, P224().Params().P)
return ret
}
func TestToFromBig(t *testing.T) {
func TestP224ToFromBig(t *testing.T) {
for i, test := range toFromBigTests {
n, _ := new(big.Int).SetString(test, 16)
var x p224FieldElement
@ -41,7 +45,270 @@ func TestToFromBig(t *testing.T) {
}
q := p224AlternativeToBig(&x)
if n.Cmp(q) != 0 {
t.Errorf("#%d: %x != %x (alternative)", i, n, m)
t.Errorf("#%d: %x != %x (alternative)", i, n, q)
}
}
}
// quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks)
// times. The default value of -quickchecks is 100.
var quickCheckConfig32 = &quick.Config{MaxCountScale: 32}
// weirdLimbs can be combined to generate a range of edge-case field elements.
var weirdLimbs = [...]uint32{
0, 1, (1 << 29) - 1,
(1 << 12), (1 << 12) - 1,
(1 << 28), (1 << 28) - 1,
}
func generateLimb(rand *rand.Rand) uint32 {
const bottom29Bits = 0x1fffffff
n := rand.Intn(len(weirdLimbs) + 3)
switch n {
case len(weirdLimbs):
// Random value.
return uint32(rand.Int31n(1 << 29))
case len(weirdLimbs) + 1:
// Sum of two values.
k := generateLimb(rand) + generateLimb(rand)
return k & bottom29Bits
case len(weirdLimbs) + 2:
// Difference of two values.
k := generateLimb(rand) - generateLimb(rand)
return k & bottom29Bits
default:
return weirdLimbs[n]
}
}
func (p224FieldElement) Generate(rand *rand.Rand, size int) reflect.Value {
return reflect.ValueOf(p224FieldElement{
weirdLimbs[rand.Intn(len(weirdLimbs))],
weirdLimbs[rand.Intn(len(weirdLimbs))],
weirdLimbs[rand.Intn(len(weirdLimbs))],
weirdLimbs[rand.Intn(len(weirdLimbs))],
weirdLimbs[rand.Intn(len(weirdLimbs))],
weirdLimbs[rand.Intn(len(weirdLimbs))],
weirdLimbs[rand.Intn(len(weirdLimbs))],
weirdLimbs[rand.Intn(len(weirdLimbs))],
})
}
func isInBounds(x *p224FieldElement) bool {
return bits.Len32(x[0]) <= 29 &&
bits.Len32(x[1]) <= 29 &&
bits.Len32(x[2]) <= 29 &&
bits.Len32(x[3]) <= 29 &&
bits.Len32(x[4]) <= 29 &&
bits.Len32(x[5]) <= 29 &&
bits.Len32(x[6]) <= 29 &&
bits.Len32(x[7]) <= 29
}
func TestP224Mul(t *testing.T) {
mulMatchesBigInt := func(a, b, out p224FieldElement) bool {
var tmp p224LargeFieldElement
p224Mul(&out, &a, &b, &tmp)
exp := new(big.Int).Mul(p224AlternativeToBig(&a), p224AlternativeToBig(&b))
exp.Mod(exp, P224().Params().P)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 || !isInBounds(&out) {
t.Logf("a = %x", a)
t.Logf("b = %x", b)
t.Logf("p224Mul(a, b) = %x = %v", out, got)
t.Logf("a * b = %v", exp)
return false
}
return true
}
a := p224FieldElement{0xfffffff, 0xfffffff, 0xf00ffff, 0x20f, 0x0, 0x0, 0x0, 0x0}
b := p224FieldElement{1, 0, 0, 0, 0, 0, 0, 0}
if !mulMatchesBigInt(a, b, p224FieldElement{}) {
t.Fail()
}
if err := quick.Check(mulMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Square(t *testing.T) {
squareMatchesBigInt := func(a, out p224FieldElement) bool {
var tmp p224LargeFieldElement
p224Square(&out, &a, &tmp)
exp := p224AlternativeToBig(&a)
exp.Mul(exp, exp)
exp.Mod(exp, P224().Params().P)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 || !isInBounds(&out) {
t.Logf("a = %x", a)
t.Logf("p224Square(a, b) = %x = %v", out, got)
t.Logf("a * a = %v", exp)
return false
}
return true
}
if err := quick.Check(squareMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Add(t *testing.T) {
addMatchesBigInt := func(a, b, out p224FieldElement) bool {
p224Add(&out, &a, &b)
exp := new(big.Int).Add(p224AlternativeToBig(&a), p224AlternativeToBig(&b))
exp.Mod(exp, P224().Params().P)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 {
t.Logf("a = %x", a)
t.Logf("b = %x", b)
t.Logf("p224Add(a, b) = %x = %v", out, got)
t.Logf("a + b = %v", exp)
return false
}
return true
}
if err := quick.Check(addMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Reduce(t *testing.T) {
reduceMatchesBigInt := func(a p224FieldElement) bool {
out := a
// TODO: generate higher values for functions like p224Reduce that are
// expected to work with higher input bounds.
p224Reduce(&out)
exp := p224AlternativeToBig(&a)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 || !isInBounds(&out) {
t.Logf("a = %x = %v", a, exp)
t.Logf("p224Reduce(a) = %x = %v", out, got)
return false
}
return true
}
if err := quick.Check(reduceMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Contract(t *testing.T) {
contractMatchesBigInt := func(a, out p224FieldElement) bool {
p224Contract(&out, &a)
exp := p224AlternativeToBig(&a)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 {
t.Logf("a = %x = %v", a, exp)
t.Logf("p224Contract(a) = %x = %v", out, got)
return false
}
// Check that out < P.
for i := range p224P {
k := 8 - i - 1
if out[k] > p224P[k] {
t.Logf("p224Contract(a) = %x", out)
return false
}
if out[k] < p224P[k] {
return true
}
}
t.Logf("p224Contract(a) = %x", out)
return false
}
if !contractMatchesBigInt(p224P, p224FieldElement{}) {
t.Error("p224Contract(p) is broken")
}
pMinus1 := p224FieldElement{0, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
if !contractMatchesBigInt(pMinus1, p224FieldElement{}) {
t.Error("p224Contract(p - 1) is broken")
}
// Check that we can handle input above p, but lowest limb zero.
a := p224FieldElement{0, 1, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
if !contractMatchesBigInt(a, p224FieldElement{}) {
t.Error("p224Contract(p + 2²⁸) is broken")
}
// Check that we can handle input above p, but lowest three limbs zero.
b := p224FieldElement{0, 0, 0, 0xffff001, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
if !contractMatchesBigInt(b, p224FieldElement{}) {
t.Error("p224Contract(p + 2⁸⁴) is broken")
}
if err := quick.Check(contractMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224IsZero(t *testing.T) {
if got := p224IsZero(&p224FieldElement{}); got != 1 {
t.Errorf("p224IsZero(0) = %d, expected 1", got)
}
if got := p224IsZero((*p224FieldElement)(&p224P)); got != 1 {
t.Errorf("p224IsZero(p) = %d, expected 1", got)
}
if got := p224IsZero(&p224FieldElement{1}); got != 0 {
t.Errorf("p224IsZero(1) = %d, expected 0", got)
}
isZeroMatchesBigInt := func(a p224FieldElement) bool {
isZero := p224IsZero(&a)
big := p224AlternativeToBig(&a)
if big.Sign() == 0 && isZero != 1 {
return false
}
if big.Sign() != 0 && isZero != 0 {
return false
}
return true
}
if err := quick.Check(isZeroMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Invert(t *testing.T) {
var out p224FieldElement
p224Invert(&out, &p224FieldElement{})
if got := p224IsZero(&out); got != 1 {
t.Errorf("p224Invert(0) = %x, expected 0", out)
}
p224Invert(&out, (*p224FieldElement)(&p224P))
if got := p224IsZero(&out); got != 1 {
t.Errorf("p224Invert(p) = %x, expected 0", out)
}
p224Invert(&out, &p224FieldElement{1})
p224Contract(&out, &out)
if out != (p224FieldElement{1}) {
t.Errorf("p224Invert(1) = %x, expected 1", out)
}
var tmp p224LargeFieldElement
a := p224FieldElement{1, 2, 3, 4, 5, 6, 7, 8}
p224Invert(&out, &a)
p224Mul(&out, &out, &a, &tmp)
p224Contract(&out, &out)
if out != (p224FieldElement{1}) {
t.Errorf("p224Invert(a) * a = %x, expected 1", out)
}
}

View File

@ -12,13 +12,13 @@ import (
"go/doc"
"go/parser"
"go/token"
exec "internal/execabs"
"internal/goroot"
"internal/goversion"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
pathpkg "path"
"path/filepath"
"runtime"

View File

@ -207,6 +207,8 @@ var pkgDeps = map[string][]string{
"internal/lazyregexp": {"L2", "OS", "regexp"},
"internal/lazytemplate": {"L2", "OS", "text/template"},
"internal/execabs": {"L2", "OS", "fmt", "context", "reflect"},
// L4 is defined as L3+fmt+log+time, because in general once
// you're using L3 packages, use of fmt, log, or time is not a big deal.
"L4": {
@ -240,7 +242,7 @@ var pkgDeps = map[string][]string{
"go/constant": {"L4", "go/token", "math/big"},
"go/importer": {"L4", "go/build", "go/internal/gccgoimporter", "go/internal/gcimporter", "go/internal/srcimporter", "go/token", "go/types"},
"go/internal/gcimporter": {"L4", "OS", "go/build", "go/constant", "go/token", "go/types", "text/scanner"},
"go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "go/constant", "go/token", "go/types", "internal/xcoff", "text/scanner"},
"go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "go/constant", "go/token", "go/types", "internal/xcoff", "text/scanner", "internal/execabs"},
"go/internal/srcimporter": {"L4", "OS", "fmt", "go/ast", "go/build", "go/parser", "go/token", "go/types", "path/filepath"},
"go/types": {"L4", "GOPARSER", "container/heap", "go/constant"},
@ -272,7 +274,7 @@ var pkgDeps = map[string][]string{
"encoding/pem": {"L4"},
"encoding/xml": {"L4", "encoding"},
"flag": {"L4", "OS"},
"go/build": {"L4", "OS", "GOPARSER", "internal/goroot", "internal/goversion"},
"go/build": {"L4", "OS", "GOPARSER", "internal/goroot", "internal/goversion", "internal/execabs"},
"html": {"L4"},
"image/draw": {"L4", "image/internal/imageutil"},
"image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"},
@ -280,7 +282,7 @@ var pkgDeps = map[string][]string{
"image/jpeg": {"L4", "image/internal/imageutil"},
"image/png": {"L4", "compress/zlib"},
"index/suffixarray": {"L4", "regexp"},
"internal/goroot": {"L4", "OS"},
"internal/goroot": {"L4", "OS", "internal/execabs"},
"internal/singleflight": {"sync"},
"internal/trace": {"L4", "OS", "container/heap"},
"internal/xcoff": {"L4", "OS", "debug/dwarf"},

View File

@ -7,8 +7,8 @@ package gccgoimporter
import (
"bufio"
"go/types"
exec "internal/execabs"
"os"
"os/exec"
"path/filepath"
"strings"
)

View File

@ -0,0 +1,70 @@
// Copyright 2020 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 execabs is a drop-in replacement for os/exec
// that requires PATH lookups to find absolute paths.
// That is, execabs.Command("cmd") runs the same PATH lookup
// as exec.Command("cmd"), but if the result is a path
// which is relative, the Run and Start methods will report
// an error instead of running the executable.
package execabs
import (
"context"
"fmt"
"os/exec"
"path/filepath"
"reflect"
"unsafe"
)
var ErrNotFound = exec.ErrNotFound
type (
Cmd = exec.Cmd
Error = exec.Error
ExitError = exec.ExitError
)
func relError(file, path string) error {
return fmt.Errorf("%s resolves to executable in current directory (.%c%s)", file, filepath.Separator, path)
}
func LookPath(file string) (string, error) {
path, err := exec.LookPath(file)
if err != nil {
return "", err
}
if filepath.Base(file) == file && !filepath.IsAbs(path) {
return "", relError(file, path)
}
return path, nil
}
func fixCmd(name string, cmd *exec.Cmd) {
if filepath.Base(name) == name && !filepath.IsAbs(cmd.Path) {
// exec.Command was called with a bare binary name and
// exec.LookPath returned a path which is not absolute.
// Set cmd.lookPathErr and clear cmd.Path so that it
// cannot be run.
lookPathErr := (*error)(unsafe.Pointer(reflect.ValueOf(cmd).Elem().FieldByName("lookPathErr").Addr().Pointer()))
if *lookPathErr == nil {
*lookPathErr = relError(name, cmd.Path)
}
cmd.Path = ""
}
}
func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd {
cmd := exec.CommandContext(ctx, name, arg...)
fixCmd(name, cmd)
return cmd
}
func Command(name string, arg ...string) *exec.Cmd {
cmd := exec.Command(name, arg...)
fixCmd(name, cmd)
return cmd
}

View File

@ -0,0 +1,107 @@
// Copyright 2020 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 execabs
import (
"context"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"testing"
)
func TestFixCmd(t *testing.T) {
cmd := &exec.Cmd{Path: "hello"}
fixCmd("hello", cmd)
if cmd.Path != "" {
t.Errorf("fixCmd didn't clear cmd.Path")
}
expectedErr := fmt.Sprintf("hello resolves to executable in current directory (.%chello)", filepath.Separator)
if err := cmd.Run(); err == nil {
t.Fatal("Command.Run didn't fail")
} else if err.Error() != expectedErr {
t.Fatalf("Command.Run returned unexpected error: want %q, got %q", expectedErr, err.Error())
}
}
func TestCommand(t *testing.T) {
for _, cmd := range []func(string) *Cmd{
func(s string) *Cmd { return Command(s) },
func(s string) *Cmd { return CommandContext(context.Background(), s) },
} {
tmpDir, err := ioutil.TempDir("", "execabs-test")
if err != nil {
t.Fatalf("ioutil.TempDir failed: %s", err)
}
defer os.RemoveAll(tmpDir)
executable := "execabs-test"
if runtime.GOOS == "windows" {
executable += ".exe"
}
if err = ioutil.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
t.Fatalf("ioutil.WriteFile failed: %s", err)
}
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("os.Getwd failed: %s", err)
}
defer os.Chdir(cwd)
if err = os.Chdir(tmpDir); err != nil {
t.Fatalf("os.Chdir failed: %s", err)
}
if runtime.GOOS != "windows" {
// add "." to PATH so that exec.LookPath looks in the current directory on
// non-windows platforms as well
origPath := os.Getenv("PATH")
defer os.Setenv("PATH", origPath)
os.Setenv("PATH", fmt.Sprintf(".:%s", origPath))
}
expectedErr := fmt.Sprintf("execabs-test resolves to executable in current directory (.%c%s)", filepath.Separator, executable)
if err = cmd("execabs-test").Run(); err == nil {
t.Fatalf("Command.Run didn't fail when exec.LookPath returned a relative path")
} else if err.Error() != expectedErr {
t.Errorf("Command.Run returned unexpected error: want %q, got %q", expectedErr, err.Error())
}
}
}
func TestLookPath(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "execabs-test")
if err != nil {
t.Fatalf("ioutil.TempDir failed: %s", err)
}
defer os.RemoveAll(tmpDir)
executable := "execabs-test"
if runtime.GOOS == "windows" {
executable += ".exe"
}
if err = ioutil.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
t.Fatalf("ioutil.WriteFile failed: %s", err)
}
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("os.Getwd failed: %s", err)
}
defer os.Chdir(cwd)
if err = os.Chdir(tmpDir); err != nil {
t.Fatalf("os.Chdir failed: %s", err)
}
if runtime.GOOS != "windows" {
// add "." to PATH so that exec.LookPath looks in the current directory on
// non-windows platforms as well
origPath := os.Getenv("PATH")
defer os.Setenv("PATH", origPath)
os.Setenv("PATH", fmt.Sprintf(".:%s", origPath))
}
expectedErr := fmt.Sprintf("execabs-test resolves to executable in current directory (.%c%s)", filepath.Separator, executable)
if _, err := LookPath("execabs-test"); err == nil {
t.Fatalf("LookPath didn't fail when finding a non-relative path")
} else if err.Error() != expectedErr {
t.Errorf("LookPath returned unexpected error: want %q, got %q", expectedErr, err.Error())
}
}

View File

@ -7,8 +7,8 @@
package goroot
import (
exec "internal/execabs"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"