[dev.boringcrypto.go1.14] all: merge go1.14.14 into dev.boringcrypto.go1.14

Change-Id: I3f120b8b0f009108457de97302700b45757a557c
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index b46b310..26eb328 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -16,11 +16,11 @@
 	"go/parser"
 	"go/token"
 	"go/types"
+	exec "internal/execabs"
 	"io"
 	"io/ioutil"
 	"log"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"regexp"
 	"runtime"
diff --git a/src/cmd/api/run.go b/src/cmd/api/run.go
index a36f117..ecb1d0f 100644
--- a/src/cmd/api/run.go
+++ b/src/cmd/api/run.go
@@ -10,9 +10,9 @@
 
 import (
 	"fmt"
+	exec "internal/execabs"
 	"log"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"runtime"
 	"strings"
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index d447bcb..698181c 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -13,11 +13,11 @@
 	"go/ast"
 	"go/printer"
 	"go/token"
+	exec "internal/execabs"
 	"internal/xcoff"
 	"io"
 	"io/ioutil"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"regexp"
 	"sort"
diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go
index 921306b..00d931b 100644
--- a/src/cmd/cgo/util.go
+++ b/src/cmd/cgo/util.go
@@ -8,9 +8,9 @@
 	"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 @@
 	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 @@
 	// 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)
 }
diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go
index 1e76a67..068c382 100644
--- a/src/cmd/compile/internal/ssa/html.go
+++ b/src/cmd/compile/internal/ssa/html.go
@@ -9,9 +9,9 @@
 	"cmd/internal/src"
 	"fmt"
 	"html"
+	exec "internal/execabs"
 	"io"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"strconv"
 	"strings"
diff --git a/src/cmd/cover/func.go b/src/cmd/cover/func.go
index 988c4ca..ce7c771 100644
--- a/src/cmd/cover/func.go
+++ b/src/cmd/cover/func.go
@@ -15,9 +15,9 @@
 	"go/ast"
 	"go/parser"
 	"go/token"
+	exec "internal/execabs"
 	"io"
 	"os"
-	"os/exec"
 	"path"
 	"path/filepath"
 	"runtime"
diff --git a/src/cmd/cover/testdata/toolexec.go b/src/cmd/cover/testdata/toolexec.go
index 1769efe..386de79 100644
--- a/src/cmd/cover/testdata/toolexec.go
+++ b/src/cmd/cover/testdata/toolexec.go
@@ -16,7 +16,7 @@
 
 import (
 	"os"
-	"os/exec"
+	exec "internal/execabs"
 	"strings"
 )
 
diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
index a07e64b..095ebbd 100644
--- a/src/cmd/dist/buildtool.go
+++ b/src/cmd/dist/buildtool.go
@@ -298,8 +298,10 @@
 			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
diff --git a/src/cmd/doc/dirs.go b/src/cmd/doc/dirs.go
index 38cbe7f..661624c 100644
--- a/src/cmd/doc/dirs.go
+++ b/src/cmd/doc/dirs.go
@@ -7,9 +7,9 @@
 import (
 	"bytes"
 	"fmt"
+	exec "internal/execabs"
 	"log"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"regexp"
 	"strings"
diff --git a/src/cmd/fix/typecheck.go b/src/cmd/fix/typecheck.go
index 66e0cdc..8390e44 100644
--- a/src/cmd/fix/typecheck.go
+++ b/src/cmd/fix/typecheck.go
@@ -9,9 +9,9 @@
 	"go/ast"
 	"go/parser"
 	"go/token"
+	exec "internal/execabs"
 	"io/ioutil"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"reflect"
 	"runtime"
diff --git a/src/cmd/go/internal/base/base.go b/src/cmd/go/internal/base/base.go
index 272da55..15e6035 100644
--- a/src/cmd/go/internal/base/base.go
+++ b/src/cmd/go/internal/base/base.go
@@ -12,9 +12,9 @@
 	"flag"
 	"fmt"
 	"go/scanner"
+	exec "internal/execabs"
 	"log"
 	"os"
-	"os/exec"
 	"strings"
 	"sync"
 
diff --git a/src/cmd/go/internal/bug/bug.go b/src/cmd/go/internal/bug/bug.go
index fe71281..9434bc2 100644
--- a/src/cmd/go/internal/bug/bug.go
+++ b/src/cmd/go/internal/bug/bug.go
@@ -8,11 +8,11 @@
 import (
 	"bytes"
 	"fmt"
+	exec "internal/execabs"
 	"io"
 	"io/ioutil"
 	urlpkg "net/url"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"regexp"
 	"runtime"
diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go
index 315db69..758fa3b 100644
--- a/src/cmd/go/internal/generate/generate.go
+++ b/src/cmd/go/internal/generate/generate.go
@@ -9,10 +9,10 @@
 	"bufio"
 	"bytes"
 	"fmt"
+	exec "internal/execabs"
 	"io"
 	"log"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"regexp"
 	"strconv"
diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go
index 5867288..383981d 100644
--- a/src/cmd/go/internal/modfetch/codehost/codehost.go
+++ b/src/cmd/go/internal/modfetch/codehost/codehost.go
@@ -10,10 +10,10 @@
 	"bytes"
 	"crypto/sha256"
 	"fmt"
+	exec "internal/execabs"
 	"io"
 	"io/ioutil"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"strings"
 	"sync"
diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go
index f08df51..aa696ec 100644
--- a/src/cmd/go/internal/modfetch/codehost/git.go
+++ b/src/cmd/go/internal/modfetch/codehost/git.go
@@ -8,11 +8,11 @@
 	"bytes"
 	"errors"
 	"fmt"
+	exec "internal/execabs"
 	"io"
 	"io/ioutil"
 	"net/url"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"sort"
 	"strconv"
diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go
index 4ad142c..a23a1bb 100644
--- a/src/cmd/go/internal/test/test.go
+++ b/src/cmd/go/internal/test/test.go
@@ -10,10 +10,10 @@
 	"errors"
 	"fmt"
 	"go/build"
+	exec "internal/execabs"
 	"io"
 	"io/ioutil"
 	"os"
-	"os/exec"
 	"path"
 	"path/filepath"
 	"regexp"
diff --git a/src/cmd/go/internal/tool/tool.go b/src/cmd/go/internal/tool/tool.go
index 930eecb..f06c903 100644
--- a/src/cmd/go/internal/tool/tool.go
+++ b/src/cmd/go/internal/tool/tool.go
@@ -7,8 +7,8 @@
 
 import (
 	"fmt"
+	exec "internal/execabs"
 	"os"
-	"os/exec"
 	"sort"
 	"strings"
 
diff --git a/src/cmd/go/internal/vet/vetflag.go b/src/cmd/go/internal/vet/vetflag.go
index e3de48b..052b8f1 100644
--- a/src/cmd/go/internal/vet/vetflag.go
+++ b/src/cmd/go/internal/vet/vetflag.go
@@ -9,9 +9,9 @@
 	"encoding/json"
 	"flag"
 	"fmt"
+	exec "internal/execabs"
 	"log"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"strings"
 
diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go
index e3cb87f..8256681 100644
--- a/src/cmd/go/internal/work/action.go
+++ b/src/cmd/go/internal/work/action.go
@@ -56,6 +56,9 @@
 	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.
diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go
index e3b25c9..c19e6f1 100644
--- a/src/cmd/go/internal/work/build.go
+++ b/src/cmd/go/internal/work/build.go
@@ -8,8 +8,8 @@
 	"errors"
 	"fmt"
 	"go/build"
+	exec "internal/execabs"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"runtime"
 	"strings"
diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go
index 7558a30..5fbdbb6 100644
--- a/src/cmd/go/internal/work/buildid.go
+++ b/src/cmd/go/internal/work/buildid.go
@@ -7,9 +7,9 @@
 import (
 	"bytes"
 	"fmt"
+	exec "internal/execabs"
 	"io/ioutil"
 	"os"
-	"os/exec"
 	"strings"
 
 	"cmd/go/internal/base"
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index a87bc80..8230d85 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -16,13 +16,13 @@
 	"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 @@
 		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 @@
 
 	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 @@
 	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 @@
 	// 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 @@
 	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.
diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go
index 4c1f36d..2f5d5d6 100644
--- a/src/cmd/go/internal/work/gccgo.go
+++ b/src/cmd/go/internal/work/gccgo.go
@@ -6,9 +6,9 @@
 
 import (
 	"fmt"
+	exec "internal/execabs"
 	"io/ioutil"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"strings"
 
diff --git a/src/cmd/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go
index d9c3aab..9c74cf5 100644
--- a/src/cmd/go/testdata/addmod.go
+++ b/src/cmd/go/testdata/addmod.go
@@ -25,7 +25,7 @@
 	"io/ioutil"
 	"log"
 	"os"
-	"os/exec"
+	exec "internal/execabs"
 	"path/filepath"
 	"strings"
 
diff --git a/src/cmd/go/testdata/script/cgo_path.txt b/src/cmd/go/testdata/script/cgo_path.txt
new file mode 100644
index 0000000..e4d07de
--- /dev/null
+++ b/src/cmd/go/testdata/script/cgo_path.txt
@@ -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
diff --git a/src/cmd/internal/browser/browser.go b/src/cmd/internal/browser/browser.go
index 6867c85..577d317 100644
--- a/src/cmd/internal/browser/browser.go
+++ b/src/cmd/internal/browser/browser.go
@@ -6,8 +6,8 @@
 package browser
 
 import (
+	exec "internal/execabs"
 	"os"
-	"os/exec"
 	"runtime"
 	"time"
 )
diff --git a/src/cmd/internal/diff/diff.go b/src/cmd/internal/diff/diff.go
index e9d2c23..c0ca2f3 100644
--- a/src/cmd/internal/diff/diff.go
+++ b/src/cmd/internal/diff/diff.go
@@ -7,9 +7,9 @@
 package diff
 
 import (
+	exec "internal/execabs"
 	"io/ioutil"
 	"os"
-	"os/exec"
 	"runtime"
 )
 
diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go
index 56b44a1..f97a127 100644
--- a/src/cmd/internal/dwarf/dwarf.go
+++ b/src/cmd/internal/dwarf/dwarf.go
@@ -12,7 +12,7 @@
 	"cmd/internal/objabi"
 	"errors"
 	"fmt"
-	"os/exec"
+	exec "internal/execabs"
 	"sort"
 	"strconv"
 	"strings"
diff --git a/src/cmd/link/internal/ld/execarchive.go b/src/cmd/link/internal/ld/execarchive.go
index fe5cc40..4687c62 100644
--- a/src/cmd/link/internal/ld/execarchive.go
+++ b/src/cmd/link/internal/ld/execarchive.go
@@ -7,8 +7,8 @@
 package ld
 
 import (
+	exec "internal/execabs"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"syscall"
 )
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index a3a9da4..b3e6f74 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -51,11 +51,11 @@
 	"encoding/binary"
 	"encoding/hex"
 	"fmt"
+	exec "internal/execabs"
 	"io"
 	"io/ioutil"
 	"log"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"runtime"
 	"sort"
diff --git a/src/cmd/test2json/main.go b/src/cmd/test2json/main.go
index 0385d8f..52bad6b 100644
--- a/src/cmd/test2json/main.go
+++ b/src/cmd/test2json/main.go
@@ -82,9 +82,9 @@
 import (
 	"flag"
 	"fmt"
+	exec "internal/execabs"
 	"io"
 	"os"
-	"os/exec"
 
 	"cmd/internal/test2json"
 )
diff --git a/src/cmd/trace/pprof.go b/src/cmd/trace/pprof.go
index a31d71b..e6ea1a4 100644
--- a/src/cmd/trace/pprof.go
+++ b/src/cmd/trace/pprof.go
@@ -9,12 +9,12 @@
 import (
 	"bufio"
 	"fmt"
+	exec "internal/execabs"
 	"internal/trace"
 	"io"
 	"io/ioutil"
 	"net/http"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"runtime"
 	"sort"
diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go
index 2ea63f3..8c76021 100644
--- a/src/crypto/elliptic/p224.go
+++ b/src/crypto/elliptic/p224.go
@@ -386,10 +386,11 @@
 // 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 @@
 	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 @@
 	// 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 @@
 	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 @@
 	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 @@
 	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.
diff --git a/src/crypto/elliptic/p224_test.go b/src/crypto/elliptic/p224_test.go
index 8b4fa04..eeb24d9 100644
--- a/src/crypto/elliptic/p224_test.go
+++ b/src/crypto/elliptic/p224_test.go
@@ -6,7 +6,11 @@
 
 import (
 	"math/big"
+	"math/bits"
+	"math/rand"
+	"reflect"
 	"testing"
+	"testing/quick"
 )
 
 var toFromBigTests = []string{
@@ -21,16 +25,16 @@
 	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 @@
 		}
 		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)
+	}
+}
diff --git a/src/go/build/build.go b/src/go/build/build.go
index 1a122c6..9136319 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -12,13 +12,13 @@
 	"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"
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 00966bc..8b136e6 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -214,6 +214,8 @@
 	"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": {
@@ -247,7 +249,7 @@
 	"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"},
 
@@ -279,7 +281,7 @@
 	"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"},
@@ -287,7 +289,7 @@
 	"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"},
diff --git a/src/go/internal/gccgoimporter/gccgoinstallation.go b/src/go/internal/gccgoimporter/gccgoinstallation.go
index 8fc7ce3..e90a3cc 100644
--- a/src/go/internal/gccgoimporter/gccgoinstallation.go
+++ b/src/go/internal/gccgoimporter/gccgoinstallation.go
@@ -7,8 +7,8 @@
 import (
 	"bufio"
 	"go/types"
+	exec "internal/execabs"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"strings"
 )
diff --git a/src/internal/execabs/execabs.go b/src/internal/execabs/execabs.go
new file mode 100644
index 0000000..547c3a5
--- /dev/null
+++ b/src/internal/execabs/execabs.go
@@ -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
+}
diff --git a/src/internal/execabs/execabs_test.go b/src/internal/execabs/execabs_test.go
new file mode 100644
index 0000000..a0b88dd
--- /dev/null
+++ b/src/internal/execabs/execabs_test.go
@@ -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())
+	}
+}
diff --git a/src/internal/goroot/gc.go b/src/internal/goroot/gc.go
index 0f541d7..ce72bc3 100644
--- a/src/internal/goroot/gc.go
+++ b/src/internal/goroot/gc.go
@@ -7,8 +7,8 @@
 package goroot
 
 import (
+	exec "internal/execabs"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"strings"
 	"sync"