[dev.link] all: merge branch 'master' into dev.link

Change-Id: I446db56b20ef2189e23e225a91a17736c1d11e4c
This commit is contained in:
Cherry Zhang 2020-06-11 16:49:19 -04:00
commit 3187b05b87
71 changed files with 1541 additions and 832 deletions

20
.gitattributes vendored
View file

@ -1,16 +1,16 @@
# Treat all files in the Go repo as binary, with no git magic updating
# line endings. Windows users contributing to Go will need to use a
# modern version of git and editors capable of LF line endings.
# line endings. This produces predictable results in different environments.
#
# Windows users contributing to Go will need to use a modern version
# of git and editors capable of LF line endings.
#
# Windows .bat files are known to have multiple bugs when run with LF
# endings, and so they are checked in with CRLF endings, with a test
# in test/winbatch.go to catch problems. (See golang.org/issue/37791.)
#
# We'll prevent accidental CRLF line endings from entering the repo
# via the git-review gofmt checks.
# via the git-codereview gofmt checks and tests.
#
# See golang.org/issue/9281
# See golang.org/issue/9281.
* -text
# The only exception is Windows files that must absolutely be CRLF or
# might not work. Batch files are known to have multiple bugs when run
# with LF endings. See golang.org/issue/37791 for more information.
*.bat text eol=crlf

View file

@ -1397,6 +1397,7 @@ Upthere, Inc.
Uriel Mangado <uriel@berlinblue.org>
Vadim Grek <vadimprog@gmail.com>
Vadim Vygonets <unixdj@gmail.com>
Vee Zhang <veezhang@126.com> <vveezhang@gmail.com>
Vendasta
Veselkov Konstantin <kostozyb@gmail.com>
Victor Vrantchan <vrancean+github@gmail.com>

View file

@ -2195,6 +2195,7 @@ Vadim Grek <vadimprog@gmail.com>
Vadim Vygonets <unixdj@gmail.com>
Val Polouchkine <vpolouch@justin.tv>
Valentin Vidic <vvidic@valentin-vidic.from.hr>
Vee Zhang <veezhang@126.com> <vveezhang@gmail.com>
Vega Garcia Luis Alfonso <vegacom@gmail.com>
Venil Noronha <veniln@vmware.com>
Veselkov Konstantin <kostozyb@gmail.com>

132
api/go1.15.txt Normal file
View file

@ -0,0 +1,132 @@
pkg bufio, var ErrBadReadCount error
pkg crypto, method (Hash) String() string
pkg crypto/ecdsa, func SignASN1(io.Reader, *PrivateKey, []uint8) ([]uint8, error)
pkg crypto/ecdsa, func VerifyASN1(*PublicKey, []uint8, []uint8) bool
pkg crypto/ecdsa, method (*PrivateKey) Equal(crypto.PrivateKey) bool
pkg crypto/ecdsa, method (*PublicKey) Equal(crypto.PublicKey) bool
pkg crypto/ed25519, method (PrivateKey) Equal(crypto.PrivateKey) bool
pkg crypto/ed25519, method (PublicKey) Equal(crypto.PublicKey) bool
pkg crypto/elliptic, func MarshalCompressed(Curve, *big.Int, *big.Int) []uint8
pkg crypto/elliptic, func UnmarshalCompressed(Curve, []uint8) (*big.Int, *big.Int)
pkg crypto/rsa, method (*PrivateKey) Equal(crypto.PrivateKey) bool
pkg crypto/rsa, method (*PublicKey) Equal(crypto.PublicKey) bool
pkg crypto/tls, method (*Dialer) Dial(string, string) (net.Conn, error)
pkg crypto/tls, method (*Dialer) DialContext(context.Context, string, string) (net.Conn, error)
pkg crypto/tls, method (ClientAuthType) String() string
pkg crypto/tls, method (CurveID) String() string
pkg crypto/tls, method (SignatureScheme) String() string
pkg crypto/tls, type Config struct, VerifyConnection func(ConnectionState) error
pkg crypto/tls, type Dialer struct
pkg crypto/tls, type Dialer struct, Config *Config
pkg crypto/tls, type Dialer struct, NetDialer *net.Dialer
pkg crypto/x509, func CreateRevocationList(io.Reader, *RevocationList, *Certificate, crypto.Signer) ([]uint8, error)
pkg crypto/x509, type RevocationList struct
pkg crypto/x509, type RevocationList struct, ExtraExtensions []pkix.Extension
pkg crypto/x509, type RevocationList struct, NextUpdate time.Time
pkg crypto/x509, type RevocationList struct, Number *big.Int
pkg crypto/x509, type RevocationList struct, RevokedCertificates []pkix.RevokedCertificate
pkg crypto/x509, type RevocationList struct, SignatureAlgorithm SignatureAlgorithm
pkg crypto/x509, type RevocationList struct, ThisUpdate time.Time
pkg database/sql, method (*DB) SetConnMaxIdleTime(time.Duration)
pkg database/sql, method (*Row) Err() error
pkg database/sql, type DBStats struct, MaxIdleTimeClosed int64
pkg database/sql/driver, type Validator interface { IsValid }
pkg database/sql/driver, type Validator interface, IsValid() bool
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 4096
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_APPCONTAINER ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 64
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 128
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_GUARD_CF = 16384
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_GUARD_CF ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 32
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_BIND = 2048
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_BIND ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 512
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_ISOLATION ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_SEH = 1024
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_SEH ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 256
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NX_COMPAT ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 32768
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE ideal-int
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 8192
pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_WDM_DRIVER ideal-int
pkg debug/pe, const IMAGE_FILE_32BIT_MACHINE = 256
pkg debug/pe, const IMAGE_FILE_32BIT_MACHINE ideal-int
pkg debug/pe, const IMAGE_FILE_AGGRESIVE_WS_TRIM = 16
pkg debug/pe, const IMAGE_FILE_AGGRESIVE_WS_TRIM ideal-int
pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_HI = 32768
pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_HI ideal-int
pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_LO = 128
pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_LO ideal-int
pkg debug/pe, const IMAGE_FILE_DEBUG_STRIPPED = 512
pkg debug/pe, const IMAGE_FILE_DEBUG_STRIPPED ideal-int
pkg debug/pe, const IMAGE_FILE_DLL = 8192
pkg debug/pe, const IMAGE_FILE_DLL ideal-int
pkg debug/pe, const IMAGE_FILE_EXECUTABLE_IMAGE = 2
pkg debug/pe, const IMAGE_FILE_EXECUTABLE_IMAGE ideal-int
pkg debug/pe, const IMAGE_FILE_LARGE_ADDRESS_AWARE = 32
pkg debug/pe, const IMAGE_FILE_LARGE_ADDRESS_AWARE ideal-int
pkg debug/pe, const IMAGE_FILE_LINE_NUMS_STRIPPED = 4
pkg debug/pe, const IMAGE_FILE_LINE_NUMS_STRIPPED ideal-int
pkg debug/pe, const IMAGE_FILE_LOCAL_SYMS_STRIPPED = 8
pkg debug/pe, const IMAGE_FILE_LOCAL_SYMS_STRIPPED ideal-int
pkg debug/pe, const IMAGE_FILE_NET_RUN_FROM_SWAP = 2048
pkg debug/pe, const IMAGE_FILE_NET_RUN_FROM_SWAP ideal-int
pkg debug/pe, const IMAGE_FILE_RELOCS_STRIPPED = 1
pkg debug/pe, const IMAGE_FILE_RELOCS_STRIPPED ideal-int
pkg debug/pe, const IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 1024
pkg debug/pe, const IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP ideal-int
pkg debug/pe, const IMAGE_FILE_SYSTEM = 4096
pkg debug/pe, const IMAGE_FILE_SYSTEM ideal-int
pkg debug/pe, const IMAGE_FILE_UP_SYSTEM_ONLY = 16384
pkg debug/pe, const IMAGE_FILE_UP_SYSTEM_ONLY ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_APPLICATION = 10
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_APPLICATION ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_ROM = 13
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_ROM ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12
pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE = 1
pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8
pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE_WINDOWS ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_OS2_CUI = 5
pkg debug/pe, const IMAGE_SUBSYSTEM_OS2_CUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_POSIX_CUI = 7
pkg debug/pe, const IMAGE_SUBSYSTEM_POSIX_CUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_UNKNOWN = 0
pkg debug/pe, const IMAGE_SUBSYSTEM_UNKNOWN ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_GUI ideal-int
pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX = 14
pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX ideal-int
pkg go/printer, const StdFormat = 16
pkg go/printer, const StdFormat Mode
pkg math/big, method (*Int) FillBytes([]uint8) []uint8
pkg net, method (*Resolver) LookupIP(context.Context, string, string) ([]IP, error)
pkg net/url, method (*URL) EscapedFragment() string
pkg net/url, method (*URL) Redacted() string
pkg net/url, type URL struct, RawFragment string
pkg os, method (*File) ReadFrom(io.Reader) (int64, error)
pkg os, var ErrDeadlineExceeded error
pkg regexp, method (*Regexp) SubexpIndex(string) int
pkg strconv, func FormatComplex(complex128, uint8, int, int) string
pkg strconv, func ParseComplex(string, int) (complex128, error)
pkg sync, method (*Map) LoadAndDelete(interface{}) (interface{}, bool)
pkg testing, method (*B) TempDir() string
pkg testing, method (*T) Deadline() (time.Time, bool)
pkg testing, method (*T) TempDir() string
pkg testing, type TB interface, TempDir() string
pkg time, method (*Ticker) Reset(Duration)

View file

@ -1,3 +0,0 @@
pkg testing, method (*T) Deadline() (time.Time, bool)
pkg time, method (*Ticker) Reset(Duration)
pkg sync, method (*Map) LoadAndDelete(interface{}) (interface{}, bool)

View file

@ -30,7 +30,7 @@ adds <a href="#test">caching of successful test results</a>,
runs <a href="#test-vet">vet automatically during tests</a>,
and
permits <a href="#cgo">passing string values directly between Go and C using cgo</a>.
A new <a href="#cgo">compiler option whitelist</a> may cause
A new <a href="#cgo">hard-coded set of safe compiler options</a> may cause
unexpected <a href="https://golang.org/s/invalidflag"><code>invalid
flag</code></a> errors in code that built successfully with older
releases.
@ -267,7 +267,7 @@ and the <a href="/cmd/test2json/">test2json documentation</a>.
<p>
Options specified by cgo using <code>#cgo CFLAGS</code> and the like
are now checked against a whitelist of permitted options.
are now checked against a list of permitted options.
This closes a security hole in which a downloaded package uses
compiler options like
<span style="white-space: nowrap"><code>-fplugin</code></span>

View file

@ -55,6 +55,13 @@ Do not send CLs removing the interior tags from such phrases.
on Windows.
</p>
<p><!-- CL 227003 -->
The <code>-race</code> and <code>-msan</code> flags now always
enable <code>-d=checkptr</code>, which checks uses
of <code>unsafe.Pointer</code>. This was previously the case on all
OSes except Windows.
</p>
<p><!-- CL 211139 -->
Go-built DLLs no longer cause the process to exit when it receives a
signal (such as Ctrl-C at a terminal).
@ -211,10 +218,24 @@ Do not send CLs removing the interior tags from such phrases.
<h2 id="runtime">Runtime</h2>
<p><!-- CL 232862 -->
Go now retries system calls that return <code>EINTR</code>. This
became more common in Go 1.14 with the addition of asynchronous
preemption, but is now handled transparently.
<p><!-- CL 221779 -->
If <code>panic</code> is invoked with a value whose type is derived from any
of: <code>bool</code>, <code>complex64</code>, <code>complex128</code>, <code>float32</code>, <code>float64</code>,
<code>int</code>, <code>int8</code>, <code>int16</code>, <code>int32</code>, <code>int64</code>, <code>string</code>,
<code>uint</code>, <code>uint8</code>, <code>uint16</code>, <code>uint32</code>, <code>uint64</code>, <code>uintptr</code>,
then the value will be printed, instead of just its address.
Previously, this was only true for values of exactly these types.
</p>
<p><!-- CL 228900 -->
On a Unix system, if the <code>kill</code> command
or <code>kill</code> system call is used to send
a <code>SIGSEGV</code>, <code>SIGBUS</code>,
or <code>SIGFPE</code> signal to a Go program, and if the signal
is not being handled via
<a href="/pkg/os/signal/#Notify"><code>os/signal.Notify</code></a>,
the Go program will now reliably crash with a stack trace.
In earlier releases the behavior was unpredictable.
</p>
<p><!-- CL 221182, CL 229998 -->
@ -222,8 +243,14 @@ Do not send CLs removing the interior tags from such phrases.
counts, and has lower worst-case latency.
</p>
<p>
TODO
<p><!-- CL 216401 -->
Converting a small integer value into an interface value no longer
causes allocation.
</p>
<p><!-- CL 216818 -->
Non-blocking receives on closed channels now perform as well as
non-blocking receives on open channels.
</p>
<h2 id="compiler">Compiler</h2>
@ -245,6 +272,15 @@ TODO
aggressively eliminating unused type metadata.
</p>
<p><!-- CL 219357, CL 231600 -->
The toolchain now mitigates
<a href="https://www.intel.com/content/www/us/en/support/articles/000055650/processors.html">Intel
CPU erratum SKX102</a> on <code>GOARCH=amd64</code> by aligning
functions to 32 byte boundaries and padding jump instructions. While
this padding increases binary sizes, this is more than made up for
by the binary size improvements mentioned above.
</p>
<p><!-- CL 222661 -->
Go 1.15 adds a <code>-spectre</code> flag to both the
compiler and the assembler, to allow enabling Spectre mitigations.
@ -253,6 +289,19 @@ TODO
See the <a href="https://github.com/golang/go/wiki/Spectre">Spectre wiki page</a> for details.
</p>
<p><!-- CL 228578 -->
The compiler now rejects <code>//go:</code> compiler directives that
have no meaning for the declaration they are applied to with a
"misplaced compiler directive" error. Such misapplied directives
were broken before, but were silently ignored by the compiler.
</p>
<p><!-- CL 206658, CL 205066 -->
The compiler's <code>-json</code> optimization logging now reports
large (>= 128 byte) copies and includes explanations of escape
analysis decisions.
</p>
<h2 id="linker">Linker</h2>
<p>
@ -283,6 +332,14 @@ TODO
improvements expected in future releases.
</p>
<h2 id="objdump">Objdump</h2>
<p><!-- CL 225459 -->
The <a href="/cmd/objdump/">objdump</a> tool now supports
disassembling in GNU assembler syntax with the <code>-gnu</code>
flag.
</p>
<h2 id="library">Core library</h2>
<h3 id="time/tzdata">New embedded tzdata package</h3>
@ -299,10 +356,6 @@ TODO
Either approach increases the size of the program by about 800 KB.
</p>
<p>
TODO
</p>
<h3 id="cgo">Cgo</h3>
<p><!-- CL 235817 -->
@ -321,10 +374,6 @@ TODO
in mind.
</p>
<p>
TODO
</p>
<dl id="debug/pe"><dt><a href="/pkg/debug/pe/">debug/pe</a></dt>
<dd>
<p><!-- CL 222637 -->
@ -336,10 +385,53 @@ TODO
</dd>
</dl><!-- debug/pe -->
<dl id="crypto"><dt><a href="/pkg/crypto/">crypto</a></dt>
<dd>
<p><!-- CL 231417, CL 225460 -->
The <code>PrivateKey</code> and <code>PublicKey</code> types in the
<a href="/pkg/crypto/rsa"><code>crypto/rsa</code></a>,
<a href="/pkg/crypto/ecdsa"><code>crypto/ecdsa</code></a>, and
<a href="/pkg/crypto/ed25519"><code>crypto/ed25519</code></a> packages
now have an <code>Equal</code> method to compare keys for equivalence
or to make type-safe interfaces for public keys. The method signature
is compatible with
<a href="https://pkg.go.dev/github.com/google/go-cmp/cmp#Equal"><code>go-cmp</code>'s
definition of equality</a>.
</p>
<p><!-- CL 224937 -->
<a href="/pkg/crypto/#Hash"><code>Hash</code></a> now implements
<a href="/pkg/fmt/#Stringer"><code>fmt.Stringer</code></a>.
</p>
</dd>
</dl><!-- crypto -->
<dl id="crypto/ecdsa"><dt><a href="/pkg/crypto/ecdsa/">crypto/ecdsa</a></dt>
<dd>
<p><!-- CL 217940 -->
The new <a href="/pkg/crypto/ecdsa/#SignASN1"><code>SignASN1</code></a>
and <a href="/pkg/crypto/ecdsa/#VerifyASN1"><code>VerifyASN1</code></a>
functions allow generating and verifying ECDSA signatures in the standard
ASN.1 DER encoding.
</p>
</dd>
</dl><!-- crypto/ecdsa -->
<dl id="crypto/elliptic"><dt><a href="/pkg/crypto/elliptic/">crypto/elliptic</a></dt>
<dd>
<p><!-- CL 202819 -->
The new <a href="/pkg/crypto/elliptic/#MarshalCompressed"><code>MarshalCompressed</code></a>
and <a href="/pkg/crypto/elliptic/#UnmarshalCompressed"><code>UnmarshalCompressed</code></a>
functions allow encoding and decoding NIST elliptic curve points in compressed format.
</p>
</dd>
</dl><!-- crypto/elliptic -->
<dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
<dd>
<p><!-- CL 226203 -->
VerifyPKCS1v15 now rejects invalid short signatures with missing leading zeroes.
<a href="/pkg/crypto/rsa/#VerifyPKCS1v15"><code>VerifyPKCS1v15</code></a>
now rejects invalid short signatures with missing leading zeroes, according to RFC 8017.
</p>
</dd>
</dl><!-- crypto/rsa -->
@ -353,21 +445,137 @@ TODO
<a href="/pkg/crypto/tls/#Dialer.DialContext"><code>DialContext</code></a>
method permits using a context to both connect and handshake with a TLS server.
</p>
<p><!-- CL 229122 -->
The new
<a href="/pkg/crypto/tls/#Config.VerifyConnection"><code>VerifyConnection</code></a>
callback on the <a href="/pkg/crypto/tls/#Config"><code>Config</code></a> type
allows custom verification logic for every connection. It has access to the
<a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>
which includes peer certificates, SCTs, and stapled OCSP responses.
</p>
<p><!-- CL 230679 -->
Auto-generated session ticket keys are now automatically rotated every 24 hours,
with a lifetime of 7 days, to limit their impact on forward secrecy.
</p>
<p><!-- CL 231317 -->
Session ticket lifetimes in TLS 1.2 and earlier, where the session keys
are reused for resumed connections, are now limited to 7 days, also to
limit their impact on forward secrecy.
</p>
<p><!-- CL 231038 -->
The client-side downgrade protection checks specified in RFC 8446 are now
enforced. This has the potential to cause connection errors for clients
encountering middleboxes that behave like unauthorized downgrade attacks.
</p>
<p><!-- CL 208226 -->
<a href="/pkg/crypto/tls/#SignatureScheme"><code>SignatureScheme</code></a>,
<a href="/pkg/crypto/tls/#CurveID"><code>CurveID</code></a>, and
<a href="/pkg/crypto/tls/#ClientAuthType"><code>ClientAuthType</code></a>
now implement <a href="/pkg/fmt/#Stringer"><code>fmt.Stringer</code></a>.
</p>
<p><!-- CL 236737 -->
The <a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>
fields <code>OCSPResponse</code> and <code>SignedCertificateTimestamps</code>
are now repopulated on client-side resumed connections.
</p>
</dd>
</dl>
</dl><!-- crypto/tls -->
<dl id="crypto/x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
<dd>
<p><!-- CL 231378, CL 231380, CL 231381 -->
If either the name on the certificate or the name being verified (with
<a href="/pkg/crypto/x509/#VerifyOptions.DNSName"><code>VerifyOptions.DNSName</code></a>
or <a href="/pkg/crypto/x509/#Certificate.VerifyHostname"><code>VerifyHostname</code></a>)
are invalid, they will now be compared case-insensitively without further
processing (without honoring wildcards or stripping trailing dots).
Invalid names include those with any characters other than letters,
digits, hyphens and underscores, those with empty labels, and names on
certificates with trailing dots.
</p>
<p><!-- CL 231379 -->
The deprecated, legacy behavior of treating the <code>CommonName</code>
field as a hostname when no Subject Alternative Names are present is now
disabled by default. It can be temporarily re-enabled by adding the value
<code>x509ignoreCN=0</code> to the <code>GODEBUG</code> environment
variable. If the <code>CommonName</code> is an invalid hostname, it's
always ignored.
</p>
<p><!-- CL 217298 -->
The new <a href="/pkg/crypto/x509/#CreateRevocationList"><code>CreateRevocationList</code></a>
function and <a href="/pkg/crypto/x509/#RevocationList"><code>RevocationList</code></a> type
allow creating RFC 5280-compliant X.509 v2 Certificate Revocation Lists.
</p>
<p><!-- CL 227098 -->
<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
now automatically generates the <code>SubjectKeyId</code> if the template
is a CA and doesn't explicitly specify one.
</p>
<p><!-- CL 228777 -->
<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
now returns an error if the template specifies <code>MaxPathLen</code> but is not a CA.
</p>
<p><!-- CL 205237 -->
TODO: <a href="https://golang.org/cl/205237">https://golang.org/cl/205237</a>: load roots from colon separated SSL_CERT_DIR in loadSystemRoots
On Unix systems other than macOS, the <code>SSL_CERT_DIR</code>
environment variable can now be a colon-separated list.
</p>
<p><!-- CL 227037 -->
On macOS, binaries are now always linked against
<code>Security.framework</code> to extract the system trust roots,
regardless of whether cgo is available. The resulting behavior should be
more consistent with the OS verifier.
</p>
</dd>
</dl><!-- crypto/x509 -->
<dl id="crypto/x509/pkix"><dt><a href="/pkg/crypto/x509/pkix/">crypto/x509/pkix</a></dt>
<dd>
<p><!-- CL 229864 -->
<a href="/pkg/crypto/x509/pkix/#Name.String"><code>Name.String</code></a>
now prints non-standard attributes from
<a href="/pkg/crypto/x509/pkix/#Name.Names"><code>Names</code></a> if
<a href="/pkg/crypto/x509/pkix/#Name.ExtraNames"><code>ExtraNames</code></a> is empty.
</p>
</dd>
</dl><!-- crypto/x509/pkix -->
<dl id="encoding/json"><dt><a href="/pkg/encoding/json/">encoding/json</a></dt>
<dd>
<p><!-- CL 191783 -->
Decoding a JSON array into a slice no longer reuses any existing slice elements,
following the rules that the package documentation already stated.
</p>
<p><!-- CL 199837 -->
Introduce an internal limit to the maximum depth of nesting when decoding.
This reduces the possibility that a deeply nested input could use large quantities
of stack memory, or even cause a "goroutine stack exceeds limit" panic.
</p>
</dd>
</dl><!-- encoding/json -->
<dl id="encoding/xml"><dt><a href="/pkg/encoding/xml/">encoding/xml</a></dt>
<dd>
<p><!-- CL 203417 -->
TODO: <a href="https://golang.org/cl/203417">https://golang.org/cl/203417</a>: fix reserved namespace check to be case-insensitive
The encoder has always taken care to avoid using namespace prefixes beginning with
<code>xml</code>,
which are reserved by the XML specification.
Now, following the specification more closely,
that check is case-insensitive, so that prefixes beginning with
<code>XML</code>, <code>XmL</code>,
and so on are also avoided.
</p>
</dd>
</dl><!-- encoding/xml -->
@ -390,7 +598,8 @@ TODO
<dl id="fmt"><dt><a href="/pkg/fmt/">fmt</a></dt>
<dd>
<p><!-- CL 215001 -->
TODO: <a href="https://golang.org/cl/215001">https://golang.org/cl/215001</a>: do not remove trailing zeros for %g and %G with #(sharp) flag
The printing verbs <code>%#g</code> and <code>%#G</code> now preserve
trailing zeros for floating-point values.
</p>
</dd>
</dl><!-- fmt -->
@ -410,7 +619,8 @@ TODO
<dl id="math/big"><dt><a href="/pkg/math/big/">math/big</a></dt>
<dd>
<p><!-- CL 230397 -->
TODO: <a href="https://golang.org/cl/230397">https://golang.org/cl/230397</a>: add (*Int).FillBytes
The new <a href="/pkg/math/big/#Int.FillBytes"><code>Int.FillBytes</code></a>
method allows serializing to fixed-size pre-allocated byte slices.
</p>
</dd>
</dl><!-- math/big -->
@ -441,8 +651,10 @@ TODO
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
<dd>
<p><!-- CL 231418 -->
TODO: <a href="https://golang.org/cl/231418">https://golang.org/cl/231418</a>: only support &#34;chunked&#34; in inbound Transfer-Encoding headers
<p><!-- CL 231418, CL 231419 -->
Parsing is now stricter as a hardening measure against request smuggling attacks:
non-ASCII white space is no longer trimmed like SP and HTAB, and support for the
"<code>identity</code>" <code>Transfer-Encoding</code> was dropped.
</p>
</dd>
</dl><!-- net/http -->
@ -457,7 +669,9 @@ TODO
</p>
<p><!-- CL 224897 -->
TODO: <a href="https://golang.org/cl/224897">https://golang.org/cl/224897</a>: make Switching Protocol requests (e.g. Websockets) cancelable
When a Switching Protocol (like WebSocket) request handled by
<a href="/pkg/net/http/httputil/#ReverseProxy"><code>ReverseProxy</code></a>
is canceled, the backend connection is now correctly closed.
</p>
</dd>
</dl>
@ -506,6 +720,14 @@ TODO
which <code>Timeout</code> returns <code>true</code> although a
deadline has not been exceeded.
</p>
<p><!-- CL 232862 -->
Packages <code>os</code> and <code>net</code> now automatically
retry system calls that fail with <code>EINTR</code>. Previously
this led to spurious failures, which became more common in Go
1.14 with the addition of asynchronous preemption. Now this is
handled transparently.
</p>
</dd>
</dl>
@ -525,7 +747,7 @@ TODO
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
<dd>
<p><!-- CL 228902 -->
Package reflect now disallows accessing methods of all
Package <code>reflect</code> now disallows accessing methods of all
non-exported fields, whereas previously it allowed accessing
those of non-exported, embedded fields. Code that relies on the
previous behavior should be updated to instead access the
@ -546,26 +768,6 @@ TODO
<dl id="pkg-runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
<dd>
<p><!-- CL 221779 -->
If <code>panic</code> is invoked with a value whose type is derived from any
of: <code>bool</code>, <code>complex64</code>, <code>complex128</code>, <code>float32</code>, <code>float64</code>,
<code>int</code>, <code>int8</code>, <code>int16</code>, <code>int32</code>, <code>int64</code>, <code>string</code>,
<code>uint</code>, <code>uint8</code>, <code>uint16</code>, <code>uint32</code>, <code>uint64</code>, <code>uintptr</code>,
then the value will be printed, instead of just its address.
Previously, this was only true for values of exactly these types.
</p>
<p><!-- CL -->
On a Unix system, if the <code>kill</code> command
or <code>kill</code> system call is used to send
a <code>SIGSEGV</code>, <code>SIGBUS</code>,
or <code>SIGFPE</code> signal to a Go program, and if the signal
is not being handled via
<a href="/pkg/os/signal/#Notify"><code>os/signal.Notify</code></a>,
the Go program will now reliably crash with a stack trace.
In earlier releases the behavior was unpredictable.
</p>
<p><!-- CL 216557 -->
Several functions, including
<a href="/pkg/runtime/#ReadMemStats"><code>ReadMemStats</code></a>
@ -573,16 +775,6 @@ TODO
<a href="/pkg/runtime/#GoroutineProfile"><code>GoroutineProfile</code></a>,
no longer block if a garbage collection is in progress.
</p>
<p><!-- CL 216401 -->
Converting small integer values into an interface value no
longer causes allocation.
</p>
<p><!-- CL 216818 -->
Non-blocking receives on closed channels now perform as well as
non-blocking receives on open channels.
</p>
</dd>
</dl>

View file

@ -73,19 +73,29 @@ func testAddr2Line(t *testing.T, exepath, addr string) {
if err != nil {
t.Fatalf("Stat failed: %v", err)
}
// Debug paths are stored slash-separated, so convert to system-native.
srcPath = filepath.FromSlash(srcPath)
fi2, err := os.Stat(srcPath)
if gorootFinal := os.Getenv("GOROOT_FINAL"); gorootFinal != "" && strings.HasPrefix(srcPath, gorootFinal) {
if os.IsNotExist(err) || (err == nil && !os.SameFile(fi1, fi2)) {
// srcPath has had GOROOT_FINAL substituted for GOROOT, and it doesn't
// match the actual file. GOROOT probably hasn't been moved to its final
// location yet, so try the original location instead.
fi2, err = os.Stat(runtime.GOROOT() + strings.TrimPrefix(srcPath, gorootFinal))
}
}
if err != nil {
t.Fatalf("Stat failed: %v", err)
}
if !os.SameFile(fi1, fi2) {
t.Fatalf("addr2line_test.go and %s are not same file", srcPath)
}
if srcLineNo != "89" {
t.Fatalf("line number = %v; want 89", srcLineNo)
if srcLineNo != "99" {
t.Fatalf("line number = %v; want 99", srcLineNo)
}
}
// This is line 88. The test depends on that.
// This is line 98. The test depends on that.
func TestAddr2Line(t *testing.T) {
testenv.MustHaveGoBuild(t)

View file

@ -420,6 +420,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
UXTBW R2, R6 // 461c0053
UXTHW R7, R20 // f43c0053
VCNT V0.B8, V0.B8 // 0058200e
VCNT V0.B16, V0.B16 // 0058204e
WFE // 5f2003d5
WFI // 7f2003d5
YIELD // 3f2003d5

View file

@ -990,7 +990,7 @@ produces a file named a.out, even if cmd/link does so by invoking the host
linker in external linking mode.
By default, cmd/link will decide the linking mode as follows: if the only
packages using cgo are those on a whitelist of standard library
packages using cgo are those on a list of known standard library
packages (net, os/user, runtime/cgo), cmd/link will use internal linking
mode. Otherwise, there are non-standard cgo packages involved, and cmd/link
will use external linking mode. The first rule means that a build of

View file

@ -96,7 +96,7 @@ func TestFormats(t *testing.T) {
}
importPath := filepath.Join("cmd/compile", path)
if blacklistedPackages[filepath.ToSlash(importPath)] {
if ignoredPackages[filepath.ToSlash(importPath)] {
return filepath.SkipDir
}
@ -344,8 +344,7 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) {
for index, file := range files {
ast.Inspect(file, func(n ast.Node) bool {
if call, ok := n.(*ast.CallExpr); ok {
// ignore blacklisted functions
if blacklistedFunctions[nodeString(call.Fun)] {
if ignoredFunctions[nodeString(call.Fun)] {
return true
}
// look for an arguments that might be a format string
@ -354,7 +353,7 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) {
// make sure we have enough arguments
n := numFormatArgs(s)
if i+1+n > len(call.Args) {
t.Errorf("%s: not enough format args (blacklist %s?)", posString(call), nodeString(call.Fun))
t.Errorf("%s: not enough format args (ignore %s?)", posString(call), nodeString(call.Fun))
break // ignore this call
}
// assume last n arguments are to be formatted;
@ -549,14 +548,14 @@ func formatReplace(in string, f func(i int, s string) string) string {
return string(append(buf, in[i0:]...))
}
// blacklistedPackages is the set of packages which can
// ignoredPackages is the set of packages which can
// be ignored.
var blacklistedPackages = map[string]bool{}
var ignoredPackages = map[string]bool{}
// blacklistedFunctions is the set of functions which may have
// ignoredFunctions is the set of functions which may have
// format-like arguments but which don't do any formatting and
// thus may be ignored.
var blacklistedFunctions = map[string]bool{}
var ignoredFunctions = map[string]bool{}
func init() {
// verify that knownFormats entries are correctly formatted

View file

@ -140,6 +140,7 @@ var knownFormats = map[string]string{
"float64 %.3f": "",
"float64 %.6g": "",
"float64 %g": "",
"int %#x": "",
"int %-12d": "",
"int %-6d": "",
"int %-8o": "",
@ -203,6 +204,7 @@ var knownFormats = map[string]string{
"uint64 %b": "",
"uint64 %d": "",
"uint64 %x": "",
"uint8 %#x": "",
"uint8 %d": "",
"uint8 %v": "",
"uint8 %x": "",

View file

@ -898,6 +898,20 @@ var blockJump = map[ssa.BlockKind]struct {
ssa.BlockARMUGE: {arm.ABHS, arm.ABLO},
ssa.BlockARMUGT: {arm.ABHI, arm.ABLS},
ssa.BlockARMULE: {arm.ABLS, arm.ABHI},
ssa.BlockARMLTnoov: {arm.ABMI, arm.ABPL},
ssa.BlockARMGEnoov: {arm.ABPL, arm.ABMI},
}
// To model a 'LEnoov' ('<=' without overflow checking) branching
var leJumps = [2][2]gc.IndexJump{
{{Jump: arm.ABEQ, Index: 0}, {Jump: arm.ABPL, Index: 1}}, // next == b.Succs[0]
{{Jump: arm.ABMI, Index: 0}, {Jump: arm.ABEQ, Index: 0}}, // next == b.Succs[1]
}
// To model a 'GTnoov' ('>' without overflow checking) branching
var gtJumps = [2][2]gc.IndexJump{
{{Jump: arm.ABMI, Index: 1}, {Jump: arm.ABEQ, Index: 1}}, // next == b.Succs[0]
{{Jump: arm.ABEQ, Index: 1}, {Jump: arm.ABPL, Index: 0}}, // next == b.Succs[1]
}
func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
@ -941,7 +955,8 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
ssa.BlockARMLT, ssa.BlockARMGE,
ssa.BlockARMLE, ssa.BlockARMGT,
ssa.BlockARMULT, ssa.BlockARMUGT,
ssa.BlockARMULE, ssa.BlockARMUGE:
ssa.BlockARMULE, ssa.BlockARMUGE,
ssa.BlockARMLTnoov, ssa.BlockARMGEnoov:
jmp := blockJump[b.Kind]
switch next {
case b.Succs[0].Block():
@ -958,6 +973,12 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
}
}
case ssa.BlockARMLEnoov:
s.CombJump(b, next, &leJumps)
case ssa.BlockARMGTnoov:
s.CombJump(b, next, &gtJumps)
default:
b.Fatalf("branch not implemented: %s", b.LongString())
}

View file

@ -141,13 +141,13 @@ func isSelfAssign(dst, src *Node) bool {
return samesafeexpr(dst.Left, src.Left)
}
// mayAffectMemory reports whether n evaluation may affect program memory state.
// If expression can't affect it, then it can be safely ignored by the escape analysis.
// mayAffectMemory reports whether evaluation of n may affect the program's
// memory state. If the expression can't affect memory state, then it can be
// safely ignored by the escape analysis.
func mayAffectMemory(n *Node) bool {
// We may want to use "memory safe" black list instead of general
// "side-effect free", which can include all calls and other ops
// that can affect allocate or change global state.
// It's safer to start from a whitelist for now.
// We may want to use a list of "memory safe" ops instead of generally
// "side-effect free", which would include all calls and other ops that can
// allocate or change global state. For now, it's safer to start with the latter.
//
// We're ignoring things like division by zero, index out of range,
// and nil pointer dereference here.

View file

@ -451,6 +451,7 @@ var passes = [...]pass{
{name: "lowered deadcode for cse", fn: deadcode}, // deadcode immediately before CSE avoids CSE making dead values live again
{name: "lowered cse", fn: cse},
{name: "elim unread autos", fn: elimUnreadAutos},
{name: "tighten tuple selectors", fn: tightenTupleSelectors, required: true},
{name: "lowered deadcode", fn: deadcode, required: true},
{name: "checkLower", fn: checkLower, required: true},
{name: "late phielim", fn: phielim},
@ -509,6 +510,8 @@ var passOrder = [...]constraint{
{"decompose builtin", "late opt"},
// decompose builtin is the last pass that may introduce new float ops, so run softfloat after it
{"decompose builtin", "softfloat"},
// tuple selectors must be tightened to generators and de-duplicated before scheduling
{"tighten tuple selectors", "schedule"},
// remove critical edges before phi tighten, so that phi args get better placement
{"critical", "phi tighten"},
// don't layout blocks until critical edges have been removed

View file

@ -223,60 +223,6 @@ func cse(f *Func) {
}
}
// Fixup tuple selectors.
//
// If we have rewritten a tuple generator to a new one in a different
// block, copy its selectors to the new generator's block, so tuple
// generator and selectors stay together.
//
// Note: that there must be only one selector of each type per tuple
// generator. CSE may have left us with more than one so we de-duplicate
// them using a map. See issue 16741.
selectors := make(map[struct {
id ID
op Op
}]*Value)
for _, b := range f.Blocks {
for _, selector := range b.Values {
if selector.Op != OpSelect0 && selector.Op != OpSelect1 {
continue
}
// Get the tuple generator to use as a key for de-duplication.
tuple := selector.Args[0]
if !tuple.Type.IsTuple() {
f.Fatalf("arg of tuple selector %s is not a tuple: %s", selector.String(), tuple.LongString())
}
// If there is a pre-existing selector in the target block then
// use that. Do this even if the selector is already in the
// target block to avoid duplicate tuple selectors.
key := struct {
id ID
op Op
}{tuple.ID, selector.Op}
if t := selectors[key]; t != nil {
if selector != t {
selector.copyOf(t)
}
continue
}
// If the selector is in the wrong block copy it into the target
// block.
if selector.Block != tuple.Block {
t := selector.copyInto(tuple.Block)
selector.copyOf(t)
selectors[key] = t
continue
}
// The selector is in the target block. Add it to the map so it
// cannot be duplicated.
selectors[key] = selector
}
}
if f.pass.stats > 0 {
f.LogStat("CSE REWRITES", rewrites)
}

View file

@ -704,6 +704,10 @@
(UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no)
(EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no)
(NE (InvertFlags cmp) yes no) -> (NE cmp yes no)
(LTnoov (InvertFlags cmp) yes no) => (GTnoov cmp yes no)
(GEnoov (InvertFlags cmp) yes no) => (LEnoov cmp yes no)
(LEnoov (InvertFlags cmp) yes no) => (GEnoov cmp yes no)
(GTnoov (InvertFlags cmp) yes no) => (LTnoov cmp yes no)
// absorb flag constants into boolean values
(Equal (FlagEQ)) -> (MOVWconst [1])
@ -1417,42 +1421,42 @@
(NE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftLLreg x y z) yes no)
(NE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRLreg x y z) yes no)
(NE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRAreg x y z) yes no)
(LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LT (CMP x y) yes no)
(LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LT (CMP a (MUL <x.Type> x y)) yes no)
(LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LT (CMPconst [c] x) yes no)
(LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftLL x y [c]) yes no)
(LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRL x y [c]) yes no)
(LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRA x y [c]) yes no)
(LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftLLreg x y z) yes no)
(LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRLreg x y z) yes no)
(LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRAreg x y z) yes no)
(LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LE (CMP x y) yes no)
(LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LE (CMP a (MUL <x.Type> x y)) yes no)
(LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LE (CMPconst [c] x) yes no)
(LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftLL x y [c]) yes no)
(LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRL x y [c]) yes no)
(LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRA x y [c]) yes no)
(LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftLLreg x y z) yes no)
(LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRLreg x y z) yes no)
(LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRAreg x y z) yes no)
(LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LT (CMN x y) yes no)
(LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LT (CMN a (MUL <x.Type> x y)) yes no)
(LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LT (CMNconst [c] x) yes no)
(LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftLL x y [c]) yes no)
(LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRL x y [c]) yes no)
(LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRA x y [c]) yes no)
(LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftLLreg x y z) yes no)
(LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRLreg x y z) yes no)
(LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRAreg x y z) yes no)
(LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LE (CMN x y) yes no)
(LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LE (CMN a (MUL <x.Type> x y)) yes no)
(LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LE (CMNconst [c] x) yes no)
(LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftLL x y [c]) yes no)
(LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRL x y [c]) yes no)
(LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRA x y [c]) yes no)
(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftLLreg x y z) yes no)
(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRLreg x y z) yes no)
(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRAreg x y z) yes no)
(LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LTnoov (CMP x y) yes no)
(LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LTnoov (CMP a (MUL <x.Type> x y)) yes no)
(LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (CMPconst [c] x) yes no)
(LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftLL x y [c]) yes no)
(LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRL x y [c]) yes no)
(LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRA x y [c]) yes no)
(LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftLLreg x y z) yes no)
(LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRLreg x y z) yes no)
(LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRAreg x y z) yes no)
(LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LEnoov (CMP x y) yes no)
(LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LEnoov (CMP a (MUL <x.Type> x y)) yes no)
(LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (CMPconst [c] x) yes no)
(LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftLL x y [c]) yes no)
(LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRL x y [c]) yes no)
(LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRA x y [c]) yes no)
(LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftLLreg x y z) yes no)
(LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRLreg x y z) yes no)
(LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRAreg x y z) yes no)
(LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LTnoov (CMN x y) yes no)
(LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
(LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (CMNconst [c] x) yes no)
(LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftLL x y [c]) yes no)
(LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRL x y [c]) yes no)
(LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRA x y [c]) yes no)
(LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftLLreg x y z) yes no)
(LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRLreg x y z) yes no)
(LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRAreg x y z) yes no)
(LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LEnoov (CMN x y) yes no)
(LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
(LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (CMNconst [c] x) yes no)
(LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLL x y [c]) yes no)
(LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRL x y [c]) yes no)
(LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRA x y [c]) yes no)
(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLLreg x y z) yes no)
(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRLreg x y z) yes no)
(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRAreg x y z) yes no)
(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LT (TST x y) yes no)
(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LT (TSTconst [c] x) yes no)
(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftLL x y [c]) yes no)
@ -1485,43 +1489,43 @@
(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftLLreg x y z) yes no)
(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRLreg x y z) yes no)
(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRAreg x y z) yes no)
(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GT (CMP x y) yes no)
(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GT (CMP a (MUL <x.Type> x y)) yes no)
(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GT (CMPconst [c] x) yes no)
(GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftLL x y [c]) yes no)
(GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRL x y [c]) yes no)
(GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRA x y [c]) yes no)
(GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftLLreg x y z) yes no)
(GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRLreg x y z) yes no)
(GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRAreg x y z) yes no)
(GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GE (CMP x y) yes no)
(GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GE (CMP a (MUL <x.Type> x y)) yes no)
(GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GE (CMPconst [c] x) yes no)
(GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftLL x y [c]) yes no)
(GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRL x y [c]) yes no)
(GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRA x y [c]) yes no)
(GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftLLreg x y z) yes no)
(GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRLreg x y z) yes no)
(GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRAreg x y z) yes no)
(GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GT (CMN x y) yes no)
(GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GT (CMNconst [c] x) yes no)
(GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftLL x y [c]) yes no)
(GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRL x y [c]) yes no)
(GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRA x y [c]) yes no)
(GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftLLreg x y z) yes no)
(GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRLreg x y z) yes no)
(GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRAreg x y z) yes no)
(GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GE (CMN x y) yes no)
(GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GE (CMN a (MUL <x.Type> x y)) yes no)
(GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GE (CMNconst [c] x) yes no)
(GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftLL x y [c]) yes no)
(GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRL x y [c]) yes no)
(GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRA x y [c]) yes no)
(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftLLreg x y z) yes no)
(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRLreg x y z) yes no)
(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRAreg x y z) yes no)
(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GTnoov (CMP x y) yes no)
(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GTnoov (CMP a (MUL <x.Type> x y)) yes no)
(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMPconst [c] x) yes no)
(GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftLL x y [c]) yes no)
(GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRL x y [c]) yes no)
(GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRA x y [c]) yes no)
(GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftLLreg x y z) yes no)
(GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRLreg x y z) yes no)
(GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRAreg x y z) yes no)
(GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GEnoov (CMP x y) yes no)
(GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GEnoov (CMP a (MUL <x.Type> x y)) yes no)
(GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (CMPconst [c] x) yes no)
(GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftLL x y [c]) yes no)
(GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRL x y [c]) yes no)
(GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRA x y [c]) yes no)
(GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftLLreg x y z) yes no)
(GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRLreg x y z) yes no)
(GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRAreg x y z) yes no)
(GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GTnoov (CMN x y) yes no)
(GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMNconst [c] x) yes no)
(GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftLL x y [c]) yes no)
(GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRL x y [c]) yes no)
(GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRA x y [c]) yes no)
(GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftLLreg x y z) yes no)
(GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRLreg x y z) yes no)
(GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRAreg x y z) yes no)
(GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GEnoov (CMN x y) yes no)
(GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
(GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (CMNconst [c] x) yes no)
(GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLL x y [c]) yes no)
(GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRL x y [c]) yes no)
(GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRA x y [c]) yes no)
(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLLreg x y z) yes no)
(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRLreg x y z) yes no)
(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRAreg x y z) yes no)
(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GT (TST x y) yes no)
(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GT (CMN a (MUL <x.Type> x y)) yes no)
(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GT (TSTconst [c] x) yes no)
(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftLL x y [c]) yes no)
(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRL x y [c]) yes no)

View file

@ -584,6 +584,10 @@ func init() {
{name: "ULE", controls: 1},
{name: "UGT", controls: 1},
{name: "UGE", controls: 1},
{name: "LTnoov", controls: 1}, // 'LT' but without honoring overflow
{name: "LEnoov", controls: 1}, // 'LE' but without honoring overflow
{name: "GTnoov", controls: 1}, // 'GT' but without honoring overflow
{name: "GEnoov", controls: 1}, // 'GE' but without honoring overflow
}
archs = append(archs, arch{

View file

@ -61,6 +61,10 @@ const (
BlockARMULE
BlockARMUGT
BlockARMUGE
BlockARMLTnoov
BlockARMLEnoov
BlockARMGTnoov
BlockARMGEnoov
BlockARM64EQ
BlockARM64NE
@ -195,6 +199,10 @@ var blockString = [...]string{
BlockARMULE: "ULE",
BlockARMUGT: "UGT",
BlockARMUGE: "UGE",
BlockARMLTnoov: "LTnoov",
BlockARMLEnoov: "LEnoov",
BlockARMGTnoov: "GTnoov",
BlockARMGEnoov: "GEnoov",
BlockARM64EQ: "EQ",
BlockARM64NE: "NE",

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,6 @@ package ssa
import (
"math"
"math/rand"
"runtime"
"testing"
)
@ -18,6 +17,7 @@ var (
y64 int64 = math.MinInt64 + 1
x32 int32 = math.MaxInt32 - 2
x32b int32 = math.MaxInt32 - 2
x32c int32 = math.MaxInt32 - 2
y32 int32 = math.MinInt32 + 1
one64 int64 = 1
one32 int32 = 1
@ -25,6 +25,8 @@ var (
v64_n int64 = -11
v32 int32 = 11
v32_n int32 = -11
uv32 uint32 = 19
uz uint8 = 1 // for lowering to SLL/SRL/SRA
)
var crTests = []struct {
@ -39,6 +41,8 @@ var crTests = []struct {
{"MAddVar32", testMAddVar32},
{"MSubVar64", testMSubVar64},
{"MSubVar32", testMSubVar32},
{"AddShift32", testAddShift32},
{"SubShift32", testSubShift32},
}
var crBenches = []struct {
@ -58,9 +62,6 @@ var crBenches = []struct {
// and machine code sequences are covered.
// It's for arm64 initially, please see https://github.com/golang/go/issues/38740
func TestCondRewrite(t *testing.T) {
if runtime.GOARCH == "arm" {
t.Skip("fix on arm expected!")
}
for _, test := range crTests {
t.Run(test.name, test.tf)
}
@ -408,6 +409,66 @@ func testMSubVar32(t *testing.T) {
}
}
// 32-bit ADDshift, pick up 1~2 scenarios randomly for each condition
func testAddShift32(t *testing.T) {
if x32+v32<<1 < 0 {
} else {
t.Errorf("'%#x + %#x<<%#x < 0' failed", x32, v32, 1)
}
if x32+v32>>1 <= 0 {
} else {
t.Errorf("'%#x + %#x>>%#x <= 0' failed", x32, v32, 1)
}
if x32+int32(uv32>>1) > 0 {
t.Errorf("'%#x + int32(%#x>>%#x) > 0' failed", x32, uv32, 1)
}
if x32+v32<<uz >= 0 {
t.Errorf("'%#x + %#x<<%#x >= 0' failed", x32, v32, uz)
}
if x32+v32>>uz > 0 {
t.Errorf("'%#x + %#x>>%#x > 0' failed", x32, v32, uz)
}
if x32+int32(uv32>>uz) < 0 {
} else {
t.Errorf("'%#x + int32(%#x>>%#x) < 0' failed", x32, uv32, uz)
}
}
// 32-bit SUBshift, pick up 1~2 scenarios randomly for each condition
func testSubShift32(t *testing.T) {
if y32-v32<<1 > 0 {
} else {
t.Errorf("'%#x - %#x<<%#x > 0' failed", y32, v32, 1)
}
if y32-v32>>1 < 0 {
t.Errorf("'%#x - %#x>>%#x < 0' failed", y32, v32, 1)
}
if y32-int32(uv32>>1) >= 0 {
} else {
t.Errorf("'%#x - int32(%#x>>%#x) >= 0' failed", y32, uv32, 1)
}
if y32-v32<<uz < 0 {
t.Errorf("'%#x - %#x<<%#x < 0' failed", y32, v32, uz)
}
if y32-v32>>uz >= 0 {
} else {
t.Errorf("'%#x - %#x>>%#x >= 0' failed", y32, v32, uz)
}
if y32-int32(uv32>>uz) <= 0 {
t.Errorf("'%#x - int32(%#x>>%#x) <= 0' failed", y32, uv32, uz)
}
}
var rnd = rand.New(rand.NewSource(0))
var sink int64

View file

@ -0,0 +1,59 @@
// 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 ssa
// tightenTupleSelectors ensures that tuple selectors (Select0 and
// Select1 ops) are in the same block as their tuple generator. The
// function also ensures that there are no duplicate tuple selectors.
// These properties are expected by the scheduler but may not have
// been maintained by the optimization pipeline up to this point.
//
// See issues 16741 and 39472.
func tightenTupleSelectors(f *Func) {
selectors := make(map[struct {
id ID
op Op
}]*Value)
for _, b := range f.Blocks {
for _, selector := range b.Values {
if selector.Op != OpSelect0 && selector.Op != OpSelect1 {
continue
}
// Get the tuple generator to use as a key for de-duplication.
tuple := selector.Args[0]
if !tuple.Type.IsTuple() {
f.Fatalf("arg of tuple selector %s is not a tuple: %s", selector.String(), tuple.LongString())
}
// If there is a pre-existing selector in the target block then
// use that. Do this even if the selector is already in the
// target block to avoid duplicate tuple selectors.
key := struct {
id ID
op Op
}{tuple.ID, selector.Op}
if t := selectors[key]; t != nil {
if selector != t {
selector.copyOf(t)
}
continue
}
// If the selector is in the wrong block copy it into the target
// block.
if selector.Block != tuple.Block {
t := selector.copyInto(tuple.Block)
selector.copyOf(t)
selectors[key] = t
continue
}
// The selector is in the target block. Add it to the map so it
// cannot be duplicated.
selectors[key] = selector
}
}
}

View file

@ -178,15 +178,6 @@ func (t *tester) run() {
return
}
// We must unset GOROOT_FINAL before tests, because runtime/debug requires
// correct access to source code, so if we have GOROOT_FINAL in effect,
// at least runtime/debug test will fail.
// If GOROOT_FINAL was set before, then now all the commands will appear stale.
// Nothing we can do about that other than not checking them below.
// (We call checkNotStale but only with "std" not "cmd".)
os.Setenv("GOROOT_FINAL_OLD", os.Getenv("GOROOT_FINAL")) // for cmd/link test
os.Unsetenv("GOROOT_FINAL")
for _, name := range t.runNames {
if !t.isRegisteredTestName(name) {
fatalf("unknown test %q", name)

View file

@ -124,7 +124,6 @@ func TestMain(m *testing.M) {
fmt.Printf("SKIP\n")
return
}
os.Unsetenv("GOROOT_FINAL")
flag.Parse()
@ -180,6 +179,11 @@ func TestMain(m *testing.M) {
}
testGOROOT = goEnv("GOROOT")
os.Setenv("TESTGO_GOROOT", testGOROOT)
// Ensure that GOROOT is set explicitly.
// Otherwise, if the toolchain was built with GOROOT_FINAL set but has not
// yet been moved to its final location, programs that invoke runtime.GOROOT
// may accidentally use the wrong path.
os.Setenv("GOROOT", testGOROOT)
// The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
// toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH).
@ -216,8 +220,10 @@ func TestMain(m *testing.M) {
}
testCC = strings.TrimSpace(string(out))
if out, err := exec.Command(testGo, "env", "CGO_ENABLED").Output(); err != nil {
fmt.Fprintf(os.Stderr, "running testgo failed: %v\n", err)
cmd := exec.Command(testGo, "env", "CGO_ENABLED")
cmd.Stderr = new(strings.Builder)
if out, err := cmd.Output(); err != nil {
fmt.Fprintf(os.Stderr, "running testgo failed: %v\n%s", err, cmd.Stderr)
canRun = false
} else {
canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out)))

View file

@ -13,6 +13,7 @@ package web
import (
"crypto/tls"
"errors"
"fmt"
"mime"
"net/http"
@ -47,6 +48,13 @@ var securityPreservingHTTPClient = &http.Client{
lastHop := via[len(via)-1].URL
return fmt.Errorf("redirected from secure URL %s to insecure URL %s", lastHop, req.URL)
}
// Go's http.DefaultClient allows 10 redirects before returning an error.
// The securityPreservingHTTPClient also uses this default policy to avoid
// Go command hangs.
if len(via) >= 10 {
return errors.New("stopped after 10 redirects")
}
return nil
},
}

View file

@ -168,7 +168,7 @@ func gcBackendConcurrency(gcflags []string) int {
CheckFlags:
for _, flag := range gcflags {
// Concurrent compilation is presumed incompatible with any gcflags,
// except for a small whitelist of commonly used flags.
// except for known commonly used flags.
// If the user knows better, they can manually add their own -c to the gcflags.
switch flag {
case "-N", "-l", "-S", "-B", "-C", "-I":

View file

@ -174,6 +174,25 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
return
}
// Request for $GOPROXY/redirect/<count>/... goes to redirects.
if strings.HasPrefix(path, "redirect/") {
path = path[len("redirect/"):]
if j := strings.Index(path, "/"); j >= 0 {
count, err := strconv.Atoi(path[:j])
if err != nil {
return
}
// The last redirect.
if count <= 1 {
http.Redirect(w, r, fmt.Sprintf("/mod/%s", path[j+1:]), 302)
return
}
http.Redirect(w, r, fmt.Sprintf("/mod/redirect/%d/%s", count-1, path[j+1:]), 302)
return
}
}
// Request for $GOPROXY/sumdb/<name>/supported
// is checking whether it's OK to access sumdb via the proxy.
if path == "sumdb/"+testSumDBName+"/supported" {

View file

@ -130,6 +130,7 @@ func (ts *testScript) setup() {
"GOPROXY=" + proxyURL,
"GOPRIVATE=",
"GOROOT=" + testGOROOT,
"GOROOT_FINAL=" + os.Getenv("GOROOT_FINAL"), // causes spurious rebuilds and breaks the "stale" built-in if not propagated
"TESTGO_GOROOT=" + testGOROOT,
"GOSUMDB=" + testSumDBVerifierKey,
"GONOPROXY=",

View file

@ -34,6 +34,7 @@ Scripts also have access to these other environment variables:
GOPATH=$WORK/gopath
GOPROXY=<local module proxy serving from cmd/go/testdata/mod>
GOROOT=<actual GOROOT>
GOROOT_FINAL=<actual GOROOT_FINAL>
TESTGO_GOROOT=<GOROOT used to build cmd/go, for use in tests that may change GOROOT>
HOME=/no-home
PATH=<actual PATH>

View file

@ -1,5 +1,9 @@
[short] skip
# If GOROOT_FINAL is set, 'go build -trimpath' bakes that into the resulting
# binary instead of GOROOT. Explicitly unset it here.
env GOROOT_FINAL=
# Set up two identical directories that can be used as GOPATH.
env GO111MODULE=on
mkdir $WORK/a/src/paths $WORK/b/src/paths

View file

@ -2,6 +2,13 @@
mkdir $WORK/new/bin
# In this test, we are specifically checking the logic for deriving
# the value of GOROOT from runtime.GOROOT.
# GOROOT_FINAL changes the default behavior of runtime.GOROOT,
# and will thus cause the test to fail if it is set when our
# new cmd/go is built.
env GOROOT_FINAL=
go build -o $WORK/new/bin/go$GOEXE cmd/go &
go build -o $WORK/bin/check$GOEXE check.go &
wait

View file

@ -20,7 +20,6 @@ cd $WORK/gopkgdir/x
! go list .
stderr 'cannot find main module'
! stderr 'Gopkg.lock'
! stderr 'go mod init'
-- $WORK/test/Gopkg.lock --
-- $WORK/test/x/x.go --

View file

@ -0,0 +1,10 @@
env GO111MODULE=on
env GOPROXYBASE=$GOPROXY
env GOPROXY=$GOPROXYBASE/redirect/11
env GOSUMDB=off
! go get -d rsc.io/quote@v1.2.0
stderr 'stopped after 10 redirects'
env GOPROXY=$GOPROXYBASE/redirect/9
go get -d rsc.io/quote@v1.2.0

View file

@ -36,7 +36,7 @@ func findGorootModules(t *testing.T) []gorootModule {
if err != nil {
return err
}
if info.Name() == "vendor" || info.Name() == "testdata" {
if info.IsDir() && (info.Name() == "vendor" || info.Name() == "testdata") {
return filepath.SkipDir
}
if path == filepath.Join(runtime.GOROOT(), "pkg") {

View file

@ -460,7 +460,6 @@ var optab = []Optab{
{AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
{ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
{AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
{AVCNT, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0},
{AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0},
{AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0},
{AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
@ -2773,6 +2772,7 @@ func buildop(ctxt *obj.Link) {
oprangeset(AVSRI, t)
case AVREV32:
oprangeset(AVCNT, t)
oprangeset(AVRBIT, t)
oprangeset(AVREV64, t)
oprangeset(AVREV16, t)
@ -4523,7 +4523,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
c.ctxt.Diag("invalid arrangement: %v\n", p)
}
if (p.As == AVMOV || p.As == AVRBIT) && (af != ARNG_16B && af != ARNG_8B) {
if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
c.ctxt.Diag("invalid arrangement: %v", p)
}

View file

@ -134,7 +134,7 @@ func init() {
}
func Framepointer_enabled(goos, goarch string) bool {
return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && goos == "linux")
return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && (goos == "linux" || goos == "darwin"))
}
func addexp(s string) {

View file

@ -33,8 +33,8 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
t.Fatalf("go list: %v\n%s", err, out)
}
if string(out) != "false\n" {
if os.Getenv("GOROOT_FINAL_OLD") != "" {
t.Skip("cmd/link is stale, but $GOROOT_FINAL_OLD is set")
if strings.HasPrefix(testenv.Builder(), "darwin-") {
t.Skipf("cmd/link is spuriously stale on Darwin builders - see #33598")
}
t.Fatalf("cmd/link is stale - run go install cmd/link")
}

View file

@ -616,15 +616,15 @@ func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) {
}
fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason)
// For the moment, whitelist DWARF subprogram DIEs for
// For the moment, allow DWARF subprogram DIEs for
// auto-generated wrapper functions. What seems to happen
// here is that we get different line numbers on formal
// params; I am guessing that the pos is being inherited
// from the spot where the wrapper is needed.
whitelist := strings.HasPrefix(name, "go.info.go.interface") ||
allowed := strings.HasPrefix(name, "go.info.go.interface") ||
strings.HasPrefix(name, "go.info.go.builtin") ||
strings.HasPrefix(name, "go.debuglines")
if !whitelist {
if !allowed {
l.strictDupMsgs++
}
}

View file

@ -138,7 +138,11 @@ func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string)
args = append(args, flags...)
args = append(args, "fmthello.go")
cmd := exec.Command(testenv.GoToolPath(t), args...)
cmd.Dir = "testdata" // "Bad line" bug #36683 is sensitive to being run in the source directory
// "Bad line" bug #36683 is sensitive to being run in the source directory.
cmd.Dir = "testdata"
// Ensure that the source file location embedded in the binary matches our
// actual current GOROOT, instead of GOROOT_FINAL if set.
cmd.Env = append(os.Environ(), "GOROOT_FINAL=")
t.Logf("Running %v", cmd.Args)
out, err := cmd.CombinedOutput()
if err != nil {

View file

@ -278,6 +278,8 @@ type ClientSessionState struct {
serverCertificates []*x509.Certificate // Certificate chain presented by the server
verifiedChains [][]*x509.Certificate // Certificate chains we built for verification
receivedAt time.Time // When the session ticket was received from the server
ocspResponse []byte // Stapled OCSP response presented by the server
scts [][]byte // SCTs presented by the server
// TLS 1.3 fields.
nonce []byte // Ticket nonce sent by the server, to derive PSK

View file

@ -728,10 +728,17 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
return false, errors.New("tls: server resumed a session with a different cipher suite")
}
// Restore masterSecret and peerCerts from previous state
// Restore masterSecret, peerCerts, and ocspResponse from previous state
hs.masterSecret = hs.session.masterSecret
c.peerCertificates = hs.session.serverCertificates
c.verifiedChains = hs.session.verifiedChains
c.ocspResponse = hs.session.ocspResponse
// Let the ServerHello SCTs override the session SCTs from the original
// connection, if any are provided
if len(c.scts) == 0 && len(hs.session.scts) != 0 {
c.scts = hs.session.scts
}
return true, nil
}
@ -788,6 +795,8 @@ func (hs *clientHandshakeState) readSessionTicket() error {
serverCertificates: c.peerCertificates,
verifiedChains: c.verifiedChains,
receivedAt: c.config.time(),
ocspResponse: c.ocspResponse,
scts: c.scts,
}
return nil

View file

@ -19,6 +19,7 @@ import (
"os"
"os/exec"
"path/filepath"
"reflect"
"strconv"
"strings"
"testing"
@ -2430,3 +2431,83 @@ func TestDowngradeCanary(t *testing.T) {
t.Errorf("client unexpectedly reacted to a canary in TLS 1.0")
}
}
func TestResumptionKeepsOCSPAndSCT(t *testing.T) {
t.Run("TLSv12", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS12) })
t.Run("TLSv13", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS13) })
}
func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) {
issuer, err := x509.ParseCertificate(testRSACertificateIssuer)
if err != nil {
t.Fatalf("failed to parse test issuer")
}
roots := x509.NewCertPool()
roots.AddCert(issuer)
clientConfig := &Config{
MaxVersion: ver,
ClientSessionCache: NewLRUClientSessionCache(32),
ServerName: "example.golang",
RootCAs: roots,
}
serverConfig := testConfig.Clone()
serverConfig.MaxVersion = ver
serverConfig.Certificates[0].OCSPStaple = []byte{1, 2, 3}
serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{4, 5, 6}}
_, ccs, err := testHandshake(t, clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
// after a new session we expect to see OCSPResponse and
// SignedCertificateTimestamps populated as usual
if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) {
t.Errorf("client ConnectionState contained unexpected OCSPResponse: wanted %v, got %v",
serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse)
}
if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) {
t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps: wanted %v, got %v",
serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps)
}
// if the server doesn't send any SCTs, repopulate the old SCTs
oldSCTs := serverConfig.Certificates[0].SignedCertificateTimestamps
serverConfig.Certificates[0].SignedCertificateTimestamps = nil
_, ccs, err = testHandshake(t, clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
if !ccs.DidResume {
t.Fatalf("expected session to be resumed")
}
// after a resumed session we also expect to see OCSPResponse
// and SignedCertificateTimestamps populated
if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) {
t.Errorf("client ConnectionState contained unexpected OCSPResponse after resumption: wanted %v, got %v",
serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse)
}
if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, oldSCTs) {
t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v",
oldSCTs, ccs.SignedCertificateTimestamps)
}
// Only test overriding the SCTs for TLS 1.2, since in 1.3
// the server won't send the message containing them
if ver == VersionTLS13 {
return
}
// if the server changes the SCTs it sends, they should override the saved SCTs
serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{7, 8, 9}}
_, ccs, err = testHandshake(t, clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
if !ccs.DidResume {
t.Fatalf("expected session to be resumed")
}
if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) {
t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v",
serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps)
}
}

View file

@ -334,6 +334,8 @@ func (hs *clientHandshakeStateTLS13) processServerHello() error {
c.didResume = true
c.peerCertificates = hs.session.serverCertificates
c.verifiedChains = hs.session.verifiedChains
c.ocspResponse = hs.session.ocspResponse
c.scts = hs.session.scts
return nil
}
@ -666,6 +668,8 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error {
nonce: msg.nonce,
useBy: c.config.time().Add(lifetime),
ageAdd: msg.ageAdd,
ocspResponse: c.ocspResponse,
scts: c.scts,
}
cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config)

View file

@ -2129,16 +2129,13 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
authorityKeyId = parent.SubjectKeyId
}
encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
pki := publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey}
subjectKeyId := template.SubjectKeyId
if len(subjectKeyId) == 0 && template.IsCA {
// SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2
b, err := asn1.Marshal(pki)
if err != nil {
return nil, err
}
h := sha1.Sum(b)
// SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2:
// (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
// value of the BIT STRING subjectPublicKey (excluding the tag,
// length, and number of unused bits).
h := sha1.Sum(publicKeyBytes)
subjectKeyId = h[:]
}
@ -2147,6 +2144,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
return
}
encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
c := tbsCertificate{
Version: 2,
SerialNumber: template.SerialNumber,
@ -2154,7 +2152,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
Issuer: asn1.RawValue{FullBytes: asn1Issuer},
Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
Subject: asn1.RawValue{FullBytes: asn1Subject},
PublicKey: pki,
PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
Extensions: extensions,
}

View file

@ -20,6 +20,7 @@ import (
"path/filepath"
"strings"
"sync"
_ "unsafe" // for go:linkname
)
// An Importer provides the context for importing packages from source code.
@ -133,7 +134,7 @@ func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*type
// build.Context's VFS.
conf.FakeImportC = true
} else {
conf.UsesCgo = true
setUsesCgo(&conf)
file, err := p.cgo(bp)
if err != nil {
return nil, err
@ -260,3 +261,6 @@ func (p *Importer) joinPath(elem ...string) string {
}
return filepath.Join(elem...)
}
//go:linkname setUsesCgo go/types.srcimporter_setUsesCgo
func setUsesCgo(conf *types.Config)

View file

@ -105,14 +105,14 @@ type Config struct {
// Do not use casually!
FakeImportC bool
// If UsesCgo is set, the type checker expects the
// If go115UsesCgo is set, the type checker expects the
// _cgo_gotypes.go file generated by running cmd/cgo to be
// provided as a package source file. Qualified identifiers
// referring to package C will be resolved to cgo-provided
// declarations within _cgo_gotypes.go.
//
// It is an error to set both FakeImportC and UsesCgo.
UsesCgo bool
// It is an error to set both FakeImportC and go115UsesCgo.
go115UsesCgo bool
// If Error != nil, it is called with each error found
// during type checking; err has dynamic type Error.
@ -140,6 +140,10 @@ type Config struct {
DisableUnusedImportCheck bool
}
func srcimporter_setUsesCgo(conf *Config) {
conf.go115UsesCgo = true
}
// Info holds result type information for a type-checked package.
// Only the information for which a map is provided is collected.
// If the package has type errors, the collected information may

View file

@ -248,10 +248,10 @@ func (check *Checker) handleBailout(err *error) {
// Files checks the provided files as part of the checker's package.
func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(files) }
var errBadCgo = errors.New("cannot use FakeImportC and UsesCgo together")
var errBadCgo = errors.New("cannot use FakeImportC and go115UsesCgo together")
func (check *Checker) checkFiles(files []*ast.File) (err error) {
if check.conf.FakeImportC && check.conf.UsesCgo {
if check.conf.FakeImportC && check.conf.go115UsesCgo {
return errBadCgo
}

View file

@ -141,10 +141,10 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
}
// no package yet => import it
if path == "C" && (check.conf.FakeImportC || check.conf.UsesCgo) {
if path == "C" && (check.conf.FakeImportC || check.conf.go115UsesCgo) {
imp = NewPackage("C", "C")
imp.fake = true // package scope is not populated
imp.cgo = check.conf.UsesCgo
imp.cgo = check.conf.go115UsesCgo
} else {
// ordinary import
var err error

View file

@ -240,8 +240,7 @@ func htmlNameFilter(args ...interface{}) string {
}
s = strings.ToLower(s)
if t := attrType(s); t != contentTypePlain {
// TODO: Split attr and element name part filters so we can whitelist
// attributes.
// TODO: Split attr and element name part filters so we can recognize known attributes.
return filterFailsafe
}
for _, r := range s {

View file

@ -479,7 +479,7 @@ func DupCloseOnExec(fd int) (int, string, error) {
return dupCloseOnExecOld(fd)
}
// dupCloseOnExecUnixOld is the traditional way to dup an fd and
// dupCloseOnExecOld is the traditional way to dup an fd and
// set its O_CLOEXEC bit, using two system calls.
func dupCloseOnExecOld(fd int) (int, string, error) {
syscall.ForkLock.RLock()

View file

@ -150,4 +150,3 @@ set GOBUILDFAIL=1
if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
:end

View file

@ -503,7 +503,7 @@ func valueOrDefault(value, def string) string {
// NOTE: This is not intended to reflect the actual Go version being used.
// It was changed at the time of Go 1.1 release because the former User-Agent
// had ended up on a blacklist for some intrusion detection systems.
// had ended up blocked by some intrusion detection systems.
// See https://codereview.appspot.com/7532043.
const defaultUserAgent = "Go-http-client/1.1"

View file

@ -1698,9 +1698,9 @@ func (c *conn) closeWriteAndWait() {
time.Sleep(rstAvoidanceDelay)
}
// validNextProto reports whether the proto is not a blacklisted ALPN
// protocol name. Empty and built-in protocol types are blacklisted
// and can't be overridden with alternate implementations.
// validNextProto reports whether the proto is a valid ALPN protocol name.
// Everything is valid except the empty string and built-in protocol types,
// so that those can't be overridden with alternate implementations.
func validNextProto(proto string) bool {
switch proto {
case "", "http/1.1", "http/1.0":

View file

@ -202,10 +202,8 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
break
}
// On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause
// open(2) to be restarted for regular files. This is easy to reproduce on
// fuse file systems (see https://golang.org/issue/11180).
if runtime.GOOS == "darwin" && e == syscall.EINTR {
// We have to check EINTR here, per issues 11180 and 39237.
if e == syscall.EINTR {
continue
}

View file

@ -9,7 +9,6 @@ package os
import (
"internal/syscall/unix"
"io"
"runtime"
"syscall"
)
@ -178,7 +177,7 @@ func openFdAt(dirfd int, name string) (*File, error) {
}
// See comment in openFileNolog.
if runtime.GOOS == "darwin" && e == syscall.EINTR {
if e == syscall.EINTR {
continue
}

View file

@ -40,8 +40,8 @@ func (e *PtyError) Error() string {
func (e *PtyError) Unwrap() error { return e.Errno }
// Open returns a master pty and the name of the linked slave tty.
func Open() (master *os.File, slave string, err error) {
// Open returns a control pty and the name of the linked process tty.
func Open() (pty *os.File, processTTY string, err error) {
m, err := C.posix_openpt(C.O_RDWR)
if err != nil {
return nil, "", ptyError("posix_openpt", err)
@ -54,6 +54,6 @@ func Open() (master *os.File, slave string, err error) {
C.close(m)
return nil, "", ptyError("unlockpt", err)
}
slave = C.GoString(C.ptsname(m))
return os.NewFile(uintptr(m), "pty-master"), slave, nil
processTTY = C.GoString(C.ptsname(m))
return os.NewFile(uintptr(m), "pty"), processTTY, nil
}

View file

@ -19,7 +19,7 @@ import (
"io"
"os"
"os/exec"
"os/signal/internal/pty"
ptypkg "os/signal/internal/pty"
"strconv"
"strings"
"sync"
@ -71,20 +71,20 @@ func TestTerminalSignal(t *testing.T) {
// The test only fails when using a "slow device," in this
// case a pseudo-terminal.
master, sname, err := pty.Open()
pty, procTTYName, err := ptypkg.Open()
if err != nil {
ptyErr := err.(*pty.PtyError)
ptyErr := err.(*ptypkg.PtyError)
if ptyErr.FuncName == "posix_openpt" && ptyErr.Errno == syscall.EACCES {
t.Skip("posix_openpt failed with EACCES, assuming chroot and skipping")
}
t.Fatal(err)
}
defer master.Close()
slave, err := os.OpenFile(sname, os.O_RDWR, 0)
defer pty.Close()
procTTY, err := os.OpenFile(procTTYName, os.O_RDWR, 0)
if err != nil {
t.Fatal(err)
}
defer slave.Close()
defer procTTY.Close()
// Start an interactive shell.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
@ -92,9 +92,9 @@ func TestTerminalSignal(t *testing.T) {
cmd := exec.CommandContext(ctx, bash, "--norc", "--noprofile", "-i")
// Clear HISTFILE so that we don't read or clobber the user's bash history.
cmd.Env = append(os.Environ(), "HISTFILE=")
cmd.Stdin = slave
cmd.Stdout = slave
cmd.Stderr = slave
cmd.Stdin = procTTY
cmd.Stdout = procTTY
cmd.Stderr = procTTY
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
Setctty: true,
@ -105,21 +105,21 @@ func TestTerminalSignal(t *testing.T) {
t.Fatal(err)
}
if err := slave.Close(); err != nil {
t.Errorf("closing slave: %v", err)
if err := procTTY.Close(); err != nil {
t.Errorf("closing procTTY: %v", err)
}
progReady := make(chan bool)
sawPrompt := make(chan bool, 10)
const prompt = "prompt> "
// Read data from master in the background.
// Read data from pty in the background.
var wg sync.WaitGroup
wg.Add(1)
defer wg.Wait()
go func() {
defer wg.Done()
input := bufio.NewReader(master)
input := bufio.NewReader(pty)
var line, handled []byte
for {
b, err := input.ReadByte()
@ -130,11 +130,11 @@ func TestTerminalSignal(t *testing.T) {
if perr, ok := err.(*os.PathError); ok {
err = perr.Err
}
// EOF means master is closed.
// EOF means pty is closed.
// EIO means child process is done.
// "file already closed" means deferred close of master has happened.
// "file already closed" means deferred close of pty has happened.
if err != io.EOF && err != syscall.EIO && !strings.Contains(err.Error(), "file already closed") {
t.Logf("error reading from master: %v", err)
t.Logf("error reading from pty: %v", err)
}
return
}
@ -161,7 +161,7 @@ func TestTerminalSignal(t *testing.T) {
}()
// Set the bash prompt so that we can see it.
if _, err := master.Write([]byte("PS1='" + prompt + "'\n")); err != nil {
if _, err := pty.Write([]byte("PS1='" + prompt + "'\n")); err != nil {
t.Fatalf("setting prompt: %v", err)
}
select {
@ -172,7 +172,7 @@ func TestTerminalSignal(t *testing.T) {
// Start a small program that reads from stdin
// (namely the code at the top of this function).
if _, err := master.Write([]byte("GO_TEST_TERMINAL_SIGNALS=1 " + os.Args[0] + " -test.run=TestTerminalSignal\n")); err != nil {
if _, err := pty.Write([]byte("GO_TEST_TERMINAL_SIGNALS=1 " + os.Args[0] + " -test.run=TestTerminalSignal\n")); err != nil {
t.Fatal(err)
}
@ -190,7 +190,7 @@ func TestTerminalSignal(t *testing.T) {
time.Sleep(pause)
// Send a ^Z to stop the program.
if _, err := master.Write([]byte{26}); err != nil {
if _, err := pty.Write([]byte{26}); err != nil {
t.Fatalf("writing ^Z to pty: %v", err)
}
@ -202,7 +202,7 @@ func TestTerminalSignal(t *testing.T) {
}
// Restart the stopped program.
if _, err := master.Write([]byte("fg\n")); err != nil {
if _, err := pty.Write([]byte("fg\n")); err != nil {
t.Fatalf("writing %q to pty: %v", "fg", err)
}
@ -217,7 +217,7 @@ func TestTerminalSignal(t *testing.T) {
// Write some data for the program to read,
// which should cause it to exit.
if _, err := master.Write([]byte{'\n'}); err != nil {
if _, err := pty.Write([]byte{'\n'}); err != nil {
t.Fatalf("writing %q to pty: %v", "\n", err)
}
@ -229,7 +229,7 @@ func TestTerminalSignal(t *testing.T) {
}
// Exit the shell with the program's exit status.
if _, err := master.Write([]byte("exit $?\n")); err != nil {
if _, err := pty.Write([]byte("exit $?\n")); err != nil {
t.Fatalf("writing %q to pty: %v", "exit", err)
}

View file

@ -35,11 +35,6 @@ if errorlevel 1 goto fail
echo.
:norebuild
:: we must unset GOROOT_FINAL before tests, because runtime/debug requires
:: correct access to source code, so if we have GOROOT_FINAL in effect,
:: at least runtime/debug test will fail.
set GOROOT_FINAL=
:: get CGO_ENABLED
..\bin\go env > env.bat
if errorlevel 1 goto fail

View file

@ -18,12 +18,12 @@ var _cgo_sigaction unsafe.Pointer
//go:nosplit
//go:nowritebarrierrec
func sigaction(sig uint32, new, old *sigactiont) {
// The runtime package is explicitly blacklisted from sanitizer
// instrumentation in racewalk.go, but we might be calling into instrumented C
// functions here — so we need the pointer parameters to be properly marked.
// racewalk.go avoids adding sanitizing instrumentation to package runtime,
// but we might be calling into instrumented C functions here,
// so we need the pointer parameters to be properly marked.
//
// Mark the input as having been written before the call and the output as
// read after.
// Mark the input as having been written before the call
// and the output as read after.
if msanenabled && new != nil {
msanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new))
}

View file

@ -61,7 +61,7 @@ func debugCallCheck(pc uintptr) string {
"debugCall16384",
"debugCall32768",
"debugCall65536":
// These functions are whitelisted so that the debugger can initiate multiple function calls.
// These functions are allowed so that the debugger can initiate multiple function calls.
// See: https://golang.org/cl/161137/
return
}

View file

@ -976,6 +976,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
throw("malloc called with no P")
}
}
var span *mspan
var x unsafe.Pointer
noscan := typ == nil || typ.ptrdata == 0
if size <= maxSmallSize {
@ -1028,10 +1029,10 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
return x
}
// Allocate a new maxTinySize block.
span := c.alloc[tinySpanClass]
span = c.alloc[tinySpanClass]
v := nextFreeFast(span)
if v == 0 {
v, _, shouldhelpgc = c.nextFree(tinySpanClass)
v, span, shouldhelpgc = c.nextFree(tinySpanClass)
}
x = unsafe.Pointer(v)
(*[2]uint64)(x)[0] = 0
@ -1052,7 +1053,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
}
size = uintptr(class_to_size[sizeclass])
spc := makeSpanClass(sizeclass, noscan)
span := c.alloc[spc]
span = c.alloc[spc]
v := nextFreeFast(span)
if v == 0 {
v, span, shouldhelpgc = c.nextFree(spc)
@ -1063,15 +1064,14 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
}
}
} else {
var s *mspan
shouldhelpgc = true
systemstack(func() {
s = largeAlloc(size, needzero, noscan)
span = largeAlloc(size, needzero, noscan)
})
s.freeindex = 1
s.allocCount = 1
x = unsafe.Pointer(s.base())
size = s.elemsize
span.freeindex = 1
span.allocCount = 1
x = unsafe.Pointer(span.base())
size = span.elemsize
}
var scanSize uintptr
@ -1112,7 +1112,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
// This may be racing with GC so do it atomically if there can be
// a race marking the bit.
if gcphase != _GCoff {
gcmarknewobject(uintptr(x), size, scanSize)
gcmarknewobject(span, uintptr(x), size, scanSize)
}
if raceenabled {

View file

@ -1627,11 +1627,21 @@ func gcDumpObject(label string, obj, off uintptr) {
//
//go:nowritebarrier
//go:nosplit
func gcmarknewobject(obj, size, scanSize uintptr) {
func gcmarknewobject(span *mspan, obj, size, scanSize uintptr) {
if useCheckmark { // The world should be stopped so this should not happen.
throw("gcmarknewobject called while doing checkmark")
}
markBitsForAddr(obj).setMarked()
// Mark object.
objIndex := span.objIndex(obj)
span.markBitsForIndex(objIndex).setMarked()
// Mark span.
arena, pageIdx, pageMask := pageIndexOf(span.base())
if arena.pageMarks[pageIdx]&pageMask == 0 {
atomic.Or8(&arena.pageMarks[pageIdx], pageMask)
}
gcw := &getg().m.p.ptr().gcw
gcw.bytesMarked += uint64(size)
gcw.scanWork += int64(scanSize)

View file

@ -529,7 +529,7 @@ func updatememstats() {
// Calculate memory allocator stats.
// During program execution we only count number of frees and amount of freed memory.
// Current number of alive object in the heap and amount of alive heap memory
// Current number of alive objects in the heap and amount of alive heap memory
// are calculated by scanning all spans.
// Total number of mallocs is calculated as number of frees plus number of alive objects.
// Similarly, total amount of allocated memory is calculated as amount of freed memory

View file

@ -296,6 +296,13 @@ func wbBufFlush1(_p_ *p) {
continue
}
mbits.setMarked()
// Mark span.
arena, pageIdx, pageMask := pageIndexOf(span.base())
if arena.pageMarks[pageIdx]&pageMask == 0 {
atomic.Or8(&arena.pageMarks[pageIdx], pageMask)
}
if span.spanclass.noscan() {
gcw.bytesMarked += uint64(span.elemsize)
continue

View file

@ -563,8 +563,8 @@ func moduledataverify1(datap *moduledata) {
// given program counter address, or else nil.
//
// If pc represents multiple functions because of inlining, it returns
// the a *Func describing the innermost function, but with an entry
// of the outermost function.
// the *Func describing the innermost function, but with an entry of
// the outermost function.
func FuncForPC(pc uintptr) *Func {
f := findfunc(pc)
if !f.valid() {

View file

@ -253,6 +253,8 @@ func CmpLogicalToZero(a, b, c uint32, d, e uint64) uint64 {
// 'comparing to zero' expressions
// var + const
// 'x-const' might be canonicalized to 'x+(-const)', so we check both
// CMN and CMP for subtraction expressions to make the pattern robust.
func CmpToZero_ex1(a int64, e int32) int {
// arm64:`CMN`,-`ADD`,`(BMI|BPL)`
if a+3 < 0 {
@ -269,37 +271,41 @@ func CmpToZero_ex1(a int64, e int32) int {
return 2
}
// arm64:`CMP`,-`SUB`,`(BMI|BPL)`
// arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
if a-7 < 0 {
return 3
}
// arm64:`CMP`,-`SUB`,`(BMI|BPL)`
// arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
if a-11 >= 0 {
return 4
}
// arm64:`CMP`,-`SUB`,`BEQ`,`(BMI|BPL)`
// arm64:`CMP|CMN`,-`(ADD|SUB)`,`BEQ`,`(BMI|BPL)`
if a-19 > 0 {
return 4
}
// arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
// arm:`CMN`,-`ADD`,`(BMI|BPL)`
if e+3 < 0 {
return 5
}
// arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
// arm:`CMN`,-`ADD`,`(BMI|BPL)`
if e+13 >= 0 {
return 6
}
// arm64:`CMPW`,-`SUBW`,`(BMI|BPL)`
// arm64:`CMPW|CMNW`,`(BMI|BPL)`
// arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
if e-7 < 0 {
return 7
}
// arm64:`CMPW`,-`SUBW`,`(BMI|BPL)`
// arm64:`CMPW|CMNW`,`(BMI|BPL)`
// arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
if e-11 >= 0 {
return 8
}
@ -326,11 +332,13 @@ func CmpToZero_ex2(a, b, c int64, e, f, g int32) int {
}
// arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
// arm:`CMN`,-`ADD`,`(BMI|BPL)`
if e+f < 0 {
return 5
}
// arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
// arm:`CMN`,-`ADD`,`(BMI|BPL)`
if f+g >= 0 {
return 6
}
@ -350,11 +358,13 @@ func CmpToZero_ex3(a, b, c, d int64, e, f, g, h int32) int {
}
// arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
// arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
if e+f*g > 0 {
return 5
}
// arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
// arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
if f+g*h <= 0 {
return 6
}
@ -384,3 +394,16 @@ func CmpToZero_ex4(a, b, c, d int64, e, f, g, h int32) int {
}
return 0
}
func CmpToZero_ex5(e, f int32, u uint32) int {
// arm:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
if e+f<<1 > 0 {
return 1
}
// arm:`CMP`,-`SUB`,`(BMI|BPL)`
if f-int32(u>>2) >= 0 {
return 2
}
return 0
}

View file

@ -0,0 +1,12 @@
// compile -N
// 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 p
func f(x float64) bool {
x += 1
return (x != 0) == (x != 0)
}

View file

@ -4,8 +4,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Check that batch files are maintained as CRLF files (consistent behaviour
// on all operating systems). See https://github.com/golang/go/issues/37791
// Check that batch files are maintained as CRLF files (consistent
// behavior on all operating systems). See golang.org/issue/37791.
package main
@ -13,18 +13,56 @@ import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"runtime"
"strings"
)
func main() {
batches, _ := filepath.Glob(runtime.GOROOT() + "/src/*.bat")
for _, bat := range batches {
body, _ := ioutil.ReadFile(bat)
if !bytes.Contains(body, []byte("\r\n")) {
fmt.Printf("Windows batch file %s does not contain CRLF line termination.\nTry running git checkout src/*.bat to fix this.\n", bat)
os.Exit(1)
// Ensure that the GOROOT/src/all.bat file exists and has strict CRLF line endings.
enforceBatchStrictCRLF(filepath.Join(runtime.GOROOT(), "src", "all.bat"))
// Walk the entire Go repository source tree (without GOROOT/pkg),
// skipping directories that start with "." and named "testdata",
// and ensure all .bat files found have exact CRLF line endings.
err := filepath.Walk(runtime.GOROOT(), func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
if fi.IsDir() && (strings.HasPrefix(fi.Name(), ".") || fi.Name() == "testdata") {
return filepath.SkipDir
}
if path == filepath.Join(runtime.GOROOT(), "pkg") {
// GOROOT/pkg is known to contain generated artifacts, not source code.
// Skip it to avoid false positives. (Also see golang.org/issue/37929.)
return filepath.SkipDir
}
if filepath.Ext(fi.Name()) == ".bat" {
enforceBatchStrictCRLF(path)
}
return nil
})
if err != nil {
log.Fatalln(err)
}
}
func enforceBatchStrictCRLF(path string) {
b, err := ioutil.ReadFile(path)
if err != nil {
log.Fatalln(err)
}
cr, lf := bytes.Count(b, []byte{13}), bytes.Count(b, []byte{10})
crlf := bytes.Count(b, []byte{13, 10})
if cr != crlf || lf != crlf {
if rel, err := filepath.Rel(runtime.GOROOT(), path); err == nil {
// Make the test failure more readable by showing a path relative to GOROOT.
path = rel
}
fmt.Printf("Windows batch file %s does not use strict CRLF line termination.\n", path)
fmt.Printf("Please convert it to CRLF before checking it in due to golang.org/issue/37791.\n")
os.Exit(1)
}
}