[dev.boringcrypto] all: merge commit 9d0819b27c (CL 314609) into dev.boringcrypto

There used to be two BoringCrypto-specific behaviors related to cipher
suites in crypto/tls:

1. in FIPS-only mode, only a restricted set of AES ciphers is allowed

2. NOT in FIPS-only mode, AES would be prioritized over ChaCha20 even if
   AES hardware was not available

The motivation of (2) is unclear, and BoringSSL doesn't have equivalent
logic. This merge drops (2), and keeps (1). Note that the list of
FIPS-only ciphers does not have priority semantics anymore, but the
default logic still sorts them the same way as they used to be.

Change-Id: I50544011085cfa2b087f323aebf5338c0bd2dd33
This commit is contained in:
Filippo Valsorda 2021-05-12 19:23:21 +02:00
commit ed1f812cef
3217 changed files with 116892 additions and 55301 deletions

1
.gitignore vendored
View file

@ -37,6 +37,7 @@ _testmain.go
/src/cmd/internal/objabi/zbootstrap.go
/src/go/build/zcgo.go
/src/go/doc/headscan
/src/internal/buildcfg/zbootstrap.go
/src/runtime/internal/sys/zversion.go
/src/unicode/maketables
/test.out

View file

@ -145,7 +145,7 @@ Andy Davis <andy@bigandian.com>
Andy Finkenstadt <afinkenstadt@zynga.com>
Andy Lindeman <andy@lindeman.io>
Andy Maloney <asmaloney@gmail.com>
Andy Pan <panjf2000@gmail.com>
Andy Pan <panjf2000@gmail.com> <panjf2000@golangcn.org> <i@andypan.me>
Andy Walker <walkeraj@gmail.com>
Anfernee Yongkun Gui <anfernee.gui@gmail.com>
Angelo Bulfone <mbulfone@gmail.com>
@ -195,7 +195,7 @@ Ayanamist Yang <ayanamist@gmail.com>
Aymerick Jéhanne <aymerick@jehanne.org>
Azat Kaumov <kaumov.a.r@gmail.com>
Baiju Muthukadan <baiju.m.mail@gmail.com>
Baokun Lee <nototon@gmail.com>
Baokun Lee <nototon@gmail.com> <bk@golangcn.org>
Bartosz Grzybowski <melkorm@gmail.com>
Bastian Ike <bastian.ike@gmail.com>
Ben Burkert <ben@benburkert.com>
@ -1425,6 +1425,7 @@ Wèi Cōngruì <crvv.mail@gmail.com>
Wei Fu <fhfuwei@163.com>
Wei Guangjing <vcc.163@gmail.com>
Weichao Tang <tevic.tt@gmail.com>
Weixie Cui <cuiweixie@gmail.com> <523516579@qq.com>
Wembley G. Leach, Jr <wembley.gl@gmail.com>
Will Faught <will.faught@gmail.com>
Will Storey <will@summercat.com>

View file

@ -240,7 +240,7 @@ Andy Davis <andy@bigandian.com>
Andy Finkenstadt <afinkenstadt@zynga.com>
Andy Lindeman <andy@lindeman.io>
Andy Maloney <asmaloney@gmail.com>
Andy Pan <panjf2000@gmail.com>
Andy Pan <panjf2000@gmail.com> <panjf2000@golangcn.org> <i@andypan.me>
Andy Walker <walkeraj@gmail.com>
Andy Wang <cbeuw.andy@gmail.com>
Andy Williams <andy@andy.xyz>
@ -321,7 +321,7 @@ Azat Kaumov <kaumov.a.r@gmail.com>
Baiju Muthukadan <baiju.m.mail@gmail.com>
Balaram Makam <bmakam.qdt@qualcommdatacenter.com>
Balazs Lecz <leczb@google.com>
Baokun Lee <nototon@gmail.com>
Baokun Lee <nototon@gmail.com> <bk@golangcn.org>
Barnaby Keene <accounts@southcla.ws>
Bartosz Grzybowski <melkorm@gmail.com>
Bartosz Oler <brtsz@google.com>
@ -466,7 +466,7 @@ Charlotte Brandhorst-Satzkorn <catzkorn@gmail.com>
Chauncy Cullitan <chauncyc@google.com>
Chen Zhidong <njutczd@gmail.com>
Chen Zhihan <energiehund@gmail.com>
Cherry Zhang <cherryyz@google.com>
Cherry Mui <cherryyz@google.com>
Chew Choon Keat <choonkeat@gmail.com>
Chiawen Chen <golopot@gmail.com>
Chirag Sukhala <cchirag77@gmail.com>
@ -2526,6 +2526,7 @@ Wei Guangjing <vcc.163@gmail.com>
Wei Xiao <wei.xiao@arm.com>
Wei Xikai <xykwei@gmail.com>
Weichao Tang <tevic.tt@gmail.com>
Weixie Cui <cuiweixie@gmail.com> <523516579@qq.com>
Wembley G. Leach, Jr <wembley.gl@gmail.com>
Wenlei (Frank) He <wlhe@google.com>
Wenzel Lowe <lowewenzel@gmail.com>

View file

@ -1,4 +1,7 @@
pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
pkg math, const MaxFloat64 = 1.79769e+308 // 179769313486231570814527423731704356798100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
pkg math, const SmallestNonzeroFloat32 = 1.4013e-45 // 17516230804060213386546619791123951641/12500000000000000000000000000000000000000000000000000000000000000000000000000000000
pkg math, const SmallestNonzeroFloat64 = 4.94066e-324 // 4940656458412465441765687928682213723651/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
pkg math/big, const MaxBase = 36
pkg math/big, type Word uintptr
pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)

View file

@ -0,0 +1,99 @@
pkg compress/lzw, method (*Reader) Close() error
pkg compress/lzw, method (*Reader) Read([]uint8) (int, error)
pkg compress/lzw, method (*Reader) Reset(io.Reader, Order, int)
pkg compress/lzw, method (*Writer) Close() error
pkg compress/lzw, method (*Writer) Reset(io.Writer, Order, int)
pkg compress/lzw, method (*Writer) Write([]uint8) (int, error)
pkg compress/lzw, type Reader struct
pkg compress/lzw, type Writer struct
pkg crypto/tls, method (*CertificateRequestInfo) Context() context.Context
pkg crypto/tls, method (*ClientHelloInfo) Context() context.Context
pkg crypto/tls, method (*Conn) HandshakeContext(context.Context) error
pkg debug/elf, const SHT_MIPS_ABIFLAGS = 1879048234
pkg debug/elf, const SHT_MIPS_ABIFLAGS SectionType
pkg encoding/csv, method (*Reader) FieldPos(int) (int, int)
pkg go/ast, method (*FuncDecl) IsMethod() bool
pkg go/build, type Context struct, ToolTags []string
pkg go/parser, const SkipObjectResolution = 64
pkg go/parser, const SkipObjectResolution Mode
pkg go/types, type Config struct, GoVersion string
pkg io/fs, func FileInfoToDirEntry(FileInfo) DirEntry
pkg net, method (*ParseError) Temporary() bool
pkg net, method (*ParseError) Timeout() bool
pkg net, method (IP) IsPrivate() bool
pkg reflect, func VisibleFields(Type) []StructField
pkg reflect, method (Method) IsExported() bool
pkg reflect, method (StructField) IsExported() bool
pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete()
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (darwin-amd64-cgo), type Handle uintptr
pkg runtime/cgo (freebsd-386-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (freebsd-386-cgo), method (Handle) Delete()
pkg runtime/cgo (freebsd-386-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (freebsd-386-cgo), type Handle uintptr
pkg runtime/cgo (freebsd-amd64-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (freebsd-amd64-cgo), method (Handle) Delete()
pkg runtime/cgo (freebsd-amd64-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (freebsd-amd64-cgo), type Handle uintptr
pkg runtime/cgo (freebsd-arm-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (freebsd-arm-cgo), method (Handle) Delete()
pkg runtime/cgo (freebsd-arm-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (freebsd-arm-cgo), type Handle uintptr
pkg runtime/cgo (linux-386-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (linux-386-cgo), method (Handle) Delete()
pkg runtime/cgo (linux-386-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (linux-386-cgo), type Handle uintptr
pkg runtime/cgo (linux-amd64-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (linux-amd64-cgo), method (Handle) Delete()
pkg runtime/cgo (linux-amd64-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (linux-amd64-cgo), type Handle uintptr
pkg runtime/cgo (linux-arm-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (linux-arm-cgo), method (Handle) Delete()
pkg runtime/cgo (linux-arm-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (linux-arm-cgo), type Handle uintptr
pkg runtime/cgo (netbsd-386-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (netbsd-386-cgo), method (Handle) Delete()
pkg runtime/cgo (netbsd-386-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (netbsd-386-cgo), type Handle uintptr
pkg runtime/cgo (netbsd-amd64-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (netbsd-amd64-cgo), method (Handle) Delete()
pkg runtime/cgo (netbsd-amd64-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (netbsd-amd64-cgo), type Handle uintptr
pkg runtime/cgo (netbsd-arm-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (netbsd-arm-cgo), method (Handle) Delete()
pkg runtime/cgo (netbsd-arm-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (netbsd-arm-cgo), type Handle uintptr
pkg runtime/cgo (netbsd-arm64-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (netbsd-arm64-cgo), method (Handle) Delete()
pkg runtime/cgo (netbsd-arm64-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (netbsd-arm64-cgo), type Handle uintptr
pkg runtime/cgo (openbsd-386-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (openbsd-386-cgo), method (Handle) Delete()
pkg runtime/cgo (openbsd-386-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (openbsd-386-cgo), type Handle uintptr
pkg runtime/cgo (openbsd-amd64-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (openbsd-amd64-cgo), method (Handle) Delete()
pkg runtime/cgo (openbsd-amd64-cgo), method (Handle) Value() interface{}
pkg runtime/cgo (openbsd-amd64-cgo), type Handle uintptr
pkg syscall (openbsd-386), const MSG_CMSG_CLOEXEC = 2048
pkg syscall (openbsd-386), const MSG_CMSG_CLOEXEC ideal-int
pkg syscall (openbsd-386-cgo), const MSG_CMSG_CLOEXEC = 2048
pkg syscall (openbsd-386-cgo), const MSG_CMSG_CLOEXEC ideal-int
pkg syscall (openbsd-amd64), const MSG_CMSG_CLOEXEC = 2048
pkg syscall (openbsd-amd64), const MSG_CMSG_CLOEXEC ideal-int
pkg syscall (openbsd-amd64-cgo), const MSG_CMSG_CLOEXEC = 2048
pkg syscall (openbsd-amd64-cgo), const MSG_CMSG_CLOEXEC ideal-int
pkg syscall (windows-386), type SysProcAttr struct, AdditionalInheritedHandles []Handle
pkg syscall (windows-386), type SysProcAttr struct, ParentProcess Handle
pkg syscall (windows-amd64), type SysProcAttr struct, AdditionalInheritedHandles []Handle
pkg syscall (windows-amd64), type SysProcAttr struct, ParentProcess Handle
pkg testing, method (*B) Setenv(string, string)
pkg testing, method (*T) Setenv(string, string)
pkg text/template/parse, const SkipFuncCheck = 2
pkg text/template/parse, const SkipFuncCheck Mode
pkg time, func UnixMicro(int64) Time
pkg time, func UnixMilli(int64) Time
pkg time, method (*Time) IsDST() bool
pkg time, method (Time) UnixMicro() int64
pkg time, method (Time) UnixMilli() int64

File diff suppressed because it is too large Load diff

535
doc/go1.17.html Normal file
View file

@ -0,0 +1,535 @@
<!--{
"Title": "Go 1.17 Release Notes",
"Path": "/doc/go1.17"
}-->
<!--
NOTE: In this document and others in this directory, the convention is to
set fixed-width phrases with non-fixed-width spaces, as in
<code>hello</code> <code>world</code>.
Do not send CLs removing the interior tags from such phrases.
-->
<style>
main ul li { margin: 0.5em 0; }
</style>
<h2 id="introduction">DRAFT RELEASE NOTES — Introduction to Go 1.17</h2>
<p>
<strong>
Go 1.17 is not yet released. These are work-in-progress
release notes. Go 1.17 is expected to be released in August 2021.
</strong>
</p>
<h2 id="language">Changes to the language</h2>
<p><!-- CL 216424 -->
TODO: <a href="https://golang.org/cl/216424">https://golang.org/cl/216424</a>: allow conversion from slice to array ptr
</p>
<p><!-- CL 312212 -->
TODO: <a href="https://golang.org/cl/312212">https://golang.org/cl/312212</a>: add unsafe.Add and unsafe.Slice
</p>
<h2 id="ports">Ports</h2>
<h3 id="darwin">Darwin</h3>
<p><!-- golang.org/issue/23011 -->
As <a href="go1.16#darwin">announced</a> in the Go 1.16 release
notes, Go 1.17 requires macOS 10.13 High Sierra or later; support
for previous versions has been discontinued.
</p>
<p>
TODO: complete the Ports section
</p>
<h2 id="tools">Tools</h2>
<p>
TODO: complete the Tools section
</p>
<h3 id="go-command">Go command</h3>
<h4 id="lazy-loading">Lazy module loading</h4>
<p><!-- golang.org/issue/36460 -->
If a module specifies <code>go</code> <code>1.17</code> or higher in its
<code>go.mod</code> file, its transitive requirements are now loaded lazily,
avoding the need to download or read <code>go.mod</code> files for
otherwise-irrelevant dependencies. To support lazy loading, in Go 1.17 modules
the <code>go</code> command maintains <em>explicit</em> requirements in
the <code>go.mod</code> file for every dependency that provides any package
transitively imported by any package or test within the module.
See <a href="https://golang.org/design/36460-lazy-module-loading">the design
document</a> for more detail.
<!-- TODO(bcmills): replace the design-doc link with proper documentation. -->
</p>
<p><!-- golang.org/issue/45094 --> To facilitate the upgrade to lazy loading,
the <code>go</code> <code>mod</code> <code>tidy</code> subcommand now supports
a <code>-go</code> flag to set or change the <code>go</code> version in
the <code>go.mod</code> file. To enable lazy loading for an existing module
without changing the selected versions of its dependencies, run:
</p>
<pre>
go mod tidy -go=1.17
</pre>
<h4 id="module-deprecation-comments">Module deprecation comments</h4>
<p><!-- golang.org/issue/40357 -->
Module authors may deprecate a module by adding a
<a href="/ref/mod#go-mod-file-module-deprecation"><code>// Deprecated:</code>
comment</a> to <code>go.mod</code>, then tagging a new version.
<code>go</code> <code>get</code> now prints a warning if a module needed to
build packages named on the command line is deprecated. <code>go</code>
<code>list</code> <code>-m</code> <code>-u</code> prints deprecations for all
dependencies (use <code>-f</code> or <code>-json</code> to show the full
message). The <code>go</code> command considers different major versions to
be distinct modules, so this mechanism may be used, for example, to provide
users with migration instructions for a new major version.
</p>
<h4 id="go-get"><code>go</code> <code>get</code></h4>
<p><!-- golang.org/issue/37519 -->
The <code>go</code> <code>get</code> <code>-insecure</code> flag is
deprecated and has been removed. To permit the use of insecure schemes
when fetching dependencies, please use the <code>GOINSECURE</code>
environment variable. The <code>-insecure</code> flag also bypassed module
sum validation, use <code>GOPRIVATE</code> or <code>GONOSUMDB</code> if
you need that functionality. See <code>go</code> <code>help</code>
<code>environment</code> for details.
</p>
<h4 id="missing-go-directive"><code>go.mod</code> files missing <code>go</code> directives</h4>
<p><!-- golang.org/issue/44976 -->
If the main module's <code>go.mod</code> file does not contain
a <a href="/doc/modules/gomod-ref#go"><code>go</code> directive</a> and
the <code>go</code> command cannot update the <code>go.mod</code> file, the
<code>go</code> command now assumes <code>go 1.11</code> instead of the
current release. (<code>go</code> <code>mod</code> <code>init</code> has added
<code>go</code> directives automatically <a href="/doc/go1.12#modules">since
Go 1.12</a>.)
</p>
<p><!-- golang.org/issue/44976 -->
If a module dependency lacks an explicit <code>go.mod</code> file, or
its <code>go.mod</code> file does not contain
a <a href="/doc/modules/gomod-ref#go"><code>go</code> directive</a>,
the <code>go</code> command now assumes <code>go 1.16</code> for that
dependency instead of the current release. (Dependencies developed in GOPATH
mode may lack a <code>go.mod</code> file, and
the <code>vendor/modules.txt</code> has to date never recorded
the <code>go</code> versions indicated by dependencies' <code>go.mod</code>
files.)
</p>
<h4 id="vendor"><code>vendor</code> contents</h4>
<p><!-- golang.org/issue/36876 -->
If the main module specifies <code>go</code> <code>1.17</code> or higher,
<code>go</code> <code>mod</code> <code>vendor</code> now annotates
<code>vendor/modules.txt</code> with the <code>go</code> version indicated by
each vendored module in its own <code>go.mod</code> file. The annotated
version is used when building the module's packages from vendored source code.
</p>
<p><!-- golang.org/issue/42970 -->
If the main module specifies <code>go</code> <code>1.17</code> or higher,
<code>go</code> <code>mod</code> <code>vendor</code> now omits <code>go.mod</code>
and <code>go.sum</code> files for vendored dependencies, which can otherwise
interfere with the ability of the <code>go</code> command to identify the correct
module root when invoked within the <code>vendor</code> tree.
</p>
<h4 id="password-prompts">Password prompts</h4>
<p><!-- golang.org/issue/44904 -->
The <code>go</code> command by default now suppresses SSH password prompts and
Git Credential Manager prompts when fetching Git repositories using SSH, as it
already did previously for other Git password prompts. Users authenticating to
private Git repos with password-protected SSH may configure
an <code>ssh-agent</code> to enable the <code>go</code> command to use
password-protected SSH keys.
</p>
<p><!-- CL 249759 -->
TODO: <a href="https://golang.org/cl/249759">https://golang.org/cl/249759</a>: cmd/cover: replace code using optimized golang.org/x/tools/cover
</p>
<h3 id="vet">Vet</h3>
<p><!-- CL 299532 -->
TODO: <a href="https://golang.org/cl/299532">https://golang.org/cl/299532</a>: cmd/vet: bring in sigchanyzer to report unbuffered channels to signal.Notify
</p>
<p>
TODO: complete the Vet section
</p>
<h2 id="runtime">Runtime</h2>
<p><!-- CL 304470 -->
TODO: <a href="https://golang.org/cl/304470">https://golang.org/cl/304470</a>: cmd/compile, runtime: add metadata for argument printing in traceback
</p>
<p>
TODO: complete the Runtime section
</p>
<h2 id="compiler">Compiler</h2>
<p>
TODO: complete the Compiler section, or delete if not needed
</p>
<h2 id="linker">Linker</h2>
<p>
TODO: complete the Linker section, or delete if not needed
</p>
<h2 id="library">Core library</h2>
<p>
TODO: complete the Core library section
</p>
<h3 id="crypto/tls"><a href="/pkg/crypto/tls">crypto/tls</a></h3>
<p><!-- CL 295370 -->
<a href="/pkg/crypto/tls#Conn.HandshakeContext">(*Conn).HandshakeContext</a> was added to
allow the user to control cancellation of an in-progress TLS Handshake.
The context provided is propagated into the
<a href="/pkg/crypto/tls#ClientHelloInfo">ClientHelloInfo</a>
and <a href="/pkg/crypto/tls#CertificateRequestInfo">CertificateRequestInfo</a>
structs and accessible through the new
<a href="/pkg/crypto/tls#ClientHelloInfo.Context">(*ClientHelloInfo).Context</a>
and
<a href="/pkg/crypto/tls#CertificateRequestInfo.Context">
(*CertificateRequestInfo).Context
</a> methods respectively. Canceling the context after the handshake has finished
has no effect.
</p>
<p><!-- CL 289209 -->
When <a href="/pkg/crypto/tls#Config">Config.NextProtos</a> is set, servers now
enforce that there is an overlap between the configured protocols and the protocols
advertised by the client, if any. If there is no overlap the connection is closed
with the <code>no_application_protocol</code> alert, as required by RFC 7301.
</p>
<h3 id="runtime/cgo"><a href="/pkg/runtime/cgo">Cgo</a></h3>
<p>
The <a href="/pkg/runtime/cgo">runtime/cgo</a> package now provides a
new facility that allows to turn any Go values to a safe representation
that can be used to pass values between C and Go safely. See
<a href="/pkg/runtime/cgo#Handle">runtime/cgo.Handle</a> for more information.
</p>
<h3 id="minor_library_changes">Minor changes to the library</h3>
<p>
As always, there are various minor changes and updates to the library,
made with the Go 1 <a href="/doc/go1compat">promise of compatibility</a>
in mind.
</p>
<dl id="archive/zip"><dt><a href="/pkg/archive/zip/">archive/zip</a></dt>
<dd>
<p><!-- CL 312310 -->
TODO: <a href="https://golang.org/cl/312310">https://golang.org/cl/312310</a>: add File.OpenRaw, Writer.CreateRaw, Writer.Copy
</p>
</dd>
</dl><!-- archive/zip -->
<dl id="bufio"><dt><a href="/pkg/bufio/">bufio</a></dt>
<dd>
<p><!-- CL 280492 -->
The <a href="/pkg/bufio/#Writer.WriteRune"><code>Writer.WriteRune</code></a> method
now writes the replacement character U+FFFD for negative rune values,
as it does for other invalid runes.
</p>
</dd>
</dl><!-- bufio -->
<dl id="bytes"><dt><a href="/pkg/bytes/">bytes</a></dt>
<dd>
<p><!-- CL 280492 -->
The <a href="/pkg/bytes/#Buffer.WriteRune"><code>Buffer.WriteRune</code></a> method
now writes the replacement character U+FFFD for negative rune values,
as it does for other invalid runes.
</p>
</dd>
</dl><!-- bytes -->
<dl id="compress/lzw"><dt><a href="/pkg/compress/lzw/">compress/lzw</a></dt>
<dd>
<p><!-- CL 273667 -->
The new
<a href="/pkg/compress/lzw/#Reader.Reset"><code>Reader.Reset</code></a>
and
<a href="/pkg/compress/lzw/#Writer.Reset"><code>Writer.Reset</code></a>
methods allow reuse of a <code>Reader</code> or <code>Writer</code>.
</p>
</dd>
</dl><!-- compress/lzw -->
<dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
<dd>
<p><!-- CL 302230 -->
TODO: <a href="https://golang.org/cl/302230">https://golang.org/cl/302230</a>: fix salt length calculation with PSSSaltLengthAuto
</p>
</dd>
</dl><!-- crypto/rsa -->
<dl id="database/sql"><dt><a href="/pkg/database/sql/">database/sql</a></dt>
<dd>
<p><!-- CL 258360 -->
TODO: <a href="https://golang.org/cl/258360">https://golang.org/cl/258360</a>: close driver.Connector if it implements io.Closer
</p>
<p><!-- CL 311572 -->
TODO: <a href="https://golang.org/cl/311572">https://golang.org/cl/311572</a>: add NullInt16 and NullByte
</p>
</dd>
</dl><!-- database/sql -->
<dl id="encoding/binary"><dt><a href="/pkg/encoding/binary/">encoding/binary</a></dt>
<dd>
<p><!-- CL 299531 -->
<code>binary.Uvarint</code> will stop reading after <code>10 bytes</code> to avoid
wasted computations. If more than <code>10 bytes</code> are needed, the byte count returned is <code>-11</code>.
<br />
Previous Go versions could return larger negative counts when reading incorrectly encoded varints.
</p>
</dd>
</dl><!-- encoding/binary -->
<dl id="flag"><dt><a href="/pkg/flag/">flag</a></dt>
<dd>
<p><!-- CL 271788 -->
TODO: <a href="https://golang.org/cl/271788">https://golang.org/cl/271788</a>: panic if flag name begins with - or contains =
</p>
</dd>
</dl><!-- flag -->
<dl id="io/fs"><dt><a href="/pkg/io/fs/">io/fs</a></dt>
<dd>
<p><!-- CL 293649 -->
TODO: <a href="https://golang.org/cl/293649">https://golang.org/cl/293649</a>: implement FileInfoToDirEntry
</p>
</dd>
</dl><!-- io/fs -->
<dl id="math"><dt><a href="/pkg/math/">math</a></dt>
<dd>
<p><!-- CL 247058 -->
TODO: <a href="https://golang.org/cl/247058">https://golang.org/cl/247058</a>: add MaxUint, MinInt, MaxInt
</p>
</dd>
</dl><!-- math -->
<dl id="mime"><dt><a href="/pkg/mime/">mime</a></dt>
<dd>
<p><!-- CL 305230 -->
TODO: <a href="https://golang.org/cl/305230">https://golang.org/cl/305230</a>: support reading shared mime-info database on unix systems
</p>
</dd>
</dl><!-- mime -->
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
<dd>
<p><!-- CL 272668 -->
TODO: <a href="https://golang.org/cl/272668">https://golang.org/cl/272668</a>: add IP.IsPrivate
</p>
<p><!-- CL 301709 -->
TODO: <a href="https://golang.org/cl/301709">https://golang.org/cl/301709</a>: make go resolver aware of network parameter
</p>
<p><!-- CL 307030 -->
TODO: <a href="https://golang.org/cl/307030">https://golang.org/cl/307030</a>: make ErrClosed and ParseError implement net.Error
</p>
</dd>
</dl><!-- net -->
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
<dd>
<p><!-- CL 295370 -->
The <a href="/pkg/net/http/"><code>net/http</code></a> package now uses the new
<a href="/pkg/crypto/tls#Conn.HandshakeContext"><code>(*tls.Conn).HandshakeContext</code></a>
with the <a href="/pkg/net/http/#Request"><code>Request</code></a> context
when performing TLS handshakes in the client or server.
</p>
<p><!-- CL 235437 -->
TODO: <a href="https://golang.org/cl/235437">https://golang.org/cl/235437</a>: add to deadlines only when positive
</p>
<p><!-- CL 308952 -->
TODO: <a href="https://golang.org/cl/308952">https://golang.org/cl/308952</a>: make ReadRequest return an error when requests have multiple Host headers
</p>
</dd>
</dl><!-- net/http -->
<dl id="net/http/httptest"><dt><a href="/pkg/net/http/httptest/">net/http/httptest</a></dt>
<dd>
<p><!-- CL 308950 -->
TODO: <a href="https://golang.org/cl/308950">https://golang.org/cl/308950</a>: panic on non-3 digit (XXX) status code in Recorder.WriteHeader
</p>
</dd>
</dl><!-- net/http/httptest -->
<dl id="net/url"><dt><a href="/pkg/net/url/">net/url</a></dt>
<dd>
<p><!-- CL 314850 -->
TODO: <a href="https://golang.org/cl/314850">https://golang.org/cl/314850</a>: add Values.Has
</p>
</dd>
</dl><!-- net/url -->
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
<dd>
<p><!-- CL 268020 -->
TODO: <a href="https://golang.org/cl/268020">https://golang.org/cl/268020</a>: avoid allocation in File.WriteString
</p>
</dd>
</dl><!-- os -->
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
<dd>
<p><!-- CL 266197 -->
The new
<a href="/pkg/reflect/#StructField.IsExported"><code>StructField.IsExported</code></a>
and
<a href="/pkg/reflect/#Method.IsExported"><code>Method.IsExported</code></a>
methods report whether a struct field or type method is exported.
They provide a more readable alternative to checking whether <code>PkgPath</code>
is empty.
</p>
<p><!-- CL 281233 -->
TODO: <a href="https://golang.org/cl/281233">https://golang.org/cl/281233</a>: add VisibleFields function
</p>
<p><!-- CL 284136 -->
TODO: <a href="https://golang.org/cl/284136">https://golang.org/cl/284136</a>: panic if ArrayOf is called with negative length
</p>
</dd>
</dl><!-- reflect -->
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
<dd>
<p><!-- CL 170079 -->
TODO: <a href="https://golang.org/cl/170079">https://golang.org/cl/170079</a>: implement Ryū-like algorithm for fixed precision ftoa
</p>
<p><!-- CL 170080 -->
TODO: <a href="https://golang.org/cl/170080">https://golang.org/cl/170080</a>: Implement Ryū algorithm for ftoa shortest mode
</p>
<p><!-- CL 314775 -->
The new <a href="/pkg/strconv/#QuotedPrefix"><code>QuotedPrefix</code></a> function
returns the quoted string (as understood by
<a href="/pkg/strconv/#Unquote"><code>Unquote</code></a>)
at the start of input.
</p>
</dd>
</dl><!-- strconv -->
<dl id="strings"><dt><a href="/pkg/strings/">strings</a></dt>
<dd>
<p><!-- CL 280492 -->
The <a href="/pkg/strings/#Builder.WriteRune"><code>Builder.WriteRune</code></a> method
now writes the replacement character U+FFFD for negative rune values,
as it does for other invalid runes.
</p>
</dd>
</dl><!-- strings -->
<dl id="sync/atomic"><dt><a href="/pkg/sync/atomic/">sync/atomic</a></dt>
<dd>
<p><!-- CL 241678 -->
TODO: <a href="https://golang.org/cl/241678">https://golang.org/cl/241678</a>: add (*Value).Swap and (*Value).CompareAndSwap
</p>
</dd>
</dl><!-- sync/atomic -->
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
<dd>
<p><!-- CL 295371 -->
TODO: <a href="https://golang.org/cl/295371">https://golang.org/cl/295371</a>: do not overflow key memory in GetQueuedCompletionStatus
</p>
<p><!-- CL 313653 -->
TODO: <a href="https://golang.org/cl/313653">https://golang.org/cl/313653</a>: restore signal mask after setting foreground process group
</p>
</dd>
</dl><!-- syscall -->
<dl id="testing"><dt><a href="/pkg/testing/">testing</a></dt>
<dd>
<p><!-- CL 310033 -->
TODO: <a href="https://golang.org/cl/310033">https://golang.org/cl/310033</a>: add -shuffle=off|on|N to alter the execution order of tests and benchmarks
</p>
</dd>
</dl><!-- testing -->
<dl id="text/template/parse"><dt><a href="/pkg/text/template/parse/">text/template/parse</a></dt>
<dd>
<p><!-- CL 301493 -->
TODO: <a href="https://golang.org/cl/301493">https://golang.org/cl/301493</a>: add a mode to skip func-check on parsing
</p>
</dd>
</dl><!-- text/template/parse -->
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
<dd>
<p><!-- CL 260858 -->
time.Time now has a <a href="/pkg/time/#Time.GoString">GoString</a>
method that will return a more useful value for times when printed with
the <code>"%#v"</code> format specifier in the fmt package.
</p>
<p><!-- CL 264077 -->
TODO: <a href="https://golang.org/cl/264077">https://golang.org/cl/264077</a>: add Time.IsDST() to check if its Location is in Daylight Savings Time
</p>
<p><!-- CL 293349 -->
TODO: <a href="https://golang.org/cl/293349">https://golang.org/cl/293349</a>: add Time.Unix{Milli,Micro} and to-Time helpers UnixMicro, UnixMilli
</p>
<p><!-- CL 300996 -->
TODO: <a href="https://golang.org/cl/300996">https://golang.org/cl/300996</a>: support &#34;,&#34; as separator for fractional seconds
</p>
</dd>
</dl><!-- time -->
<dl id="unicode"><dt><a href="/pkg/unicode/">unicode</a></dt>
<dd>
<p><!-- CL 280493 -->
The <a href="/pkg/unicode/#Is"><code>Is</code></a>,
<a href="/pkg/unicode/#IsGraphic"><code>IsGraphic</code></a>,
<a href="/pkg/unicode/#IsLetter"><code>IsLetter</code></a>,
<a href="/pkg/unicode/#IsLower"><code>IsLower</code></a>,
<a href="/pkg/unicode/#IsMark"><code>IsMark</code></a>,
<a href="/pkg/unicode/#IsNumber"><code>IsNumber</code></a>,
<a href="/pkg/unicode/#IsPrint"><code>IsPrint</code></a>,
<a href="/pkg/unicode/#IsPunct"><code>IsPunct</code></a>,
<a href="/pkg/unicode/#IsSpace"><code>IsSpace</code></a>,
<a href="/pkg/unicode/#IsSymbol"><code>IsSymbol</code></a>, and
<a href="/pkg/unicode/#IsUpper"><code>IsUpper</code></a> functions
now return <code>false</code> on negative rune values, as they do for other invalid runes.
</p>
</dd>
</dl><!-- unicode -->

View file

@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of Feb 19, 2021",
"Subtitle": "Version of Apr 28, 2021",
"Path": "/ref/spec"
}-->
@ -3532,9 +3532,9 @@ within <code>Greeting</code>, <code>who</code> will have the value
</p>
<p>
If the final argument is assignable to a slice type <code>[]T</code>, it is
passed unchanged as the value for a <code>...T</code> parameter if the argument
is followed by <code>...</code>. In this case no new slice is created.
If the final argument is assignable to a slice type <code>[]T</code> and
is followed by <code>...</code>, it is passed unchanged as the value
for a <code>...T</code> parameter. In this case no new slice is created.
</p>
<p>
@ -3681,8 +3681,8 @@ The bitwise logical and shift operators apply to integers only.
^ bitwise XOR integers
&amp;^ bit clear (AND NOT) integers
&lt;&lt; left shift integer &lt;&lt; unsigned integer
&gt;&gt; right shift integer &gt;&gt; unsigned integer
&lt;&lt; left shift integer &lt;&lt; integer &gt;= 0
&gt;&gt; right shift integer &gt;&gt; integer &gt;= 0
</pre>
@ -4164,6 +4164,10 @@ in any of these cases:
<li>
<code>x</code> is a string and <code>T</code> is a slice of bytes or runes.
</li>
<li>
<code>x</code> is a slice, <code>T</code> is a pointer to an array,
and the slice and array types have <a href="#Type_identity">identical</a> element types.
</li>
</ul>
<p>
@ -4314,6 +4318,24 @@ MyRunes("白鵬翔") // []rune{0x767d, 0x9d6c, 0x7fd4}
</li>
</ol>
<h4 id="Conversions_from_slice_to_array_pointer">Conversions from slice to array pointer</h4>
<p>
Converting a slice to an array pointer yields a pointer to the underlying array of the slice.
If the <a href="#Length_and_capacity">length</a> of the slice is less than the length of the array,
a <a href="#Run_time_panics">run-time panic</a> occurs.
</p>
<pre>
s := make([]byte, 2, 4)
s0 := (*[0]byte)(s) // s0 != nil
s2 := (*[2]byte)(s) // &amp;s2[0] == &amp;s[0]
s4 := (*[4]byte)(s) // panics: len([4]byte) > len(s)
var t []string
t0 := (*[0]string)(t) // t0 == nil
t1 := (*[1]string)(t) // panics: len([1]string) > len(s)
</pre>
<h3 id="Constant_expressions">Constant expressions</h3>
@ -4931,9 +4953,9 @@ ExprSwitchCase = "case" ExpressionList | "default" .
<p>
If the switch expression evaluates to an untyped constant, it is first implicitly
<a href="#Conversions">converted</a> to its <a href="#Constants">default type</a>;
if it is an untyped boolean value, it is first implicitly converted to type <code>bool</code>.
<a href="#Conversions">converted</a> to its <a href="#Constants">default type</a>.
The predeclared untyped value <code>nil</code> cannot be used as a switch expression.
The switch expression type must be <a href="#Comparison_operators">comparable</a>.
</p>
<p>
@ -6689,6 +6711,10 @@ type Pointer *ArbitraryType
func Alignof(variable ArbitraryType) uintptr
func Offsetof(selector ArbitraryType) uintptr
func Sizeof(variable ArbitraryType) uintptr
type IntegerType int // shorthand for an integer type; it is not a real type
func Add(ptr Pointer, len IntegerType) Pointer
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
</pre>
<p>
@ -6745,6 +6771,32 @@ Calls to <code>Alignof</code>, <code>Offsetof</code>, and
<code>Sizeof</code> are compile-time constant expressions of type <code>uintptr</code>.
</p>
<p>
The function <code>Add</code> adds <code>len</code> to <code>ptr</code>
and returns the updated pointer <code>unsafe.Pointer(uintptr(ptr) + uintptr(len))</code>.
The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
A constant <code>len</code> argument must be <a href="#Representability">representable</a> by a value of type <code>int</code>;
if it is an untyped constant it is given type <code>int</code>.
The rules for <a href="/pkg/unsafe#Pointer">valid uses</a> of <code>Pointer</code> still apply.
</p>
<p>
The function <code>Slice</code> returns a slice whose underlying array starts at <code>ptr</code>
and whose length and capacity are <code>len</code>:
</p>
<pre>
(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
</pre>
<p>
The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
A constant <code>len</code> argument must be non-negative and <a href="#Representability">representable</a> by a value of type <code>int</code>;
if it is an untyped constant it is given type <code>int</code>.
If <code>ptr</code> is <code>nil</code> or <code>len</code> is negative at run time,
a <a href="#Run_time_panics">run-time panic</a> occurs.
</p>
<h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
<p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -14,7 +14,6 @@ import (
"fmt"
"go/build"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
@ -276,7 +275,7 @@ func adbCopyGoroot() error {
if err := syscall.Flock(int(stat.Fd()), syscall.LOCK_EX); err != nil {
return err
}
s, err := ioutil.ReadAll(stat)
s, err := io.ReadAll(stat)
if err != nil {
return err
}
@ -294,7 +293,7 @@ func adbCopyGoroot() error {
goroot := runtime.GOROOT()
// Build go for android.
goCmd := filepath.Join(goroot, "bin", "go")
tmpGo, err := ioutil.TempFile("", "go_android_exec-cmd-go-*")
tmpGo, err := os.CreateTemp("", "go_android_exec-cmd-go-*")
if err != nil {
return err
}

View file

@ -0,0 +1,134 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 42580: cmd/cgo: shifting identifier position in ast
package errorstest
import (
"bytes"
"fmt"
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
type ShortPosition struct {
Line int
Column int
Visited bool
}
type IdentPositionInfo map[string][]ShortPosition
type Visitor struct {
identPosInfo IdentPositionInfo
fset *token.FileSet
t *testing.T
}
func (v *Visitor) Visit(node ast.Node) ast.Visitor {
if ident, ok := node.(*ast.Ident); ok {
if expectedPositions, ok := v.identPosInfo[ident.Name]; ok {
gotMatch := false
var errorMessage strings.Builder
for caseIndex, expectedPos := range expectedPositions {
actualPosition := v.fset.PositionFor(ident.Pos(), true)
errorOccured := false
if expectedPos.Line != actualPosition.Line {
fmt.Fprintf(&errorMessage, "wrong line number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Line, actualPosition.Line)
errorOccured = true
}
if expectedPos.Column != actualPosition.Column {
fmt.Fprintf(&errorMessage, "wrong column number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Column, actualPosition.Column)
errorOccured = true
}
if errorOccured {
continue
}
gotMatch = true
expectedPositions[caseIndex].Visited = true
}
if !gotMatch {
v.t.Errorf(errorMessage.String())
}
}
}
return v
}
func TestArgumentsPositions(t *testing.T) {
testdata, err := filepath.Abs("testdata")
if err != nil {
t.Fatal(err)
}
tmpPath := t.TempDir()
dir := filepath.Join(tmpPath, "src", "testpositions")
if err := os.MkdirAll(dir, 0755); err != nil {
t.Fatal(err)
}
cmd := exec.Command("go", "tool", "cgo",
"-srcdir", testdata,
"-objdir", dir,
"issue42580.go")
cmd.Stderr = new(bytes.Buffer)
err = cmd.Run()
if err != nil {
t.Fatalf("%s: %v\n%s", cmd, err, cmd.Stderr)
}
mainProcessed, err := ioutil.ReadFile(filepath.Join(dir, "issue42580.cgo1.go"))
if err != nil {
t.Fatal(err)
}
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "", mainProcessed, parser.AllErrors)
if err != nil {
fmt.Println(err)
return
}
expectation := IdentPositionInfo{
"checkedPointer": []ShortPosition{
ShortPosition{
Line: 32,
Column: 56,
},
},
"singleInnerPointerChecked": []ShortPosition{
ShortPosition{
Line: 37,
Column: 91,
},
},
"doublePointerChecked": []ShortPosition{
ShortPosition{
Line: 42,
Column: 91,
},
},
}
for _, decl := range f.Decls {
if fdecl, ok := decl.(*ast.FuncDecl); ok {
ast.Walk(&Visitor{expectation, fset, t}, fdecl.Body)
}
}
for ident, positions := range expectation {
for _, position := range positions {
if !position.Visited {
t.Errorf("Position %d:%d missed for %s ident", position.Line, position.Column, ident)
}
}
}
}

View file

@ -6,7 +6,6 @@ package errorstest
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@ -55,7 +54,7 @@ func TestBadSymbol(t *testing.T) {
makeFile := func(mdir, base, source string) string {
ret := filepath.Join(mdir, base)
if err := ioutil.WriteFile(ret, []byte(source), 0644); err != nil {
if err := os.WriteFile(ret, []byte(source), 0644); err != nil {
t.Fatal(err)
}
return ret
@ -100,7 +99,7 @@ func TestBadSymbol(t *testing.T) {
// _cgo_import.go.
rewrite := func(from, to string) {
obj, err := ioutil.ReadFile(from)
obj, err := os.ReadFile(from)
if err != nil {
t.Fatal(err)
}
@ -115,7 +114,7 @@ func TestBadSymbol(t *testing.T) {
obj = bytes.ReplaceAll(obj, []byte(magicInput), []byte(magicReplace))
if err := ioutil.WriteFile(to, obj, 0644); err != nil {
if err := os.WriteFile(to, obj, 0644); err != nil {
t.Fatal(err)
}
}

View file

@ -7,7 +7,6 @@ package errorstest
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@ -25,7 +24,7 @@ func check(t *testing.T, file string) {
t.Run(file, func(t *testing.T) {
t.Parallel()
contents, err := ioutil.ReadFile(path(file))
contents, err := os.ReadFile(path(file))
if err != nil {
t.Fatal(err)
}
@ -56,7 +55,7 @@ func check(t *testing.T, file string) {
}
func expect(t *testing.T, file string, errors []*regexp.Regexp) {
dir, err := ioutil.TempDir("", filepath.Base(t.Name()))
dir, err := os.MkdirTemp("", filepath.Base(t.Name()))
if err != nil {
t.Fatal(err)
}

View file

@ -10,7 +10,6 @@ import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@ -463,7 +462,7 @@ func buildPtrTests(t *testing.T) (dir, exe string) {
gopath = *tmp
dir = ""
} else {
d, err := ioutil.TempDir("", filepath.Base(t.Name()))
d, err := os.MkdirTemp("", filepath.Base(t.Name()))
if err != nil {
t.Fatal(err)
}
@ -475,7 +474,7 @@ func buildPtrTests(t *testing.T) (dir, exe string) {
if err := os.MkdirAll(src, 0777); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(src, "go.mod"), []byte("module ptrtest"), 0666); err != nil {
if err := os.WriteFile(filepath.Join(src, "go.mod"), []byte("module ptrtest"), 0666); err != nil {
t.Fatal(err)
}
@ -535,10 +534,10 @@ func buildPtrTests(t *testing.T) (dir, exe string) {
fmt.Fprintf(&cgo1, "}\n\n")
fmt.Fprintf(&cgo1, "%s\n", ptrTestMain)
if err := ioutil.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil {
if err := os.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil {
if err := os.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil {
t.Fatal(err)
}

44
misc/cgo/errors/testdata/issue42580.go vendored Normal file
View file

@ -0,0 +1,44 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 42580: cmd/cgo: shifting identifier position in ast
package cgotest
// typedef int (*intFunc) ();
//
// char* strarg = "";
//
// int func_with_char(char* arg, void* dummy)
// {return 5;}
//
// int* get_arr(char* arg, void* dummy)
// {return NULL;}
import "C"
import "unsafe"
// Test variables
var (
checkedPointer = []byte{1}
doublePointerChecked = []byte{1}
singleInnerPointerChecked = []byte{1}
)
// This test checks the positions of variable identifiers.
// Changing the positions of the test variables idents after this point will break the test.
func TestSingleArgumentCast() C.int {
retcode := C.func_with_char((*C.char)(unsafe.Pointer(&checkedPointer[0])), unsafe.Pointer(C.strarg))
return retcode
}
func TestSingleArgumentCastRecFuncAsSimpleArg() C.int {
retcode := C.func_with_char((*C.char)(unsafe.Pointer(C.get_arr((*C.char)(unsafe.Pointer(&singleInnerPointerChecked[0])), unsafe.Pointer(C.strarg)))), nil)
return retcode
}
func TestSingleArgumentCastRecFunc() C.int {
retcode := C.func_with_char((*C.char)(unsafe.Pointer(C.get_arr((*C.char)(unsafe.Pointer(&doublePointerChecked[0])), unsafe.Pointer(C.strarg)))), unsafe.Pointer(C.strarg))
return retcode
}

View file

@ -6,7 +6,6 @@ package life_test
import (
"bytes"
"io/ioutil"
"log"
"os"
"os/exec"
@ -21,7 +20,7 @@ func TestMain(m *testing.M) {
}
func testMain(m *testing.M) int {
GOPATH, err := ioutil.TempDir("", "cgolife")
GOPATH, err := os.MkdirTemp("", "cgolife")
if err != nil {
log.Panic(err)
}
@ -38,7 +37,7 @@ func testMain(m *testing.M) int {
log.Panic(err)
}
os.Setenv("PWD", modRoot)
if err := ioutil.WriteFile("go.mod", []byte("module cgolife\n"), 0666); err != nil {
if err := os.WriteFile("go.mod", []byte("module cgolife\n"), 0666); err != nil {
log.Panic(err)
}

View file

@ -6,7 +6,6 @@ package stdio_test
import (
"bytes"
"io/ioutil"
"log"
"os"
"os/exec"
@ -21,7 +20,7 @@ func TestMain(m *testing.M) {
}
func testMain(m *testing.M) int {
GOPATH, err := ioutil.TempDir("", "cgostdio")
GOPATH, err := os.MkdirTemp("", "cgostdio")
if err != nil {
log.Panic(err)
}
@ -38,7 +37,7 @@ func testMain(m *testing.M) int {
log.Panic(err)
}
os.Setenv("PWD", modRoot)
if err := ioutil.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil {
if err := os.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil {
log.Panic(err)
}

View file

@ -59,6 +59,7 @@ func Test28896(t *testing.T) { test28896(t) }
func Test30065(t *testing.T) { test30065(t) }
func Test32579(t *testing.T) { test32579(t) }
func Test31891(t *testing.T) { test31891(t) }
func Test45451(t *testing.T) { test45451(t) }
func TestAlign(t *testing.T) { testAlign(t) }
func TestAtol(t *testing.T) { testAtol(t) }
func TestBlocking(t *testing.T) { testBlocking(t) }
@ -80,6 +81,7 @@ func TestNamedEnum(t *testing.T) { testNamedEnum(t) }
func TestCastToEnum(t *testing.T) { testCastToEnum(t) }
func TestErrno(t *testing.T) { testErrno(t) }
func TestFpVar(t *testing.T) { testFpVar(t) }
func TestHandle(t *testing.T) { testHandle(t) }
func TestHelpers(t *testing.T) { testHelpers(t) }
func TestLibgcc(t *testing.T) { testLibgcc(t) }
func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }

View file

@ -8,7 +8,7 @@ package cgotest
import (
"fmt"
"io/ioutil"
"os"
"strings"
"syscall"
"testing"
@ -64,7 +64,7 @@ import "C"
func compareStatus(filter, expect string) error {
expected := filter + expect
pid := syscall.Getpid()
fs, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
fs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
if err != nil {
return fmt.Errorf("unable to find %d tasks: %v", pid, err)
}
@ -72,7 +72,7 @@ func compareStatus(filter, expect string) error {
foundAThread := false
for _, f := range fs {
tf := fmt.Sprintf("/proc/%s/status", f.Name())
d, err := ioutil.ReadFile(tf)
d, err := os.ReadFile(tf)
if err != nil {
// There are a surprising number of ways this
// can error out on linux. We've seen all of

View file

@ -5,7 +5,7 @@
// +build !android
// Test that pthread_cancel works as expected
// (NPTL uses SIGRTMIN to implement thread cancelation)
// (NPTL uses SIGRTMIN to implement thread cancellation)
// See https://golang.org/issue/6997
package cgotest
@ -17,8 +17,10 @@ extern int CancelThread();
*/
import "C"
import "testing"
import "time"
import (
"testing"
"time"
)
func test6997(t *testing.T) {
r := C.StartThread()

11
misc/cgo/test/issue8148.c Normal file
View file

@ -0,0 +1,11 @@
// Copyright 2014 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.
#include "_cgo_export.h"
int get8148(void) {
T t;
t.i = 42;
return issue8148Callback(&t);
}

View file

@ -10,14 +10,7 @@ package cgotest
/*
typedef struct { int i; } T;
int issue8148Callback(T*);
static int get() {
T t;
t.i = 42;
return issue8148Callback(&t);
}
int get8148(void);
*/
import "C"
@ -27,5 +20,5 @@ func issue8148Callback(t *C.T) C.int {
}
func Issue8148() int {
return int(C.get())
return int(C.get8148())
}

View file

@ -5,7 +5,6 @@
package cgotest
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@ -37,7 +36,7 @@ func TestCrossPackageTests(t *testing.T) {
}
}
GOPATH, err := ioutil.TempDir("", "cgotest")
GOPATH, err := os.MkdirTemp("", "cgotest")
if err != nil {
t.Fatal(err)
}
@ -47,7 +46,7 @@ func TestCrossPackageTests(t *testing.T) {
if err := overlayDir(modRoot, "testdata"); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgotest\n"), 0666); err != nil {
if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgotest\n"), 0666); err != nil {
t.Fatal(err)
}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test that setgid does not hang on GNU/Linux.
// Test that setgid does not hang on Linux.
// See https://golang.org/issue/3871 for details.
package cgotest

View file

@ -899,6 +899,10 @@ static uint16_t issue31093F(uint16_t v) { return v; }
// issue 32579
typedef struct S32579 { unsigned char data[1]; } S32579;
// issue 37033, cgo.Handle
extern void GoFunc37033(uintptr_t handle);
void cFunc37033(uintptr_t handle) { GoFunc37033(handle); }
// issue 38649
// Test that #define'd type aliases work.
#define netbsd_gid unsigned int
@ -908,6 +912,9 @@ typedef struct S32579 { unsigned char data[1]; } S32579;
enum Enum40494 { X_40494 };
union Union40494 { int x; };
void issue40494(enum Enum40494 e, union Union40494* up) {}
// Issue 45451, bad handling of go:notinheap types.
typedef struct issue45451Undefined issue45451;
*/
import "C"
@ -920,6 +927,7 @@ import (
"os/signal"
"reflect"
"runtime"
"runtime/cgo"
"sync"
"syscall"
"testing"
@ -2230,6 +2238,23 @@ func test32579(t *testing.T) {
}
}
// issue 37033, check if cgo.Handle works properly
func testHandle(t *testing.T) {
ch := make(chan int)
for i := 0; i < 42; i++ {
h := cgo.NewHandle(ch)
go func() {
C.cFunc37033(C.uintptr_t(h))
}()
if v := <-ch; issue37033 != v {
t.Fatalf("unexpected receiving value: got %d, want %d", v, issue37033)
}
h.Delete()
}
}
// issue 38649
var issue38649 C.netbsd_gid = 42
@ -2244,3 +2269,19 @@ var issue39877 *C.void = nil
func Issue40494() {
C.issue40494(C.enum_Enum40494(C.X_40494), (*C.union_Union40494)(nil))
}
// Issue 45451.
func test45451(t *testing.T) {
var u *C.issue45451
typ := reflect.ValueOf(u).Type().Elem()
// The type is undefined in C so allocating it should panic.
defer func() {
if r := recover(); r == nil {
t.Error("expected panic")
}
}()
_ = reflect.New(typ)
t.Errorf("reflect.New(%v) should have panicked", typ)
}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
// +build gc
#include "textflag.h"

View file

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build amd64 amd64p32
// +build !gccgo
// +build gc
#include "textflag.h"

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
// +build gc
#include "textflag.h"

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
// +build gc
#include "textflag.h"

View file

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build mips64 mips64le
// +build !gccgo
// +build gc
#include "textflag.h"

View file

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build mips mipsle
// +build !gccgo
// +build gc
#include "textflag.h"

View file

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build ppc64 ppc64le
// +build !gccgo
// +build gc
#include "textflag.h"

View file

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build riscv64
// +build !gccgo
// +build gc
#include "textflag.h"

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
// +build gc
#include "textflag.h"

24
misc/cgo/test/testx.c Normal file
View file

@ -0,0 +1,24 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "_cgo_export.h"
void lockOSThreadC(void) {
lockOSThreadCallback();
}
void issue7978c(uint32_t *sync) {
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0)
;
__atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2)
;
issue7978cb();
__atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6)
;
}
void f7665(void) {
}

View file

@ -12,6 +12,7 @@ package cgotest
import (
"runtime"
"runtime/cgo"
"runtime/debug"
"strings"
"sync"
@ -26,7 +27,6 @@ import (
extern void doAdd(int, int);
// issue 1328
extern void BackIntoGo(void);
void IntoC(void);
// issue 1560
@ -38,11 +38,7 @@ long long mysleep(int seconds);
long long twoSleep(int);
// issue 3775
void lockOSThreadCallback(void);
inline static void lockOSThreadC(void)
{
lockOSThreadCallback();
}
void lockOSThreadC(void);
int usleep(unsigned usec);
// issue 4054 part 2 - part 1 in test.go
@ -81,21 +77,9 @@ extern void f7665(void);
#include <stdint.h>
void issue7978cb(void);
// use ugly atomic variable sync since that doesn't require calling back into
// Go code or OS dependencies
static void issue7978c(uint32_t *sync) {
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0)
;
__atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2)
;
issue7978cb();
__atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6)
;
}
void issue7978c(uint32_t *sync);
// issue 8331 part 2 - part 1 in test.go
// A typedef of an unnamed struct is the same struct when
@ -428,9 +412,6 @@ func test6907Go(t *testing.T) {
// issue 7665
//export f7665
func f7665() {}
var bad7665 unsafe.Pointer = C.f7665
var good7665 uintptr = uintptr(C.f7665)
@ -558,6 +539,17 @@ func test31891(t *testing.T) {
C.callIssue31891()
}
// issue 37033, check if cgo.Handle works properly
var issue37033 = 42
//export GoFunc37033
func GoFunc37033(handle C.uintptr_t) {
h := cgo.Handle(handle)
ch := h.Value().(chan int)
ch <- issue37033
}
// issue 38408
// A typedef pointer can be used as the element type.
// No runtime test; just make sure it compiles.

View file

@ -10,7 +10,6 @@ import (
"debug/elf"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
@ -53,7 +52,7 @@ func testMain(m *testing.M) int {
// We need a writable GOPATH in which to run the tests.
// Construct one in a temporary directory.
var err error
GOPATH, err = ioutil.TempDir("", "carchive_test")
GOPATH, err = os.MkdirTemp("", "carchive_test")
if err != nil {
log.Panic(err)
}
@ -74,7 +73,7 @@ func testMain(m *testing.M) int {
log.Panic(err)
}
os.Setenv("PWD", modRoot)
if err := ioutil.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil {
if err := os.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil {
log.Panic(err)
}
@ -176,7 +175,7 @@ func genHeader(t *testing.T, header, dir string) {
// The 'cgo' command generates a number of additional artifacts,
// but we're only interested in the header.
// Shunt the rest of the outputs to a temporary directory.
objDir, err := ioutil.TempDir(GOPATH, "_obj")
objDir, err := os.MkdirTemp(GOPATH, "_obj")
if err != nil {
t.Fatal(err)
}
@ -252,7 +251,7 @@ var badLineRegexp = regexp.MustCompile(`(?m)^#line [0-9]+ "/.*$`)
// the user and make the files change based on details of the location
// of GOPATH.
func checkLineComments(t *testing.T, hdrname string) {
hdr, err := ioutil.ReadFile(hdrname)
hdr, err := os.ReadFile(hdrname)
if err != nil {
if !os.IsNotExist(err) {
t.Error(err)
@ -618,7 +617,7 @@ func TestExtar(t *testing.T) {
t.Fatal(err)
}
s := strings.Replace(testar, "PWD", dir, 1)
if err := ioutil.WriteFile("testar", []byte(s), 0777); err != nil {
if err := os.WriteFile("testar", []byte(s), 0777); err != nil {
t.Fatal(err)
}
@ -776,7 +775,7 @@ func TestSIGPROF(t *testing.T) {
// tool with -buildmode=c-archive, it passes -shared to the compiler,
// so we override that. The go tool doesn't work this way, but Bazel
// will likely do it in the future. And it ought to work. This test
// was added because at one time it did not work on PPC GNU/Linux.
// was added because at one time it did not work on PPC Linux.
func TestCompileWithoutShared(t *testing.T) {
// For simplicity, reuse the signal forwarding test.
checkSignalForwardingTest(t)

View file

@ -5,7 +5,7 @@
package main
import (
"io/ioutil"
"io"
"runtime/pprof"
)
@ -13,7 +13,7 @@ import "C"
//export go_start_profile
func go_start_profile() {
pprof.StartCPUProfile(ioutil.Discard)
pprof.StartCPUProfile(io.Discard)
}
//export go_stop_profile

View file

@ -36,7 +36,7 @@ int install_handler() {
return 2;
}
// gccgo does not set SA_ONSTACK for SIGSEGV.
if (getenv("GCCGO") == "" && (osa.sa_flags&SA_ONSTACK) == 0) {
if (getenv("GCCGO") == NULL && (osa.sa_flags&SA_ONSTACK) == 0) {
fprintf(stderr, "Go runtime did not install signal handler\n");
return 2;
}

View file

@ -11,7 +11,6 @@ import (
"encoding/binary"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
@ -125,7 +124,7 @@ func testMain(m *testing.M) int {
// Copy testdata into GOPATH/src/testcshared, along with a go.mod file
// declaring the same path.
GOPATH, err := ioutil.TempDir("", "cshared_test")
GOPATH, err := os.MkdirTemp("", "cshared_test")
if err != nil {
log.Panic(err)
}
@ -140,7 +139,7 @@ func testMain(m *testing.M) int {
log.Panic(err)
}
os.Setenv("PWD", modRoot)
if err := ioutil.WriteFile("go.mod", []byte("module testcshared\n"), 0666); err != nil {
if err := os.WriteFile("go.mod", []byte("module testcshared\n"), 0666); err != nil {
log.Panic(err)
}
@ -260,7 +259,7 @@ func createHeaders() error {
// The 'cgo' command generates a number of additional artifacts,
// but we're only interested in the header.
// Shunt the rest of the outputs to a temporary directory.
objDir, err := ioutil.TempDir("", "testcshared_obj")
objDir, err := os.MkdirTemp("", "testcshared_obj")
if err != nil {
return err
}
@ -381,7 +380,7 @@ func main() {
srcfile := filepath.Join(tmpdir, "test.go")
objfile := filepath.Join(tmpdir, "test.dll")
if err := ioutil.WriteFile(srcfile, []byte(prog), 0666); err != nil {
if err := os.WriteFile(srcfile, []byte(prog), 0666); err != nil {
t.Fatal(err)
}
argv := []string{"build", "-buildmode=c-shared"}
@ -643,7 +642,7 @@ func TestPIE(t *testing.T) {
// Test that installing a second time recreates the header file.
func TestCachedInstall(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "cshared")
tmpdir, err := os.MkdirTemp("", "cshared")
if err != nil {
t.Fatal(err)
}
@ -719,14 +718,14 @@ func TestCachedInstall(t *testing.T) {
// copyFile copies src to dst.
func copyFile(t *testing.T, dst, src string) {
t.Helper()
data, err := ioutil.ReadFile(src)
data, err := os.ReadFile(src)
if err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(dst, data, 0666); err != nil {
if err := os.WriteFile(dst, data, 0666); err != nil {
t.Fatal(err)
}
}
@ -743,7 +742,7 @@ func TestGo2C2Go(t *testing.T) {
t.Parallel()
tmpdir, err := ioutil.TempDir("", "cshared-TestGo2C2Go")
tmpdir, err := os.MkdirTemp("", "cshared-TestGo2C2Go")
if err != nil {
t.Fatal(err)
}

View file

@ -6,7 +6,6 @@ package testgodefs
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@ -34,7 +33,7 @@ func TestGoDefs(t *testing.T) {
t.Fatal(err)
}
gopath, err := ioutil.TempDir("", "testgodefs-gopath")
gopath, err := os.MkdirTemp("", "testgodefs-gopath")
if err != nil {
t.Fatal(err)
}
@ -58,20 +57,20 @@ func TestGoDefs(t *testing.T) {
t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
}
if err := ioutil.WriteFile(filepath.Join(dir, fp+"_defs.go"), out, 0644); err != nil {
if err := os.WriteFile(filepath.Join(dir, fp+"_defs.go"), out, 0644); err != nil {
t.Fatal(err)
}
}
main, err := ioutil.ReadFile(filepath.Join("testdata", "main.go"))
main, err := os.ReadFile(filepath.Join("testdata", "main.go"))
if err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil {
if err := os.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil {
if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil {
t.Fatal(err)
}

View file

@ -9,7 +9,6 @@ import (
"context"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
@ -31,15 +30,28 @@ func TestMain(m *testing.M) {
os.Exit(testMain(m))
}
// tmpDir is used to cleanup logged commands -- s/tmpDir/$TMPDIR/
var tmpDir string
// prettyPrintf prints lines with tmpDir sanitized.
func prettyPrintf(format string, args ...interface{}) {
s := fmt.Sprintf(format, args...)
if tmpDir != "" {
s = strings.ReplaceAll(s, tmpDir, "$TMPDIR")
}
fmt.Print(s)
}
func testMain(m *testing.M) int {
// Copy testdata into GOPATH/src/testplugin, along with a go.mod file
// declaring the same path.
GOPATH, err := ioutil.TempDir("", "plugin_test")
GOPATH, err := os.MkdirTemp("", "plugin_test")
if err != nil {
log.Panic(err)
}
defer os.RemoveAll(GOPATH)
tmpDir = GOPATH
modRoot := filepath.Join(GOPATH, "src", "testplugin")
altRoot := filepath.Join(GOPATH, "alt", "src", "testplugin")
@ -50,14 +62,20 @@ func testMain(m *testing.M) int {
if err := overlayDir(dstRoot, srcRoot); err != nil {
log.Panic(err)
}
if err := ioutil.WriteFile(filepath.Join(dstRoot, "go.mod"), []byte("module testplugin\n"), 0666); err != nil {
prettyPrintf("mkdir -p %s\n", dstRoot)
prettyPrintf("rsync -a %s/ %s\n", srcRoot, dstRoot)
if err := os.WriteFile(filepath.Join(dstRoot, "go.mod"), []byte("module testplugin\n"), 0666); err != nil {
log.Panic(err)
}
prettyPrintf("echo 'module testplugin' > %s/go.mod\n", dstRoot)
}
os.Setenv("GOPATH", filepath.Join(GOPATH, "alt"))
if err := os.Chdir(altRoot); err != nil {
log.Panic(err)
} else {
prettyPrintf("cd %s\n", altRoot)
}
os.Setenv("PWD", altRoot)
goCmd(nil, "build", "-buildmode=plugin", "-o", filepath.Join(modRoot, "plugin-mismatch.so"), "./plugin-mismatch")
@ -65,6 +83,8 @@ func testMain(m *testing.M) int {
os.Setenv("GOPATH", GOPATH)
if err := os.Chdir(modRoot); err != nil {
log.Panic(err)
} else {
prettyPrintf("cd %s\n", modRoot)
}
os.Setenv("PWD", modRoot)
@ -72,13 +92,14 @@ func testMain(m *testing.M) int {
goCmd(nil, "build", "-buildmode=plugin", "./plugin1")
goCmd(nil, "build", "-buildmode=plugin", "./plugin2")
so, err := ioutil.ReadFile("plugin2.so")
so, err := os.ReadFile("plugin2.so")
if err != nil {
log.Panic(err)
}
if err := ioutil.WriteFile("plugin2-dup.so", so, 0444); err != nil {
if err := os.WriteFile("plugin2-dup.so", so, 0444); err != nil {
log.Panic(err)
}
prettyPrintf("cp plugin2.so plugin2-dup.so\n")
goCmd(nil, "build", "-buildmode=plugin", "-o=sub/plugin1.so", "./sub/plugin1")
goCmd(nil, "build", "-buildmode=plugin", "-o=unnamed1.so", "./unnamed1/main.go")
@ -95,8 +116,53 @@ func goCmd(t *testing.T, op string, args ...string) {
run(t, "go", append([]string{op, "-gcflags", gcflags}, args...)...)
}
// escape converts a string to something suitable for a shell command line.
func escape(s string) string {
s = strings.Replace(s, "\\", "\\\\", -1)
s = strings.Replace(s, "'", "\\'", -1)
// Conservative guess at characters that will force quoting
if s == "" || strings.ContainsAny(s, "\\ ;#*&$~?!|[]()<>{}`") {
s = "'" + s + "'"
}
return s
}
// asCommandLine renders cmd as something that could be copy-and-pasted into a command line
func asCommandLine(cwd string, cmd *exec.Cmd) string {
s := "("
if cmd.Dir != "" && cmd.Dir != cwd {
s += "cd" + escape(cmd.Dir) + ";"
}
for _, e := range cmd.Env {
if !strings.HasPrefix(e, "PATH=") &&
!strings.HasPrefix(e, "HOME=") &&
!strings.HasPrefix(e, "USER=") &&
!strings.HasPrefix(e, "SHELL=") {
s += " "
s += escape(e)
}
}
// These EVs are relevant to this test.
for _, e := range os.Environ() {
if strings.HasPrefix(e, "PWD=") ||
strings.HasPrefix(e, "GOPATH=") ||
strings.HasPrefix(e, "LD_LIBRARY_PATH=") {
s += " "
s += escape(e)
}
}
for _, a := range cmd.Args {
s += " "
s += escape(a)
}
s += " )"
return s
}
func run(t *testing.T, bin string, args ...string) string {
cmd := exec.Command(bin, args...)
cmdLine := asCommandLine(".", cmd)
prettyPrintf("%s\n", cmdLine)
cmd.Stderr = new(strings.Builder)
out, err := cmd.Output()
if err != nil {
@ -201,12 +267,18 @@ func TestMethod(t *testing.T) {
// Exported symbol's method must be live.
goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go")
goCmd(t, "build", "-o", "method.exe", "./method/main.go")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "./method.exe")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out)
}
run(t, "./method.exe")
}
func TestMethod2(t *testing.T) {
goCmd(t, "build", "-buildmode=plugin", "-o", "method2.so", "./method2/plugin.go")
goCmd(t, "build", "-o", "method2.exe", "./method2/main.go")
run(t, "./method2.exe")
}
func TestIssue44956(t *testing.T) {
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p1.so", "./issue44956/plugin1.go")
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p2.so", "./issue44956/plugin2.go")
goCmd(t, "build", "-o", "issue44956.exe", "./issue44956/main.go")
run(t, "./issue44956.exe")
}

View file

@ -0,0 +1,7 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package base
var X = &map[int]int{123: 456}

View file

@ -0,0 +1,47 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 44956: writable static temp is not exported correctly.
// In the test below, package base is
//
// X = &map{...}
//
// which compiles to
//
// X = &stmp // static
// stmp = makemap(...) // in init function
//
// plugin1 and plugin2 both import base. plugin1 doesn't use
// base.X, so that symbol is deadcoded in plugin1.
//
// plugin1 is loaded first. base.init runs at that point, which
// initialize base.stmp.
//
// plugin2 is then loaded. base.init already ran, so it doesn't run
// again. When base.stmp is not exported, plugin2's base.X points to
// its own private base.stmp, which is not initialized, fail.
package main
import "plugin"
func main() {
_, err := plugin.Open("issue44956p1.so")
if err != nil {
panic("FAIL")
}
p2, err := plugin.Open("issue44956p2.so")
if err != nil {
panic("FAIL")
}
f, err := p2.Lookup("F")
if err != nil {
panic("FAIL")
}
x := f.(func() *map[int]int)()
if x == nil || (*x)[123] != 456 {
panic("FAIL")
}
}

View file

@ -0,0 +1,9 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import _ "testplugin/issue44956/base"
func main() {}

View file

@ -1,10 +1,11 @@
// runindir -gcflags=-c=1
// +build !windows
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// TODO May delete or adapt this test once regabi is the default
package main
package ignore
import "testplugin/issue44956/base"
func F() *map[int]int { return base.X }
func main() {}

View file

@ -0,0 +1,32 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// A type can be passed to a plugin and converted to interface
// there. So its methods need to be live.
package main
import (
"plugin"
"testplugin/method2/p"
)
var t p.T
type I interface{ M() }
func main() {
pl, err := plugin.Open("method2.so")
if err != nil {
panic(err)
}
f, err := pl.Lookup("F")
if err != nil {
panic(err)
}
f.(func(p.T) interface{})(t).(I).M()
}

View file

@ -0,0 +1,9 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type T int
func (T) M() { println("M") }

View file

@ -0,0 +1,11 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "testplugin/method2/p"
func main() {}
func F(t p.T) interface{} { return t }

View file

@ -11,7 +11,6 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@ -36,7 +35,7 @@ func requireOvercommit(t *testing.T) {
overcommit.Once.Do(func() {
var out []byte
out, overcommit.err = ioutil.ReadFile("/proc/sys/vm/overcommit_memory")
out, overcommit.err = os.ReadFile("/proc/sys/vm/overcommit_memory")
if overcommit.err != nil {
return
}
@ -313,14 +312,14 @@ int main() {
`)
func (c *config) checkCSanitizer() (skip bool, err error) {
dir, err := ioutil.TempDir("", c.sanitizer)
dir, err := os.MkdirTemp("", c.sanitizer)
if err != nil {
return false, fmt.Errorf("failed to create temp directory: %v", err)
}
defer os.RemoveAll(dir)
src := filepath.Join(dir, "return0.c")
if err := ioutil.WriteFile(src, cMain, 0600); err != nil {
if err := os.WriteFile(src, cMain, 0600); err != nil {
return false, fmt.Errorf("failed to write C source file: %v", err)
}
@ -418,7 +417,7 @@ func (d *tempDir) Join(name string) string {
func newTempDir(t *testing.T) *tempDir {
t.Helper()
dir, err := ioutil.TempDir("", filepath.Dir(t.Name()))
dir, err := os.MkdirTemp("", filepath.Dir(t.Name()))
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
@ -440,3 +439,14 @@ func hangProneCmd(name string, arg ...string) *exec.Cmd {
}
return cmd
}
// mSanSupported is a copy of the function cmd/internal/sys.MSanSupported,
// because the internal pacakage can't be used here.
func mSanSupported(goos, goarch string) bool {
switch goos {
case "linux":
return goarch == "amd64" || goarch == "arm64"
default:
return false
}
}

View file

@ -6,7 +6,7 @@ package sanitizers_test
import (
"fmt"
"io/ioutil"
"os"
"strings"
"testing"
)
@ -19,6 +19,12 @@ func TestShared(t *testing.T) {
if err != nil {
t.Fatal(err)
}
GOARCH, err := goEnv("GOARCH")
if err != nil {
t.Fatal(err)
}
libExt := "so"
if GOOS == "darwin" {
libExt = "dylib"
@ -41,6 +47,11 @@ func TestShared(t *testing.T) {
for _, tc := range cases {
tc := tc
name := strings.TrimSuffix(tc.src, ".go")
//The memory sanitizer tests require support for the -msan option.
if tc.sanitizer == "memory" && !mSanSupported(GOOS, GOARCH) {
t.Logf("skipping %s test on %s/%s; -msan option is not supported.", name, GOOS, GOARCH)
continue
}
t.Run(name, func(t *testing.T) {
t.Parallel()
config := configure(tc.sanitizer)
@ -53,7 +64,7 @@ func TestShared(t *testing.T) {
mustRun(t, config.goCmd("build", "-buildmode=c-shared", "-o", lib, srcPath(tc.src)))
cSrc := dir.Join("main.c")
if err := ioutil.WriteFile(cSrc, cMain, 0600); err != nil {
if err := os.WriteFile(cSrc, cMain, 0600); err != nil {
t.Fatalf("failed to write C source file: %v", err)
}

View file

@ -10,6 +10,19 @@ import (
)
func TestMSAN(t *testing.T) {
goos, err := goEnv("GOOS")
if err != nil {
t.Fatal(err)
}
goarch, err := goEnv("GOARCH")
if err != nil {
t.Fatal(err)
}
// The msan tests require support for the -msan option.
if !mSanSupported(goos, goarch) {
t.Skipf("skipping on %s/%s; -msan option is not supported.", goos, goarch)
}
t.Parallel()
requireOvercommit(t)
config := configure("memory")

View file

@ -44,7 +44,7 @@ void spin() {
import "C"
import (
"io/ioutil"
"io"
"runtime/pprof"
"time"
)
@ -60,7 +60,7 @@ func goSpin() {
}
func main() {
pprof.StartCPUProfile(ioutil.Discard)
pprof.StartCPUProfile(io.Discard)
go C.spin()
goSpin()
pprof.StopCPUProfile()

View file

@ -13,7 +13,6 @@ import (
"fmt"
"go/build"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
@ -90,7 +89,7 @@ func goCmd(t *testing.T, args ...string) string {
// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
func testMain(m *testing.M) (int, error) {
workDir, err := ioutil.TempDir("", "shared_test")
workDir, err := os.MkdirTemp("", "shared_test")
if err != nil {
return 0, err
}
@ -177,7 +176,7 @@ func cloneTestdataModule(gopath string) (string, error) {
if err := overlayDir(modRoot, "testdata"); err != nil {
return "", err
}
if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil {
if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil {
return "", err
}
return modRoot, nil
@ -318,7 +317,7 @@ func TestShlibnameFiles(t *testing.T) {
}
for _, pkg := range pkgs {
shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname")
contentsb, err := ioutil.ReadFile(shlibnamefile)
contentsb, err := os.ReadFile(shlibnamefile)
if err != nil {
t.Errorf("error reading shlibnamefile for %s: %v", pkg, err)
continue
@ -791,7 +790,7 @@ func resetFileStamps() {
// It also sets the time of the file, so that we can see if it is rewritten.
func touch(t *testing.T, path string) (cleanup func()) {
t.Helper()
data, err := ioutil.ReadFile(path)
data, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
@ -837,14 +836,14 @@ func touch(t *testing.T, path string) (cleanup func()) {
// user-writable.
perm := fi.Mode().Perm() | 0200
if err := ioutil.WriteFile(path, data, perm); err != nil {
if err := os.WriteFile(path, data, perm); err != nil {
t.Fatal(err)
}
if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil {
t.Fatal(err)
}
return func() {
if err := ioutil.WriteFile(path, old, perm); err != nil {
if err := os.WriteFile(path, old, perm); err != nil {
t.Fatal(err)
}
}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
// +build gc
#include "textflag.h"

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
// +build gc
package depBase

View file

@ -7,7 +7,6 @@
package so_test
import (
"io/ioutil"
"log"
"os"
"os/exec"
@ -37,7 +36,7 @@ func requireTestSOSupported(t *testing.T) {
func TestSO(t *testing.T) {
requireTestSOSupported(t)
GOPATH, err := ioutil.TempDir("", "cgosotest")
GOPATH, err := os.MkdirTemp("", "cgosotest")
if err != nil {
log.Fatal(err)
}
@ -47,7 +46,7 @@ func TestSO(t *testing.T) {
if err := overlayDir(modRoot, "testdata"); err != nil {
log.Panic(err)
}
if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
log.Panic(err)
}
@ -80,6 +79,10 @@ func TestSO(t *testing.T) {
case "windows":
ext = "dll"
args = append(args, "-DEXPORT_DLL")
// At least in mingw-clang it is not permitted to just name a .dll
// on the command line. You must name the corresponding import
// library instead, even though the dll is used when the executable is run.
args = append(args, "-Wl,-out-implib,libcgosotest.a")
case "aix":
ext = "so.1"
}

View file

@ -14,7 +14,7 @@ package cgosotest
#cgo solaris LDFLAGS: -L. -lcgosotest
#cgo netbsd LDFLAGS: -L. libcgosotest.so
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
#cgo windows LDFLAGS: -L. libcgosotest.dll
#cgo windows LDFLAGS: -L. libcgosotest.a
#cgo aix LDFLAGS: -L. -l cgosotest
void init(void);

View file

@ -7,7 +7,6 @@
package so_test
import (
"io/ioutil"
"log"
"os"
"os/exec"
@ -37,7 +36,7 @@ func requireTestSOSupported(t *testing.T) {
func TestSO(t *testing.T) {
requireTestSOSupported(t)
GOPATH, err := ioutil.TempDir("", "cgosotest")
GOPATH, err := os.MkdirTemp("", "cgosotest")
if err != nil {
log.Fatal(err)
}
@ -47,7 +46,7 @@ func TestSO(t *testing.T) {
if err := overlayDir(modRoot, "testdata"); err != nil {
log.Panic(err)
}
if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
log.Panic(err)
}
@ -80,6 +79,10 @@ func TestSO(t *testing.T) {
case "windows":
ext = "dll"
args = append(args, "-DEXPORT_DLL")
// At least in mingw-clang it is not permitted to just name a .dll
// on the command line. You must name the corresponding import
// library instead, even though the dll is used when the executable is run.
args = append(args, "-Wl,-out-implib,libcgosotest.a")
case "aix":
ext = "so.1"
}

View file

@ -18,7 +18,7 @@ package cgosotest
#cgo solaris LDFLAGS: -L. -lcgosotest
#cgo netbsd LDFLAGS: -L. libcgosotest.so
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
#cgo windows LDFLAGS: -L. libcgosotest.dll
#cgo windows LDFLAGS: -L. libcgosotest.a
#cgo aix LDFLAGS: -L. -l cgosotest
#include "cgoso_c.h"

View file

@ -15,7 +15,7 @@
<a href="#" url="https://golang.org/pkg/">pkg</a> id/name:</small>
<form style='margin: 0' id='navform'><nobr><input id="inputbox" size=10 tabindex=1 /><input type="submit" value="go" /></nobr></form>
<small>Also: <a href="#" url="https://build.golang.org">buildbots</a>
<a href="#" url="https://github.com/golang/go">Github</a>
<a href="#" url="https://github.com/golang/go">GitHub</a>
</small>
</body>
</html>

View file

@ -16,7 +16,6 @@ import (
"bytes"
"crypto/x509"
"fmt"
"io/ioutil"
"os"
"os/exec"
"strings"
@ -38,7 +37,7 @@ func main() {
fmt.Println("# will be overwritten when running Go programs.")
for _, mp := range mps {
fmt.Println()
f, err := ioutil.TempFile("", "go_ios_detect_")
f, err := os.CreateTemp("", "go_ios_detect_")
check(err)
fname := f.Name()
defer os.Remove(fname)

View file

@ -26,7 +26,6 @@ import (
"fmt"
"go/build"
"io"
"io/ioutil"
"log"
"net"
"os"
@ -79,7 +78,7 @@ func main() {
func runMain() (int, error) {
var err error
tmpdir, err = ioutil.TempDir("", "go_ios_exec_")
tmpdir, err = os.MkdirTemp("", "go_ios_exec_")
if err != nil {
return 1, err
}
@ -205,13 +204,13 @@ func assembleApp(appdir, bin string) error {
}
entitlementsPath := filepath.Join(tmpdir, "Entitlements.plist")
if err := ioutil.WriteFile(entitlementsPath, []byte(entitlementsPlist()), 0744); err != nil {
if err := os.WriteFile(entitlementsPath, []byte(entitlementsPlist()), 0744); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(appdir, "Info.plist"), []byte(infoPlist(pkgpath)), 0744); err != nil {
if err := os.WriteFile(filepath.Join(appdir, "Info.plist"), []byte(infoPlist(pkgpath)), 0744); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(appdir, "ResourceRules.plist"), []byte(resourceRules), 0744); err != nil {
if err := os.WriteFile(filepath.Join(appdir, "ResourceRules.plist"), []byte(resourceRules), 0744); err != nil {
return err
}
return nil

View file

@ -11,7 +11,7 @@ import (
"errors"
"flag"
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"os"
@ -144,7 +144,7 @@ func doCrawl(url string) error {
if res.StatusCode != 200 {
return errors.New(res.Status)
}
slurp, err := ioutil.ReadAll(res.Body)
slurp, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatalf("Error reading %s body: %v", url, err)

View file

@ -13,7 +13,6 @@ package reboot_test
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@ -23,7 +22,7 @@ import (
func TestExperimentToolID(t *testing.T) {
// Set up GOROOT
goroot, err := ioutil.TempDir("", "experiment-goroot")
goroot, err := os.MkdirTemp("", "experiment-goroot")
if err != nil {
t.Fatal(err)
}
@ -34,13 +33,13 @@ func TestExperimentToolID(t *testing.T) {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(goroot, "VERSION"), []byte("go1.999"), 0666); err != nil {
if err := os.WriteFile(filepath.Join(goroot, "VERSION"), []byte("go1.999"), 0666); err != nil {
t.Fatal(err)
}
env := append(os.Environ(), "GOROOT=", "GOROOT_BOOTSTRAP="+runtime.GOROOT())
// Use a clean cache.
gocache, err := ioutil.TempDir("", "experiment-gocache")
gocache, err := os.MkdirTemp("", "experiment-gocache")
if err != nil {
t.Fatal(err)
}

View file

@ -7,7 +7,6 @@
package reboot_test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@ -16,7 +15,7 @@ import (
)
func TestRepeatBootstrap(t *testing.T) {
goroot, err := ioutil.TempDir("", "reboot-goroot")
goroot, err := os.MkdirTemp("", "reboot-goroot")
if err != nil {
t.Fatal(err)
}
@ -27,7 +26,7 @@ func TestRepeatBootstrap(t *testing.T) {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(goroot, "VERSION"), []byte(runtime.Version()), 0666); err != nil {
if err := os.WriteFile(filepath.Join(goroot, "VERSION"), []byte(runtime.Version()), 0666); err != nil {
t.Fatal(err)
}

View file

@ -993,13 +993,13 @@
</style>
<div style="padding-right: 200px">
<div style="float:right; border-style: solid; border-width: 1px; padding:20px">
X no feedback<br/>
0 uninitialized<br/>
. premonomorphic<br/>
1 monomorphic<br/>
^ recompute handler<br/>
P polymorphic<br/>
N megamorphic<br/>
X no feedback<br>
0 uninitialized<br>
. premonomorphic<br>
1 monomorphic<br>
^ recompute handler<br>
P polymorphic<br>
N megamorphic<br>
G generic
</div>
</div>
@ -3596,7 +3596,7 @@
<div id="pipeline_per_frame_container">
<div class="subtitle">Graphics Pipeline and Raster Tasks</div>
<div class="description">
When raster tasks are completed in comparison to the rest of the graphics pipeline.<br/>
When raster tasks are completed in comparison to the rest of the graphics pipeline.<br>
Only pages where raster tasks are completed after beginFrame is issued are included.
</div>
<tr-v-ui-raster-visualization id="rasterVisualization">

View file

@ -296,8 +296,8 @@
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
},
// func walltime1() (sec int64, nsec int32)
"runtime.walltime1": (sp) => {
// func walltime() (sec int64, nsec int32)
"runtime.walltime": (sp) => {
sp >>>= 0;
const msec = (new Date).getTime();
setInt64(sp + 8, msec / 1000);

View file

@ -1,2 +0,0 @@
User-agent: *
Disallow: /

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || linux || dragonfly || openbsd || solaris
// +build aix linux dragonfly openbsd solaris
package tar

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build darwin || freebsd || netbsd
// +build darwin freebsd netbsd
package tar

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || linux || darwin || dragonfly || freebsd || openbsd || netbsd || solaris
// +build aix linux darwin dragonfly freebsd openbsd netbsd solaris
package tar

View file

@ -262,16 +262,11 @@ func TestFileInfoHeaderDir(t *testing.T) {
func TestFileInfoHeaderSymlink(t *testing.T) {
testenv.MustHaveSymlink(t)
tmpdir, err := os.MkdirTemp("", "TestFileInfoHeaderSymlink")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
tmpdir := t.TempDir()
link := filepath.Join(tmpdir, "link")
target := tmpdir
err = os.Symlink(target, link)
if err != nil {
if err := os.Symlink(target, link); err != nil {
t.Fatal(err)
}
fi, err := os.Lstat(link)

View file

@ -52,12 +52,9 @@ type File struct {
FileHeader
zip *Reader
zipr io.ReaderAt
zipsize int64
headerOffset int64
}
func (f *File) hasDataDescriptor() bool {
return f.Flags&0x8 != 0
zip64 bool // zip64 extended information extra field presence
descErr error // error reading the data descriptor during init
}
// OpenReader will open the Zip file specified by name and return a ReadCloser.
@ -112,7 +109,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
// a bad one, and then only report an ErrFormat or UnexpectedEOF if
// the file count modulo 65536 is incorrect.
for {
f := &File{zip: z, zipr: r, zipsize: size}
f := &File{zip: z, zipr: r}
err = readDirectoryHeader(f, buf)
if err == ErrFormat || err == io.ErrUnexpectedEOF {
break
@ -120,6 +117,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
if err != nil {
return err
}
f.readDataDescriptor()
z.File = append(z.File, f)
}
if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here
@ -180,26 +178,68 @@ func (f *File) Open() (io.ReadCloser, error) {
return nil, ErrAlgorithm
}
var rc io.ReadCloser = dcomp(r)
var desr io.Reader
if f.hasDataDescriptor() {
desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
}
rc = &checksumReader{
rc: rc,
hash: crc32.NewIEEE(),
f: f,
desr: desr,
}
return rc, nil
}
// OpenRaw returns a Reader that provides access to the File's contents without
// decompression.
func (f *File) OpenRaw() (io.Reader, error) {
bodyOffset, err := f.findBodyOffset()
if err != nil {
return nil, err
}
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, int64(f.CompressedSize64))
return r, nil
}
func (f *File) readDataDescriptor() {
if !f.hasDataDescriptor() {
return
}
bodyOffset, err := f.findBodyOffset()
if err != nil {
f.descErr = err
return
}
// In section 4.3.9.2 of the spec: "However ZIP64 format MAY be used
// regardless of the size of a file. When extracting, if the zip64
// extended information extra field is present for the file the
// compressed and uncompressed sizes will be 8 byte values."
//
// Historically, this package has used the compressed and uncompressed
// sizes from the central directory to determine if the package is
// zip64.
//
// For this case we allow either the extra field or sizes to determine
// the data descriptor length.
zip64 := f.zip64 || f.isZip64()
n := int64(dataDescriptorLen)
if zip64 {
n = dataDescriptor64Len
}
size := int64(f.CompressedSize64)
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, n)
dd, err := readDataDescriptor(r, zip64)
if err != nil {
f.descErr = err
return
}
f.CRC32 = dd.crc32
}
type checksumReader struct {
rc io.ReadCloser
hash hash.Hash32
nread uint64 // number of bytes read so far
f *File
desr io.Reader // if non-nil, where to read the data descriptor
err error // sticky error
err error // sticky error
}
func (r *checksumReader) Stat() (fs.FileInfo, error) {
@ -220,12 +260,12 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
if r.nread != r.f.UncompressedSize64 {
return 0, io.ErrUnexpectedEOF
}
if r.desr != nil {
if err1 := readDataDescriptor(r.desr, r.f); err1 != nil {
if err1 == io.EOF {
if r.f.hasDataDescriptor() {
if r.f.descErr != nil {
if r.f.descErr == io.EOF {
err = io.ErrUnexpectedEOF
} else {
err = err1
err = r.f.descErr
}
} else if r.hash.Sum32() != r.f.CRC32 {
err = ErrChecksum
@ -336,6 +376,8 @@ parseExtras:
switch fieldTag {
case zip64ExtraID:
f.zip64 = true
// update directory values from the zip64 extra block.
// They should only be consulted if the sizes read earlier
// are maxed out.
@ -435,8 +477,9 @@ parseExtras:
return nil
}
func readDataDescriptor(r io.Reader, f *File) error {
var buf [dataDescriptorLen]byte
func readDataDescriptor(r io.Reader, zip64 bool) (*dataDescriptor, error) {
// Create enough space for the largest possible size
var buf [dataDescriptor64Len]byte
// The spec says: "Although not originally assigned a
// signature, the value 0x08074b50 has commonly been adopted
@ -446,10 +489,9 @@ func readDataDescriptor(r io.Reader, f *File) error {
// descriptors and should account for either case when reading
// ZIP files to ensure compatibility."
//
// dataDescriptorLen includes the size of the signature but
// first read just those 4 bytes to see if it exists.
// First read just those 4 bytes to see if the signature exists.
if _, err := io.ReadFull(r, buf[:4]); err != nil {
return err
return nil, err
}
off := 0
maybeSig := readBuf(buf[:4])
@ -458,21 +500,28 @@ func readDataDescriptor(r io.Reader, f *File) error {
// bytes.
off += 4
}
if _, err := io.ReadFull(r, buf[off:12]); err != nil {
return err
end := dataDescriptorLen - 4
if zip64 {
end = dataDescriptor64Len - 4
}
b := readBuf(buf[:12])
if b.uint32() != f.CRC32 {
return ErrChecksum
if _, err := io.ReadFull(r, buf[off:end]); err != nil {
return nil, err
}
b := readBuf(buf[:end])
out := &dataDescriptor{
crc32: b.uint32(),
}
// The two sizes that follow here can be either 32 bits or 64 bits
// but the spec is not very clear on this and different
// interpretations has been made causing incompatibilities. We
// already have the sizes from the central directory so we can
// just ignore these.
return nil
if zip64 {
out.compressedSize = b.uint64()
out.uncompressedSize = b.uint64()
} else {
out.compressedSize = uint64(b.uint32())
out.uncompressedSize = uint64(b.uint32())
}
return out, nil
}
func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) {
@ -628,10 +677,11 @@ func (b *readBuf) sub(n int) readBuf {
}
// A fileListEntry is a File and its ename.
// If file == nil, the fileListEntry describes a directory, without metadata.
// If file == nil, the fileListEntry describes a directory without metadata.
type fileListEntry struct {
name string
file *File // nil for directories
name string
file *File
isDir bool
}
type fileInfoDirEntry interface {
@ -640,20 +690,26 @@ type fileInfoDirEntry interface {
}
func (e *fileListEntry) stat() fileInfoDirEntry {
if e.file != nil {
if !e.isDir {
return headerFileInfo{&e.file.FileHeader}
}
return e
}
// Only used for directories.
func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem }
func (f *fileListEntry) Size() int64 { return 0 }
func (f *fileListEntry) ModTime() time.Time { return time.Time{} }
func (f *fileListEntry) Mode() fs.FileMode { return fs.ModeDir | 0555 }
func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir }
func (f *fileListEntry) IsDir() bool { return true }
func (f *fileListEntry) Sys() interface{} { return nil }
func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem }
func (f *fileListEntry) Size() int64 { return 0 }
func (f *fileListEntry) Mode() fs.FileMode { return fs.ModeDir | 0555 }
func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir }
func (f *fileListEntry) IsDir() bool { return true }
func (f *fileListEntry) Sys() interface{} { return nil }
func (f *fileListEntry) ModTime() time.Time {
if f.file == nil {
return time.Time{}
}
return f.file.FileHeader.Modified.UTC()
}
func (f *fileListEntry) Info() (fs.FileInfo, error) { return f, nil }
@ -664,7 +720,7 @@ func toValidName(name string) string {
if strings.HasPrefix(p, "/") {
p = p[len("/"):]
}
for strings.HasPrefix(name, "../") {
for strings.HasPrefix(p, "../") {
p = p[len("../"):]
}
return p
@ -673,15 +729,32 @@ func toValidName(name string) string {
func (r *Reader) initFileList() {
r.fileListOnce.Do(func() {
dirs := make(map[string]bool)
knownDirs := make(map[string]bool)
for _, file := range r.File {
isDir := len(file.Name) > 0 && file.Name[len(file.Name)-1] == '/'
name := toValidName(file.Name)
for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
dirs[dir] = true
}
r.fileList = append(r.fileList, fileListEntry{name, file})
entry := fileListEntry{
name: name,
file: file,
isDir: isDir,
}
r.fileList = append(r.fileList, entry)
if isDir {
knownDirs[name] = true
}
}
for dir := range dirs {
r.fileList = append(r.fileList, fileListEntry{dir + "/", nil})
if !knownDirs[dir] {
entry := fileListEntry{
name: dir,
file: nil,
isDir: true,
}
r.fileList = append(r.fileList, entry)
}
}
sort.Slice(r.fileList, func(i, j int) bool { return fileEntryLess(r.fileList[i].name, r.fileList[j].name) })
@ -705,7 +778,7 @@ func (r *Reader) Open(name string) (fs.File, error) {
if e == nil || !fs.ValidPath(name) {
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
}
if e.file == nil || strings.HasSuffix(e.file.Name, "/") {
if e.isDir {
return &openDir{e, r.openReadDir(name), 0}, nil
}
rc, err := e.file.Open()
@ -730,7 +803,7 @@ func split(name string) (dir, elem string, isDir bool) {
return name[:i], name[i+1:], isDir
}
var dotFile = &fileListEntry{name: "./"}
var dotFile = &fileListEntry{name: "./", isDir: true}
func (r *Reader) openLookup(name string) *fileListEntry {
if name == "." {

View file

@ -499,9 +499,15 @@ func TestReader(t *testing.T) {
func readTestZip(t *testing.T, zt ZipTest) {
var z *Reader
var err error
var raw []byte
if zt.Source != nil {
rat, size := zt.Source()
z, err = NewReader(rat, size)
raw = make([]byte, size)
if _, err := rat.ReadAt(raw, 0); err != nil {
t.Errorf("ReadAt error=%v", err)
return
}
} else {
path := filepath.Join("testdata", zt.Name)
if zt.Obscured {
@ -519,6 +525,12 @@ func readTestZip(t *testing.T, zt ZipTest) {
defer rc.Close()
z = &rc.Reader
}
var err2 error
raw, err2 = os.ReadFile(path)
if err2 != nil {
t.Errorf("ReadFile(%s) error=%v", path, err2)
return
}
}
if err != zt.Error {
t.Errorf("error=%v, want %v", err, zt.Error)
@ -545,7 +557,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
// test read of each file
for i, ft := range zt.File {
readTestFile(t, zt, ft, z.File[i])
readTestFile(t, zt, ft, z.File[i], raw)
}
if t.Failed() {
return
@ -557,7 +569,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
for i := 0; i < 5; i++ {
for j, ft := range zt.File {
go func(j int, ft ZipTestFile) {
readTestFile(t, zt, ft, z.File[j])
readTestFile(t, zt, ft, z.File[j], raw)
done <- true
}(j, ft)
n++
@ -574,7 +586,7 @@ func equalTimeAndZone(t1, t2 time.Time) bool {
return t1.Equal(t2) && name1 == name2 && offset1 == offset2
}
func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File, raw []byte) {
if f.Name != ft.Name {
t.Errorf("name=%q, want %q", f.Name, ft.Name)
}
@ -594,6 +606,31 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
t.Errorf("%v: UncompressedSize=%#x does not match UncompressedSize64=%#x", f.Name, size, f.UncompressedSize64)
}
// Check that OpenRaw returns the correct byte segment
rw, err := f.OpenRaw()
if err != nil {
t.Errorf("%v: OpenRaw error=%v", f.Name, err)
return
}
start, err := f.DataOffset()
if err != nil {
t.Errorf("%v: DataOffset error=%v", f.Name, err)
return
}
got, err := io.ReadAll(rw)
if err != nil {
t.Errorf("%v: OpenRaw ReadAll error=%v", f.Name, err)
return
}
end := uint64(start) + f.CompressedSize64
want := raw[start:end]
if !bytes.Equal(got, want) {
t.Logf("got %q", got)
t.Logf("want %q", want)
t.Errorf("%v: OpenRaw returned unexpected bytes", f.Name)
return
}
r, err := f.Open()
if err != nil {
t.Errorf("%v", err)
@ -776,8 +813,8 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) {
// "archive/zip"
// "bytes"
// "io"
// "io/ioutil"
// "log"
// "os"
// )
//
// type zeros struct{}
@ -1073,11 +1110,218 @@ func TestIssue12449(t *testing.T) {
}
func TestFS(t *testing.T) {
z, err := OpenReader("testdata/unix.zip")
for _, test := range []struct {
file string
want []string
}{
{
"testdata/unix.zip",
[]string{"hello", "dir/bar", "readonly"},
},
{
"testdata/subdir.zip",
[]string{"a/b/c"},
},
} {
t.Run(test.file, func(t *testing.T) {
t.Parallel()
z, err := OpenReader(test.file)
if err != nil {
t.Fatal(err)
}
defer z.Close()
if err := fstest.TestFS(z, test.want...); err != nil {
t.Error(err)
}
})
}
}
func TestFSModTime(t *testing.T) {
t.Parallel()
z, err := OpenReader("testdata/subdir.zip")
if err != nil {
t.Fatal(err)
}
if err := fstest.TestFS(z, "hello", "dir/bar", "dir/empty", "readonly"); err != nil {
t.Fatal(err)
defer z.Close()
for _, test := range []struct {
name string
want time.Time
}{
{
"a",
time.Date(2021, 4, 19, 12, 29, 56, 0, timeZone(-7*time.Hour)).UTC(),
},
{
"a/b/c",
time.Date(2021, 4, 19, 12, 29, 59, 0, timeZone(-7*time.Hour)).UTC(),
},
} {
fi, err := fs.Stat(z, test.name)
if err != nil {
t.Errorf("%s: %v", test.name, err)
continue
}
if got := fi.ModTime(); !got.Equal(test.want) {
t.Errorf("%s: got modtime %v, want %v", test.name, got, test.want)
}
}
}
func TestCVE202127919(t *testing.T) {
// Archive containing only the file "../test.txt"
data := []byte{
0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2e, 0x2e,
0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78,
0x74, 0x0a, 0xc9, 0xc8, 0x2c, 0x56, 0xc8, 0x2c,
0x56, 0x48, 0x54, 0x28, 0x49, 0x2d, 0x2e, 0x51,
0x28, 0x49, 0xad, 0x28, 0x51, 0x48, 0xcb, 0xcc,
0x49, 0xd5, 0xe3, 0x02, 0x04, 0x00, 0x00, 0xff,
0xff, 0x50, 0x4b, 0x07, 0x08, 0xc0, 0xd7, 0xed,
0xc3, 0x20, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00,
0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x14,
0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0xd7, 0xed, 0xc3, 0x20, 0x00, 0x00,
0x00, 0x1a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
0x78, 0x74, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x39, 0x00,
0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
}
r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
if err != nil {
t.Fatalf("Error reading the archive: %v", err)
}
_, err = r.Open("test.txt")
if err != nil {
t.Errorf("Error reading file: %v", err)
}
}
func TestReadDataDescriptor(t *testing.T) {
tests := []struct {
desc string
in []byte
zip64 bool
want *dataDescriptor
wantErr error
}{{
desc: "valid 32 bit with signature",
in: []byte{
0x50, 0x4b, 0x07, 0x08, // signature
0x00, 0x01, 0x02, 0x03, // crc32
0x04, 0x05, 0x06, 0x07, // compressed size
0x08, 0x09, 0x0a, 0x0b, // uncompressed size
},
want: &dataDescriptor{
crc32: 0x03020100,
compressedSize: 0x07060504,
uncompressedSize: 0x0b0a0908,
},
}, {
desc: "valid 32 bit without signature",
in: []byte{
0x00, 0x01, 0x02, 0x03, // crc32
0x04, 0x05, 0x06, 0x07, // compressed size
0x08, 0x09, 0x0a, 0x0b, // uncompressed size
},
want: &dataDescriptor{
crc32: 0x03020100,
compressedSize: 0x07060504,
uncompressedSize: 0x0b0a0908,
},
}, {
desc: "valid 64 bit with signature",
in: []byte{
0x50, 0x4b, 0x07, 0x08, // signature
0x00, 0x01, 0x02, 0x03, // crc32
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size
},
zip64: true,
want: &dataDescriptor{
crc32: 0x03020100,
compressedSize: 0x0b0a090807060504,
uncompressedSize: 0x131211100f0e0d0c,
},
}, {
desc: "valid 64 bit without signature",
in: []byte{
0x00, 0x01, 0x02, 0x03, // crc32
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size
},
zip64: true,
want: &dataDescriptor{
crc32: 0x03020100,
compressedSize: 0x0b0a090807060504,
uncompressedSize: 0x131211100f0e0d0c,
},
}, {
desc: "invalid 32 bit with signature",
in: []byte{
0x50, 0x4b, 0x07, 0x08, // signature
0x00, 0x01, 0x02, 0x03, // crc32
0x04, 0x05, // unexpected end
},
wantErr: io.ErrUnexpectedEOF,
}, {
desc: "invalid 32 bit without signature",
in: []byte{
0x00, 0x01, 0x02, 0x03, // crc32
0x04, 0x05, // unexpected end
},
wantErr: io.ErrUnexpectedEOF,
}, {
desc: "invalid 64 bit with signature",
in: []byte{
0x50, 0x4b, 0x07, 0x08, // signature
0x00, 0x01, 0x02, 0x03, // crc32
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end
},
zip64: true,
wantErr: io.ErrUnexpectedEOF,
}, {
desc: "invalid 64 bit without signature",
in: []byte{
0x00, 0x01, 0x02, 0x03, // crc32
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end
},
zip64: true,
wantErr: io.ErrUnexpectedEOF,
}}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
r := bytes.NewReader(test.in)
desc, err := readDataDescriptor(r, test.zip64)
if err != test.wantErr {
t.Fatalf("got err %v; want nil", err)
}
if test.want == nil {
return
}
if desc == nil {
t.Fatalf("got nil DataDescriptor; want non-nil")
}
if desc.crc32 != test.want.crc32 {
t.Errorf("got CRC32 %#x; want %#x", desc.crc32, test.want.crc32)
}
if desc.compressedSize != test.want.compressedSize {
t.Errorf("got CompressedSize %#x; want %#x", desc.compressedSize, test.want.compressedSize)
}
if desc.uncompressedSize != test.want.uncompressedSize {
t.Errorf("got UncompressedSize %#x; want %#x", desc.uncompressedSize, test.want.uncompressedSize)
}
})
}
}

View file

@ -42,7 +42,7 @@ const (
directoryHeaderLen = 46 // + filename + extra + comment
directoryEndLen = 22 // + comment
dataDescriptorLen = 16 // four uint32: descriptor signature, crc32, compressed size, size
dataDescriptor64Len = 24 // descriptor with 8 byte sizes
dataDescriptor64Len = 24 // two uint32: signature, crc32 | two uint64: compressed size, size
directory64LocLen = 20 //
directory64EndLen = 56 // + extra
@ -315,6 +315,10 @@ func (h *FileHeader) isZip64() bool {
return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max
}
func (f *FileHeader) hasDataDescriptor() bool {
return f.Flags&0x8 != 0
}
func msdosModeToFileMode(m uint32) (mode fs.FileMode) {
if m&msdosDir != 0 {
mode = fs.ModeDir | 0777
@ -341,11 +345,9 @@ func fileModeToUnixMode(mode fs.FileMode) uint32 {
case fs.ModeSocket:
m = s_IFSOCK
case fs.ModeDevice:
if mode&fs.ModeCharDevice != 0 {
m = s_IFCHR
} else {
m = s_IFBLK
}
m = s_IFBLK
case fs.ModeDevice | fs.ModeCharDevice:
m = s_IFCHR
}
if mode&fs.ModeSetuid != 0 {
m |= s_ISUID
@ -388,3 +390,11 @@ func unixModeToFileMode(m uint32) fs.FileMode {
}
return mode
}
// dataDescriptor holds the data descriptor that optionally follows the file
// contents in the zip file.
type dataDescriptor struct {
crc32 uint32
compressedSize uint64
uncompressedSize uint64
}

BIN
src/archive/zip/testdata/subdir.zip vendored Normal file

Binary file not shown.

View file

@ -37,6 +37,7 @@ type Writer struct {
type header struct {
*FileHeader
offset uint64
raw bool
}
// NewWriter returns a new Writer writing a zip file to w.
@ -245,22 +246,31 @@ func detectUTF8(s string) (valid, require bool) {
return true, require
}
// prepare performs the bookkeeping operations required at the start of
// CreateHeader and CreateRaw.
func (w *Writer) prepare(fh *FileHeader) error {
if w.last != nil && !w.last.closed {
if err := w.last.close(); err != nil {
return err
}
}
if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh {
// See https://golang.org/issue/11144 confusion.
return errors.New("archive/zip: invalid duplicate FileHeader")
}
return nil
}
// CreateHeader adds a file to the zip archive using the provided FileHeader
// for the file metadata. Writer takes ownership of fh and may mutate
// its fields. The caller must not modify fh after calling CreateHeader.
//
// This returns a Writer to which the file contents should be written.
// The file's contents must be written to the io.Writer before the next
// call to Create, CreateHeader, or Close.
// call to Create, CreateHeader, CreateRaw, or Close.
func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
if w.last != nil && !w.last.closed {
if err := w.last.close(); err != nil {
return nil, err
}
}
if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh {
// See https://golang.org/issue/11144 confusion.
return nil, errors.New("archive/zip: invalid duplicate FileHeader")
if err := w.prepare(fh); err != nil {
return nil, err
}
// The ZIP format has a sad state of affairs regarding character encoding.
@ -365,7 +375,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
ow = fw
}
w.dir = append(w.dir, h)
if err := writeHeader(w.cw, fh); err != nil {
if err := writeHeader(w.cw, h); err != nil {
return nil, err
}
// If we're creating a directory, fw is nil.
@ -373,7 +383,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
return ow, nil
}
func writeHeader(w io.Writer, h *FileHeader) error {
func writeHeader(w io.Writer, h *header) error {
const maxUint16 = 1<<16 - 1
if len(h.Name) > maxUint16 {
return errLongName
@ -390,9 +400,20 @@ func writeHeader(w io.Writer, h *FileHeader) error {
b.uint16(h.Method)
b.uint16(h.ModifiedTime)
b.uint16(h.ModifiedDate)
b.uint32(0) // since we are writing a data descriptor crc32,
b.uint32(0) // compressed size,
b.uint32(0) // and uncompressed size should be zero
// In raw mode (caller does the compression), the values are either
// written here or in the trailing data descriptor based on the header
// flags.
if h.raw && !h.hasDataDescriptor() {
b.uint32(h.CRC32)
b.uint32(uint32(min64(h.CompressedSize64, uint32max)))
b.uint32(uint32(min64(h.UncompressedSize64, uint32max)))
} else {
// When this package handle the compression, these values are
// always written to the trailing data descriptor.
b.uint32(0) // crc32
b.uint32(0) // compressed size
b.uint32(0) // uncompressed size
}
b.uint16(uint16(len(h.Name)))
b.uint16(uint16(len(h.Extra)))
if _, err := w.Write(buf[:]); err != nil {
@ -405,6 +426,65 @@ func writeHeader(w io.Writer, h *FileHeader) error {
return err
}
func min64(x, y uint64) uint64 {
if x < y {
return x
}
return y
}
// CreateRaw adds a file to the zip archive using the provided FileHeader and
// returns a Writer to which the file contents should be written. The file's
// contents must be written to the io.Writer before the next call to Create,
// CreateHeader, CreateRaw, or Close.
//
// In contrast to CreateHeader, the bytes passed to Writer are not compressed.
func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error) {
if err := w.prepare(fh); err != nil {
return nil, err
}
fh.CompressedSize = uint32(min64(fh.CompressedSize64, uint32max))
fh.UncompressedSize = uint32(min64(fh.UncompressedSize64, uint32max))
h := &header{
FileHeader: fh,
offset: uint64(w.cw.count),
raw: true,
}
w.dir = append(w.dir, h)
if err := writeHeader(w.cw, h); err != nil {
return nil, err
}
if strings.HasSuffix(fh.Name, "/") {
w.last = nil
return dirWriter{}, nil
}
fw := &fileWriter{
header: h,
zipw: w.cw,
}
w.last = fw
return fw, nil
}
// Copy copies the file f (obtained from a Reader) into w. It copies the raw
// form directly bypassing decompression, compression, and validation.
func (w *Writer) Copy(f *File) error {
r, err := f.OpenRaw()
if err != nil {
return err
}
fw, err := w.CreateRaw(&f.FileHeader)
if err != nil {
return err
}
_, err = io.Copy(fw, r)
return err
}
// RegisterCompressor registers or overrides a custom compressor for a specific
// method ID. If a compressor for a given method is not found, Writer will
// default to looking up the compressor at the package level.
@ -446,6 +526,9 @@ func (w *fileWriter) Write(p []byte) (int, error) {
if w.closed {
return 0, errors.New("zip: write to closed file")
}
if w.raw {
return w.zipw.Write(p)
}
w.crc32.Write(p)
return w.rawCount.Write(p)
}
@ -455,6 +538,9 @@ func (w *fileWriter) close() error {
return errors.New("zip: file closed twice")
}
w.closed = true
if w.raw {
return w.writeDataDescriptor()
}
if err := w.comp.Close(); err != nil {
return err
}
@ -474,26 +560,33 @@ func (w *fileWriter) close() error {
fh.UncompressedSize = uint32(fh.UncompressedSize64)
}
return w.writeDataDescriptor()
}
func (w *fileWriter) writeDataDescriptor() error {
if !w.hasDataDescriptor() {
return nil
}
// Write data descriptor. This is more complicated than one would
// think, see e.g. comments in zipfile.c:putextended() and
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588.
// The approach here is to write 8 byte sizes if needed without
// adding a zip64 extra in the local header (too late anyway).
var buf []byte
if fh.isZip64() {
if w.isZip64() {
buf = make([]byte, dataDescriptor64Len)
} else {
buf = make([]byte, dataDescriptorLen)
}
b := writeBuf(buf)
b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X
b.uint32(fh.CRC32)
if fh.isZip64() {
b.uint64(fh.CompressedSize64)
b.uint64(fh.UncompressedSize64)
b.uint32(w.CRC32)
if w.isZip64() {
b.uint64(w.CompressedSize64)
b.uint64(w.UncompressedSize64)
} else {
b.uint32(fh.CompressedSize)
b.uint32(fh.UncompressedSize)
b.uint32(w.CompressedSize)
b.uint32(w.UncompressedSize)
}
_, err := w.zipw.Write(buf)
return err

View file

@ -6,8 +6,10 @@ package zip
import (
"bytes"
"compress/flate"
"encoding/binary"
"fmt"
"hash/crc32"
"io"
"io/fs"
"math/rand"
@ -57,6 +59,18 @@ var writeTests = []WriteTest{
Method: Deflate,
Mode: 0755 | fs.ModeSymlink,
},
{
Name: "device",
Data: []byte("device file"),
Method: Deflate,
Mode: 0755 | fs.ModeDevice,
},
{
Name: "chardevice",
Data: []byte("char device file"),
Method: Deflate,
Mode: 0755 | fs.ModeDevice | fs.ModeCharDevice,
},
}
func TestWriter(t *testing.T) {
@ -353,6 +367,171 @@ func TestWriterDirAttributes(t *testing.T) {
}
}
func TestWriterCopy(t *testing.T) {
// make a zip file
buf := new(bytes.Buffer)
w := NewWriter(buf)
for _, wt := range writeTests {
testCreate(t, w, &wt)
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
// read it back
src, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
if err != nil {
t.Fatal(err)
}
for i, wt := range writeTests {
testReadFile(t, src.File[i], &wt)
}
// make a new zip file copying the old compressed data.
buf2 := new(bytes.Buffer)
dst := NewWriter(buf2)
for _, f := range src.File {
if err := dst.Copy(f); err != nil {
t.Fatal(err)
}
}
if err := dst.Close(); err != nil {
t.Fatal(err)
}
// read the new one back
r, err := NewReader(bytes.NewReader(buf2.Bytes()), int64(buf2.Len()))
if err != nil {
t.Fatal(err)
}
for i, wt := range writeTests {
testReadFile(t, r.File[i], &wt)
}
}
func TestWriterCreateRaw(t *testing.T) {
files := []struct {
name string
content []byte
method uint16
flags uint16
crc32 uint32
uncompressedSize uint64
compressedSize uint64
}{
{
name: "small store w desc",
content: []byte("gophers"),
method: Store,
flags: 0x8,
},
{
name: "small deflate wo desc",
content: bytes.Repeat([]byte("abcdefg"), 2048),
method: Deflate,
},
}
// write a zip file
archive := new(bytes.Buffer)
w := NewWriter(archive)
for i := range files {
f := &files[i]
f.crc32 = crc32.ChecksumIEEE(f.content)
size := uint64(len(f.content))
f.uncompressedSize = size
f.compressedSize = size
var compressedContent []byte
if f.method == Deflate {
var buf bytes.Buffer
w, err := flate.NewWriter(&buf, flate.BestSpeed)
if err != nil {
t.Fatalf("flate.NewWriter err = %v", err)
}
_, err = w.Write(f.content)
if err != nil {
t.Fatalf("flate Write err = %v", err)
}
err = w.Close()
if err != nil {
t.Fatalf("flate Writer.Close err = %v", err)
}
compressedContent = buf.Bytes()
f.compressedSize = uint64(len(compressedContent))
}
h := &FileHeader{
Name: f.name,
Method: f.method,
Flags: f.flags,
CRC32: f.crc32,
CompressedSize64: f.compressedSize,
UncompressedSize64: f.uncompressedSize,
}
w, err := w.CreateRaw(h)
if err != nil {
t.Fatal(err)
}
if compressedContent != nil {
_, err = w.Write(compressedContent)
} else {
_, err = w.Write(f.content)
}
if err != nil {
t.Fatalf("%s Write got %v; want nil", f.name, err)
}
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
// read it back
r, err := NewReader(bytes.NewReader(archive.Bytes()), int64(archive.Len()))
if err != nil {
t.Fatal(err)
}
for i, want := range files {
got := r.File[i]
if got.Name != want.name {
t.Errorf("got Name %s; want %s", got.Name, want.name)
}
if got.Method != want.method {
t.Errorf("%s: got Method %#x; want %#x", want.name, got.Method, want.method)
}
if got.Flags != want.flags {
t.Errorf("%s: got Flags %#x; want %#x", want.name, got.Flags, want.flags)
}
if got.CRC32 != want.crc32 {
t.Errorf("%s: got CRC32 %#x; want %#x", want.name, got.CRC32, want.crc32)
}
if got.CompressedSize64 != want.compressedSize {
t.Errorf("%s: got CompressedSize64 %d; want %d", want.name, got.CompressedSize64, want.compressedSize)
}
if got.UncompressedSize64 != want.uncompressedSize {
t.Errorf("%s: got UncompressedSize64 %d; want %d", want.name, got.UncompressedSize64, want.uncompressedSize)
}
r, err := got.Open()
if err != nil {
t.Errorf("%s: Open err = %v", got.Name, err)
continue
}
buf, err := io.ReadAll(r)
if err != nil {
t.Errorf("%s: ReadAll err = %v", got.Name, err)
continue
}
if !bytes.Equal(buf, want.content) {
t.Errorf("%v: ReadAll returned unexpected bytes", got.Name)
}
}
}
func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
header := &FileHeader{
Name: wt.Name,
@ -378,15 +557,15 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) {
testFileMode(t, f, wt.Mode)
rc, err := f.Open()
if err != nil {
t.Fatal("opening:", err)
t.Fatalf("opening %s: %v", f.Name, err)
}
b, err := io.ReadAll(rc)
if err != nil {
t.Fatal("reading:", err)
t.Fatalf("reading %s: %v", f.Name, err)
}
err = rc.Close()
if err != nil {
t.Fatal("closing:", err)
t.Fatalf("closing %s: %v", f.Name, err)
}
if !bytes.Equal(b, wt.Data) {
t.Errorf("File contents %q, want %q", b, wt.Data)

View file

@ -670,7 +670,8 @@ func (b *Writer) WriteByte(c byte) error {
// WriteRune writes a single Unicode code point, returning
// the number of bytes written and any error.
func (b *Writer) WriteRune(r rune) (size int, err error) {
if r < utf8.RuneSelf {
// Compare as uint32 to correctly handle negative runes.
if uint32(r) < utf8.RuneSelf {
err = b.WriteByte(byte(r))
if err != nil {
return 0, err

View file

@ -534,6 +534,20 @@ func TestReadWriteRune(t *testing.T) {
}
}
func TestWriteInvalidRune(t *testing.T) {
// Invalid runes, including negative ones, should be written as the
// replacement character.
for _, r := range []rune{-1, utf8.MaxRune + 1} {
var buf bytes.Buffer
w := NewWriter(&buf)
w.WriteRune(r)
w.Flush()
if s := buf.String(); s != "\uFFFD" {
t.Errorf("WriteRune(%d) wrote %q, not replacement character", r, s)
}
}
}
func TestReadStringAllocs(t *testing.T) {
r := strings.NewReader(" foo foo 42 42 42 42 42 42 42 42 4.2 4.2 4.2 4.2\n")
buf := NewReader(r)

View file

@ -48,7 +48,8 @@ type Scanner struct {
// and the next token to return to the user, if any, plus an error, if any.
//
// Scanning stops if the function returns an error, in which case some of
// the input may be discarded.
// the input may be discarded. If that error is ErrFinalToken, scanning
// stops with no error.
//
// Otherwise, the Scanner advances the input. If the token is not nil,
// the Scanner returns it to the user. If the token is nil, the

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
//go:build linux
// +build linux
package bytes_test

View file

@ -275,7 +275,8 @@ func (b *Buffer) WriteByte(c byte) error {
// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
// if it becomes too large, WriteRune will panic with ErrTooLarge.
func (b *Buffer) WriteRune(r rune) (n int, err error) {
if r < utf8.RuneSelf {
// Compare as uint32 to correctly handle negative runes.
if uint32(r) < utf8.RuneSelf {
b.WriteByte(byte(r))
return 1, nil
}

View file

@ -6,6 +6,7 @@ package bytes_test
import (
. "bytes"
"fmt"
"io"
"math/rand"
"testing"
@ -387,6 +388,16 @@ func TestRuneIO(t *testing.T) {
}
}
func TestWriteInvalidRune(t *testing.T) {
// Invalid runes, including negative ones, should be written as
// utf8.RuneError.
for _, r := range []rune{-1, utf8.MaxRune + 1} {
var buf Buffer
buf.WriteRune(r)
check(t, fmt.Sprintf("TestWriteInvalidRune (%d)", r), &buf, "\uFFFD")
}
}
func TestNext(t *testing.T) {
b := []byte{0, 1, 2, 3, 4}
tmp := make([]byte, 5)

View file

@ -215,8 +215,7 @@ func main() {
}
optional := fileFeatures(*nextFile)
exception := fileFeatures(*exceptFile)
fail = !compareAPI(bw, features, required, optional, exception,
*allowNew && strings.Contains(runtime.Version(), "devel"))
fail = !compareAPI(bw, features, required, optional, exception, *allowNew)
}
// export emits the exported package features.

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build ignore
// +build ignore
// The run program is invoked via the dist tool.
@ -9,8 +10,11 @@
package main
import (
"errors"
"fmt"
exec "internal/execabs"
"internal/goversion"
"io/fs"
"log"
"os"
"path/filepath"
@ -42,6 +46,7 @@ func main() {
apiDir := filepath.Join(goroot, "api")
out, err := exec.Command(goCmd(), "tool", "api",
"-c", findAPIDirFiles(apiDir),
allowNew(apiDir),
"-next", filepath.Join(apiDir, "next.txt"),
"-except", filepath.Join(apiDir, "except.txt")).CombinedOutput()
if err != nil {
@ -70,3 +75,35 @@ func findAPIDirFiles(apiDir string) string {
}
return strings.Join(apiFiles, ",")
}
// allowNew returns the -allow_new flag to use for the 'go tool api' invocation.
func allowNew(apiDir string) string {
// Verify that the api/go1.n.txt for previous Go version exists.
// It definitely should, otherwise it's a signal that the logic below may be outdated.
if _, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version-1))); err != nil {
log.Fatalln("Problem with api file for previous release:", err)
}
// See whether the api/go1.n.txt for this Go version has been created.
// (As of April 2021, it gets created during the release of the first Beta.)
_, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version)))
if errors.Is(err, fs.ErrNotExist) {
// It doesn't exist, so we're in development or before Beta 1.
// At this stage, unmentioned API additions are deemed okay.
// (They will be quietly shown in API check output, but the test won't fail).
return "-allow_new=true"
} else if err == nil {
// The api/go1.n.txt for this Go version has been created,
// so we're definitely past Beta 1 in the release cycle.
//
// From this point, enforce that api/go1.n.txt is an accurate and complete
// representation of what's going into the release by failing API check if
// there are API additions (a month into the freeze, there shouldn't be many).
//
// See golang.org/issue/43956.
return "-allow_new=false"
} else {
log.Fatal(err)
}
panic("unreachable")
}

View file

@ -147,7 +147,16 @@ func arm64RegisterNumber(name string, n int16) (int16, bool) {
return 0, false
}
// ARM64RegisterExtension parses an ARM64 register with extension or arrangement.
// ARM64RegisterShift constructs an ARM64 register with shift operation.
func ARM64RegisterShift(reg, op, count int16) (int64, error) {
// the base register of shift operations must be general register.
if reg > arm64.REG_R31 || reg < arm64.REG_R0 {
return 0, errors.New("invalid register for shift operation")
}
return int64(reg&31)<<16 | int64(op)<<22 | int64(uint16(count)), nil
}
// ARM64RegisterExtension constructs an ARM64 register with extension or arrangement.
func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
Rnum := (reg & 31) + int16(num<<5)
if isAmount {
@ -155,154 +164,163 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
return errors.New("index shift amount is out of range")
}
}
switch ext {
case "UXTB":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_UXTB + Rnum
case "UXTH":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_UXTH + Rnum
case "UXTW":
if !isAmount {
return errors.New("invalid register extension")
}
// effective address of memory is a base register value and an offset register value.
if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_UXTW + Rnum
} else {
a.Reg = arm64.REG_UXTW + Rnum
}
case "UXTX":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_UXTX + Rnum
case "SXTB":
if !isAmount {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_SXTB + Rnum
case "SXTH":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_SXTH + Rnum
case "SXTW":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_SXTW + Rnum
} else {
a.Reg = arm64.REG_SXTW + Rnum
}
case "SXTX":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_SXTX + Rnum
} else {
a.Reg = arm64.REG_SXTX + Rnum
}
case "LSL":
if !isAmount {
return errors.New("invalid register extension")
}
a.Index = arm64.REG_LSL + Rnum
case "B8":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8B & 15) << 5)
case "B16":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_16B & 15) << 5)
case "H4":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4H & 15) << 5)
case "H8":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8H & 15) << 5)
case "S2":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2S & 15) << 5)
case "S4":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4S & 15) << 5)
case "D1":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1D & 15) << 5)
case "D2":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2D & 15) << 5)
case "Q1":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1Q & 15) << 5)
case "B":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_B & 15) << 5)
a.Index = num
case "H":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_H & 15) << 5)
a.Index = num
case "S":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_S & 15) << 5)
a.Index = num
case "D":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_D & 15) << 5)
a.Index = num
default:
return errors.New("unsupported register extension type: " + ext)
}
if reg <= arm64.REG_R31 && reg >= arm64.REG_R0 {
switch ext {
case "UXTB":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_UXTB + Rnum
case "UXTH":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_UXTH + Rnum
case "UXTW":
if !isAmount {
return errors.New("invalid register extension")
}
// effective address of memory is a base register value and an offset register value.
if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_UXTW + Rnum
} else {
a.Reg = arm64.REG_UXTW + Rnum
}
case "UXTX":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_UXTX + Rnum
case "SXTB":
if !isAmount {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_SXTB + Rnum
case "SXTH":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_SXTH + Rnum
case "SXTW":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_SXTW + Rnum
} else {
a.Reg = arm64.REG_SXTW + Rnum
}
case "SXTX":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_SXTX + Rnum
} else {
a.Reg = arm64.REG_SXTX + Rnum
}
case "LSL":
if !isAmount {
return errors.New("invalid register extension")
}
a.Index = arm64.REG_LSL + Rnum
default:
return errors.New("unsupported general register extension type: " + ext)
}
} else if reg <= arm64.REG_V31 && reg >= arm64.REG_V0 {
switch ext {
case "B8":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8B & 15) << 5)
case "B16":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_16B & 15) << 5)
case "H4":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4H & 15) << 5)
case "H8":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8H & 15) << 5)
case "S2":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2S & 15) << 5)
case "S4":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4S & 15) << 5)
case "D1":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1D & 15) << 5)
case "D2":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2D & 15) << 5)
case "Q1":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1Q & 15) << 5)
case "B":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_B & 15) << 5)
a.Index = num
case "H":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_H & 15) << 5)
a.Index = num
case "S":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_S & 15) << 5)
a.Index = num
case "D":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_D & 15) << 5)
a.Index = num
default:
return errors.New("unsupported simd register extension type: " + ext)
}
} else {
return errors.New("invalid register and extension combination")
}
return nil
}
// ARM64RegisterArrangement parses an ARM64 vector register arrangement.
// ARM64RegisterArrangement constructs an ARM64 vector register arrangement.
func ARM64RegisterArrangement(reg int16, name, arng string) (int64, error) {
var curQ, curSize uint16
if name[0] != 'V' {

View file

@ -134,6 +134,14 @@ func (p *Parser) asmText(operands [][]lex.Token) {
next++
}
// Issue an error if we see a function defined as ABIInternal
// without NOSPLIT. In ABIInternal, obj needs to know the function
// signature in order to construct the morestack path, so this
// currently isn't supported for asm functions.
if nameAddr.Sym.ABI() == obj.ABIInternal && flag&obj.NOSPLIT == 0 {
p.errorf("TEXT %q: ABIInternal requires NOSPLIT", name)
}
// Next operand is the frame and arg size.
// Bizarre syntax: $frameSize-argSize is two words, not subtraction.
// Both frameSize and argSize must be simple integers; only frameSize
@ -799,22 +807,11 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
p.errorf("can't handle %s instruction with 4 operands", op)
return
case 5:
if p.arch.Family == sys.PPC64 && arch.IsPPC64RLD(op) {
// Always reg, reg, con, con, reg. (con, con is a 'mask').
if p.arch.Family == sys.PPC64 {
prog.From = a[0]
// Second arg is always a register type on ppc64.
prog.Reg = p.getRegister(prog, op, &a[1])
mask1 := p.getConstant(prog, op, &a[2])
mask2 := p.getConstant(prog, op, &a[3])
var mask uint32
if mask1 < mask2 {
mask = (^uint32(0) >> uint(mask1)) & (^uint32(0) << uint(31-mask2))
} else {
mask = (^uint32(0) >> uint(mask2+1)) & (^uint32(0) << uint(31-(mask1-1)))
}
prog.SetFrom3(obj.Addr{
Type: obj.TYPE_CONST,
Offset: int64(mask),
})
prog.SetRestArgs([]obj.Addr{a[2], a[3]})
prog.To = a[4]
break
}

View file

@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"fmt"
"internal/buildcfg"
"io/ioutil"
"os"
"path/filepath"
@ -19,7 +20,6 @@ import (
"cmd/asm/internal/lex"
"cmd/internal/obj"
"cmd/internal/objabi"
)
// An end-to-end test for the assembler: Do we print what we parse?
@ -270,7 +270,7 @@ var (
errQuotesRE = regexp.MustCompile(`"([^"]*)"`)
)
func testErrors(t *testing.T, goarch, file string) {
func testErrors(t *testing.T, goarch, file string, flags ...string) {
input := filepath.Join("testdata", file+".s")
architecture, ctxt := setArch(goarch)
lexer := lex.NewLexer(input)
@ -292,6 +292,14 @@ func testErrors(t *testing.T, goarch, file string) {
}
errBuf.WriteString(s)
}
for _, flag := range flags {
switch flag {
case "dynlink":
ctxt.Flag_dynlink = true
default:
t.Errorf("unknown flag %s", flag)
}
}
pList.Firstpc, ok = parser.Parse()
obj.Flushplist(ctxt, pList, nil, "")
if ok && !failed {
@ -360,10 +368,10 @@ func Test386EndToEnd(t *testing.T) {
}
func TestARMEndToEnd(t *testing.T) {
defer func(old int) { objabi.GOARM = old }(objabi.GOARM)
defer func(old int) { buildcfg.GOARM = old }(buildcfg.GOARM)
for _, goarm := range []int{5, 6, 7} {
t.Logf("GOARM=%d", goarm)
objabi.GOARM = goarm
buildcfg.GOARM = goarm
testEndToEnd(t, "arm", "arm")
if goarm == 6 {
testEndToEnd(t, "arm", "armv6")
@ -430,6 +438,10 @@ func TestAMD64Errors(t *testing.T) {
testErrors(t, "amd64", "amd64error")
}
func TestAMD64DynLinkErrors(t *testing.T) {
testErrors(t, "amd64", "amd64dynlinkerror", "dynlink")
}
func TestMIPSEndToEnd(t *testing.T) {
testEndToEnd(t, "mips", "mips")
testEndToEnd(t, "mips64", "mips64")
@ -439,8 +451,12 @@ func TestPPC64EndToEnd(t *testing.T) {
testEndToEnd(t, "ppc64", "ppc64")
}
func TestRISCVEncoder(t *testing.T) {
testEndToEnd(t, "riscv64", "riscvenc")
func TestRISCVEndToEnd(t *testing.T) {
testEndToEnd(t, "riscv64", "riscv64")
}
func TestRISCVErrors(t *testing.T) {
testErrors(t, "riscv64", "riscv64error")
}
func TestS390XEndToEnd(t *testing.T) {

View file

@ -5,20 +5,20 @@
package asm
import (
"internal/buildcfg"
"strings"
"testing"
"cmd/asm/internal/arch"
"cmd/asm/internal/lex"
"cmd/internal/obj"
"cmd/internal/objabi"
)
// A simple in-out test: Do we print what we parse?
func setArch(goarch string) (*arch.Arch, *obj.Link) {
objabi.GOOS = "linux" // obj can handle this OS for all architectures.
objabi.GOARCH = goarch
buildcfg.GOOS = "linux" // obj can handle this OS for all architectures.
buildcfg.GOARCH = goarch
architecture := arch.Set(goarch)
if architecture == nil {
panic("asm: unrecognized architecture " + goarch)

View file

@ -689,7 +689,11 @@ func (p *Parser) registerShift(name string, prefix rune) int64 {
p.errorf("unexpected %s in register shift", tok.String())
}
if p.arch.Family == sys.ARM64 {
return int64(r1&31)<<16 | int64(op)<<22 | int64(uint16(count))
off, err := arch.ARM64RegisterShift(r1, op, count)
if err != nil {
p.errorf(err.Error())
}
return off
} else {
return int64((r1 & 15) | op<<5 | count)
}
@ -999,15 +1003,17 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
p.errorf("unimplemented two-register form")
}
a.Index = r1
if scale == 0 && p.arch.Family == sys.ARM64 {
// scale is 1 by default for ARM64
a.Scale = 1
if scale != 0 && p.arch.Family == sys.ARM64 {
p.errorf("arm64 doesn't support scaled register format")
} else {
a.Scale = int16(scale)
}
}
p.get(')')
} else if scale != 0 {
if p.arch.Family == sys.ARM64 {
p.errorf("arm64 doesn't support scaled register format")
}
// First (R) was missing, all we have is (R*scale).
a.Reg = 0
a.Index = r1

View file

@ -25,11 +25,13 @@ func tokenize(s string) [][]lex.Token {
func TestErroneous(t *testing.T) {
tests := []struct {
type errtest struct {
pseudo string
operands string
expected string
}{
}
nonRuntimeTests := []errtest{
{"TEXT", "", "expect two or three operands for TEXT"},
{"TEXT", "%", "expect two or three operands for TEXT"},
{"TEXT", "1, 1", "TEXT symbol \"<erroneous symbol>\" must be a symbol(SB)"},
@ -58,23 +60,44 @@ func TestErroneous(t *testing.T) {
{"PCDATA", "1", "expect two operands for PCDATA"},
}
runtimeTests := []errtest{
{"TEXT", "foo<ABIInternal>(SB),0", "TEXT \"foo\": ABIInternal requires NOSPLIT"},
}
testcats := []struct {
compilingRuntime bool
tests []errtest
}{
{
compilingRuntime: false,
tests: nonRuntimeTests,
},
{
compilingRuntime: true,
tests: runtimeTests,
},
}
// Note these errors should be independent of the architecture.
// Just run the test with amd64.
parser := newParser("amd64")
var buf bytes.Buffer
parser.errorWriter = &buf
for _, test := range tests {
parser.errorCount = 0
parser.lineNum++
if !parser.pseudo(test.pseudo, tokenize(test.operands)) {
t.Fatalf("Wrong pseudo-instruction: %s", test.pseudo)
for _, cat := range testcats {
for _, test := range cat.tests {
parser.compilingRuntime = cat.compilingRuntime
parser.errorCount = 0
parser.lineNum++
if !parser.pseudo(test.pseudo, tokenize(test.operands)) {
t.Fatalf("Wrong pseudo-instruction: %s", test.pseudo)
}
errorLine := buf.String()
if test.expected != errorLine {
t.Errorf("Unexpected error %q; expected %q", errorLine, test.expected)
}
buf.Reset()
}
errorLine := buf.String()
if test.expected != errorLine {
t.Errorf("Unexpected error %q; expected %q", errorLine, test.expected)
}
buf.Reset()
}
}

View file

@ -0,0 +1,68 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test to make sure that if we use R15 after it is clobbered by
// a global variable access while dynamic linking, we get an error.
// See issue 43661.
TEXT ·a1(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
MOVL $0, R15
RET
TEXT ·a2(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
MOVQ $0, R15
RET
TEXT ·a3(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
XORL R15, R15
RET
TEXT ·a4(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
XORQ R15, R15
RET
TEXT ·a5(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
XORL R15, R15
RET
TEXT ·a6(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
POPQ R15
PUSHQ R15
RET
TEXT ·a7(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
MOVQ R15, AX // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
RET
TEXT ·a8(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
ADDQ AX, R15 // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
RET
TEXT ·a9(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
ORQ R15, R15 // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
RET
TEXT ·a10(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
JEQ one
ORQ R15, R15 // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
one:
RET
TEXT ·a11(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
JEQ one
JMP two
one:
ORQ R15, R15 // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
two:
RET
TEXT ·a12(SB), 0, $0-0
CMPL runtime·writeBarrier(SB), $0
JMP one
two:
ORQ R15, R15
RET
one:
MOVL $0, R15
JMP two

View file

@ -64,6 +64,16 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
CMN R1.SXTX<<2, R10 // 5fe921ab
CMPW R2.UXTH<<3, R11 // 7f2d226b
CMNW R1.SXTB, R9 // 3f81212b
ADD R1<<1, RSP, R3 // e367218b
ADDW R1<<2, R3, RSP // 7f48210b
SUB R1<<3, RSP // ff6f21cb
SUBS R1<<4, RSP, R3 // e37321eb
ADDS R1<<1, RSP, R4 // e46721ab
CMP R1<<2, RSP // ff6b21eb
CMN R1<<3, RSP // ff6f21ab
ADDS R1<<1, ZR, R4 // e40701ab
ADD R3<<50, ZR, ZR // ffcb038b
CMP R4<<24, ZR // ff6304eb
CMPW $0x60060, R2 // CMPW $393312, R2 // 1b0c8052db00a0725f001b6b
CMPW $40960, R0 // 1f284071
CMPW $27745, R2 // 3b8c8d525f001b6b
@ -207,6 +217,18 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
VUADDW2 V9.B16, V12.H8, V14.H8 // 8e11296e
VUADDW2 V13.H8, V20.S4, V30.S4 // 9e126d6e
VUADDW2 V21.S4, V24.D2, V29.D2 // 1d13b56e
VUMAX V3.B8, V2.B8, V1.B8 // 4164232e
VUMAX V3.B16, V2.B16, V1.B16 // 4164236e
VUMAX V3.H4, V2.H4, V1.H4 // 4164632e
VUMAX V3.H8, V2.H8, V1.H8 // 4164636e
VUMAX V3.S2, V2.S2, V1.S2 // 4164a32e
VUMAX V3.S4, V2.S4, V1.S4 // 4164a36e
VUMIN V3.B8, V2.B8, V1.B8 // 416c232e
VUMIN V3.B16, V2.B16, V1.B16 // 416c236e
VUMIN V3.H4, V2.H4, V1.H4 // 416c632e
VUMIN V3.H8, V2.H8, V1.H8 // 416c636e
VUMIN V3.S2, V2.S2, V1.S2 // 416ca32e
VUMIN V3.S4, V2.S4, V1.S4 // 416ca36e
FCCMPS LT, F1, F2, $1 // 41b4211e
FMADDS F1, F3, F2, F4 // 440c011f
FMADDD F4, F5, F4, F4 // 8414441f
@ -352,6 +374,9 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
MOVD $1, ZR
MOVD $1, R1
MOVK $1, R1
MOVD $0x1000100010001000, RSP // MOVD $1152939097061330944, RSP // ff8304b2
MOVW $0x10001000, RSP // MOVW $268439552, RSP // ff830432
ADDW $0x10001000, R1 // ADDW $268439552, R1 // fb83043221001b0b
// move a large constant to a Vd.
VMOVS $0x80402010, V11 // VMOVS $2151686160, V11
@ -380,13 +405,13 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
// LD1/ST1
VLD1 (R8), [V1.B16, V2.B16] // 01a1404c
VLD1.P (R3), [V31.H8, V0.H8] // 7fa4df4c
VLD1.P (R8)(R20), [V21.B16, V22.B16] // VLD1.P (R8)(R20*1), [V21.B16,V22.B16] // 15a1d44c
VLD1.P (R8)(R20), [V21.B16, V22.B16] // 15a1d44c
VLD1.P 64(R1), [V5.B16, V6.B16, V7.B16, V8.B16] // 2520df4c
VLD1.P 1(R0), V4.B[15] // 041cdf4d
VLD1.P 2(R0), V4.H[7] // 0458df4d
VLD1.P 4(R0), V4.S[3] // 0490df4d
VLD1.P 8(R0), V4.D[1] // 0484df4d
VLD1.P (R0)(R1), V4.D[1] // VLD1.P (R0)(R1*1), V4.D[1] // 0484c14d
VLD1.P (R0)(R1), V4.D[1] // 0484c14d
VLD1 (R0), V4.D[1] // 0484404d
VST1.P [V4.S4, V5.S4], 32(R1) // 24a89f4c
VST1 [V0.S4, V1.S4], (R0) // 00a8004c
@ -394,29 +419,29 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
VLD1.P 24(R30), [V3.S2,V4.S2,V5.S2] // c36bdf0c
VLD2 (R29), [V23.H8, V24.H8] // b787404c
VLD2.P 16(R0), [V18.B8, V19.B8] // 1280df0c
VLD2.P (R1)(R2), [V15.S2, V16.S2] // VLD2.P (R1)(R2*1), [V15.S2,V16.S2] // 2f88c20c
VLD2.P (R1)(R2), [V15.S2, V16.S2] // 2f88c20c
VLD3 (R27), [V11.S4, V12.S4, V13.S4] // 6b4b404c
VLD3.P 48(RSP), [V11.S4, V12.S4, V13.S4] // eb4bdf4c
VLD3.P (R30)(R2), [V14.D2, V15.D2, V16.D2] // VLD3.P (R30)(R2*1), [V14.D2,V15.D2,V16.D2] // ce4fc24c
VLD3.P (R30)(R2), [V14.D2, V15.D2, V16.D2] // ce4fc24c
VLD4 (R15), [V10.H4, V11.H4, V12.H4, V13.H4] // ea05400c
VLD4.P 32(R24), [V31.B8, V0.B8, V1.B8, V2.B8] // 1f03df0c
VLD4.P (R13)(R9), [V14.S2, V15.S2, V16.S2, V17.S2] // VLD4.P (R13)(R9*1), [V14.S2,V15.S2,V16.S2,V17.S2] // ae09c90c
VLD4.P (R13)(R9), [V14.S2, V15.S2, V16.S2, V17.S2] // ae09c90c
VLD1R (R1), [V9.B8] // 29c0400d
VLD1R.P (R1), [V9.B8] // 29c0df0d
VLD1R.P 1(R1), [V2.B8] // 22c0df0d
VLD1R.P 2(R1), [V2.H4] // 22c4df0d
VLD1R (R0), [V0.B16] // 00c0404d
VLD1R.P (R0), [V0.B16] // 00c0df4d
VLD1R.P (R15)(R1), [V15.H4] // VLD1R.P (R15)(R1*1), [V15.H4] // efc5c10d
VLD1R.P (R15)(R1), [V15.H4] // efc5c10d
VLD2R (R15), [V15.H4, V16.H4] // efc5600d
VLD2R.P 16(R0), [V0.D2, V1.D2] // 00ccff4d
VLD2R.P (R0)(R5), [V31.D1, V0.D1] // VLD2R.P (R0)(R5*1), [V31.D1, V0.D1] // 1fcce50d
VLD2R.P (R0)(R5), [V31.D1, V0.D1] // 1fcce50d
VLD3R (RSP), [V31.S2, V0.S2, V1.S2] // ffeb400d
VLD3R.P 6(R15), [V15.H4, V16.H4, V17.H4] // efe5df0d
VLD3R.P (R15)(R6), [V15.H8, V16.H8, V17.H8] // VLD3R.P (R15)(R6*1), [V15.H8, V16.H8, V17.H8] // efe5c64d
VLD3R.P (R15)(R6), [V15.H8, V16.H8, V17.H8] // efe5c64d
VLD4R (R0), [V0.B8, V1.B8, V2.B8, V3.B8] // 00e0600d
VLD4R.P 16(RSP), [V31.S4, V0.S4, V1.S4, V2.S4] // ffebff4d
VLD4R.P (R15)(R9), [V15.H4, V16.H4, V17.H4, V18.H4] // VLD4R.P (R15)(R9*1), [V15.H4, V16.H4, V17.H4, V18.H4] // efe5e90d
VLD4R.P (R15)(R9), [V15.H4, V16.H4, V17.H4, V18.H4] // efe5e90d
VST1.P [V24.S2], 8(R2) // 58789f0c
VST1 [V29.S2, V30.S2], (R29) // bdab000c
VST1 [V14.H4, V15.H4, V16.H4], (R27) // 6e67000c
@ -424,17 +449,17 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
VST1.P V4.H[7], 2(R0) // 04589f4d
VST1.P V4.S[3], 4(R0) // 04909f4d
VST1.P V4.D[1], 8(R0) // 04849f4d
VST1.P V4.D[1], (R0)(R1) // VST1.P V4.D[1], (R0)(R1*1) // 0484814d
VST1.P V4.D[1], (R0)(R1) // 0484814d
VST1 V4.D[1], (R0) // 0484004d
VST2 [V22.H8, V23.H8], (R23) // f686004c
VST2.P [V14.H4, V15.H4], 16(R17) // 2e869f0c
VST2.P [V14.H4, V15.H4], (R3)(R17) // VST2.P [V14.H4,V15.H4], (R3)(R17*1) // 6e84910c
VST2.P [V14.H4, V15.H4], (R3)(R17) // 6e84910c
VST3 [V1.D2, V2.D2, V3.D2], (R11) // 614d004c
VST3.P [V18.S4, V19.S4, V20.S4], 48(R25) // 324b9f4c
VST3.P [V19.B8, V20.B8, V21.B8], (R3)(R7) // VST3.P [V19.B8, V20.B8, V21.B8], (R3)(R7*1) // 7340870c
VST3.P [V19.B8, V20.B8, V21.B8], (R3)(R7) // 7340870c
VST4 [V22.D2, V23.D2, V24.D2, V25.D2], (R3) // 760c004c
VST4.P [V14.D2, V15.D2, V16.D2, V17.D2], 64(R15) // ee0d9f4c
VST4.P [V24.B8, V25.B8, V26.B8, V27.B8], (R3)(R23) // VST4.P [V24.B8, V25.B8, V26.B8, V27.B8], (R3)(R23*1) // 7800970c
VST4.P [V24.B8, V25.B8, V26.B8, V27.B8], (R3)(R23) // 7800970c
// pre/post-indexed
FMOVS.P F20, 4(R0) // 144400bc
@ -521,29 +546,29 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
// shifted or extended register offset.
MOVD (R2)(R6.SXTW), R4 // 44c866f8
MOVD (R3)(R6), R5 // MOVD (R3)(R6*1), R5 // 656866f8
MOVD (R2)(R6), R4 // MOVD (R2)(R6*1), R4 // 446866f8
MOVD (R3)(R6), R5 // 656866f8
MOVD (R2)(R6), R4 // 446866f8
MOVWU (R19)(R20<<2), R20 // 747a74b8
MOVD (R2)(R6<<3), R4 // 447866f8
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
MOVBU (R3)(R9.UXTW), R8 // 68486938
MOVBU (R5)(R8), R10 // MOVBU (R5)(R8*1), R10 // aa686838
MOVBU (R5)(R8), R10 // aa686838
MOVHU (R2)(R7.SXTW<<1), R11 // 4bd86778
MOVHU (R1)(R2<<1), R5 // 25786278
MOVB (R9)(R3.UXTW), R6 // 2649a338
MOVB (R10)(R6), R15 // MOVB (R10)(R6*1), R15 // 4f69a638
MOVB (R10)(R6), R15 // 4f69a638
MOVB (R29)(R30<<0), R14 // ae7bbe38
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
MOVB (R29)(R30), R14 // ae6bbe38
MOVH (R5)(R7.SXTX<<1), R19 // b3f8a778
MOVH (R8)(R4<<1), R10 // 0a79a478
MOVW (R9)(R8.SXTW<<2), R19 // 33d9a8b8
MOVW (R1)(R4.SXTX), R11 // 2be8a4b8
MOVW (R1)(R4.SXTX), ZR // 3fe8a4b8
MOVW (R2)(R5), R12 // MOVW (R2)(R5*1), R12 // 4c68a5b8
FMOVS (R2)(R6), F4 // FMOVS (R2)(R6*1), F4 // 446866bc
MOVW (R2)(R5), R12 // 4c68a5b8
FMOVS (R2)(R6), F4 // 446866bc
FMOVS (R2)(R6<<2), F4 // 447866bc
FMOVD (R2)(R6), F4 // FMOVD (R2)(R6*1), F4 // 446866fc
FMOVD (R2)(R6), F4 // 446866fc
FMOVD (R2)(R6<<3), F4 // 447866fc
MOVD R5, (R2)(R6<<3) // 457826f8
@ -553,15 +578,15 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
MOVW R7, (R3)(R4.SXTW) // 67c824b8
MOVB R4, (R2)(R6.SXTX) // 44e82638
MOVB R8, (R3)(R9.UXTW) // 68482938
MOVB R10, (R5)(R8) // MOVB R10, (R5)(R8*1) // aa682838
MOVB R10, (R5)(R8) // aa682838
MOVH R11, (R2)(R7.SXTW<<1) // 4bd82778
MOVH R5, (R1)(R2<<1) // 25782278
MOVH R7, (R2)(R5.SXTX<<1) // 47f82578
MOVH R8, (R3)(R6.UXTW) // 68482678
MOVB R4, (R2)(R6.SXTX) // 44e82638
FMOVS F4, (R2)(R6) // FMOVS F4, (R2)(R6*1) // 446826bc
FMOVS F4, (R2)(R6) // 446826bc
FMOVS F4, (R2)(R6<<2) // 447826bc
FMOVD F4, (R2)(R6) // FMOVD F4, (R2)(R6*1) // 446826fc
FMOVD F4, (R2)(R6) // 446826fc
FMOVD F4, (R2)(R6<<3) // 447826fc
// vmov
@ -571,9 +596,12 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
VMOV R20, V1.S[0] // 811e044e
VMOV R20, V1.S[1] // 811e0c4e
VMOV R1, V9.H4 // 290c020e
VDUP R1, V9.H4 // 290c020e
VMOV R22, V11.D2 // cb0e084e
VDUP R22, V11.D2 // cb0e084e
VMOV V2.B16, V4.B16 // 441ca24e
VMOV V20.S[0], V20 // 9406045e
VDUP V20.S[0], V20 // 9406045e
VMOV V12.D[0], V12.D[1] // 8c05186e
VMOV V10.S[0], V12.S[1] // 4c050c6e
VMOV V9.H[0], V12.H[1] // 2c05066e
@ -982,6 +1010,54 @@ again:
FSTPS (F3, F4), x(SB)
FSTPS (F3, F4), x+8(SB)
// FLDPQ/FSTPQ
FLDPQ -4000(R0), (F1, F2) // 1b803ed1610b40ad
FLDPQ -1024(R0), (F1, F2) // 010860ad
FLDPQ (R0), (F1, F2) // 010840ad
FLDPQ 16(R0), (F1, F2) // 018840ad
FLDPQ -16(R0), (F1, F2) // 01887fad
FLDPQ.W 32(R0), (F1, F2) // 0108c1ad
FLDPQ.P 32(R0), (F1, F2) // 0108c1ac
FLDPQ 11(R0), (F1, F2) // 1b2c0091610b40ad
FLDPQ 1024(R0), (F1, F2) // 1b001091610b40ad
FLDPQ 4104(R0), (F1, F2)
FLDPQ -4000(RSP), (F1, F2) // fb833ed1610b40ad
FLDPQ -1024(RSP), (F1, F2) // e10b60ad
FLDPQ (RSP), (F1, F2) // e10b40ad
FLDPQ 16(RSP), (F1, F2) // e18b40ad
FLDPQ -16(RSP), (F1, F2) // e18b7fad
FLDPQ.W 32(RSP), (F1, F2) // e10bc1ad
FLDPQ.P 32(RSP), (F1, F2) // e10bc1ac
FLDPQ 11(RSP), (F1, F2) // fb2f0091610b40ad
FLDPQ 1024(RSP), (F1, F2) // fb031091610b40ad
FLDPQ 4104(RSP), (F1, F2)
FLDPQ -31(R0), (F1, F2) // 1b7c00d1610b40ad
FLDPQ -4(R0), (F1, F2) // 1b1000d1610b40ad
FLDPQ x(SB), (F1, F2)
FLDPQ x+8(SB), (F1, F2)
FSTPQ (F3, F4), -4000(R5) // bb803ed1631300ad
FSTPQ (F3, F4), -1024(R5) // a31020ad
FSTPQ (F3, F4), (R5) // a31000ad
FSTPQ (F3, F4), 16(R5) // a39000ad
FSTPQ (F3, F4), -16(R5) // a3903fad
FSTPQ.W (F3, F4), 32(R5) // a31081ad
FSTPQ.P (F3, F4), 32(R5) // a31081ac
FSTPQ (F3, F4), 11(R5) // bb2c0091631300ad
FSTPQ (F3, F4), 1024(R5) // bb001091631300ad
FSTPQ (F3, F4), 4104(R5)
FSTPQ (F3, F4), -4000(RSP) // fb833ed1631300ad
FSTPQ (F3, F4), -1024(RSP) // e31320ad
FSTPQ (F3, F4), (RSP) // e31300ad
FSTPQ (F3, F4), 16(RSP) // e39300ad
FSTPQ (F3, F4), -16(RSP) // e3933fad
FSTPQ.W (F3, F4), 32(RSP) // e31381ad
FSTPQ.P (F3, F4), 32(RSP) // e31381ac
FSTPQ (F3, F4), 11(RSP) // fb2f0091631300ad
FSTPQ (F3, F4), 1024(RSP) // fb031091631300ad
FSTPQ (F3, F4), 4104(RSP)
FSTPQ (F3, F4), x(SB)
FSTPQ (F3, F4), x+8(SB)
// System Register
MSR $1, SPSel // bf4100d5
MSR $9, DAIFSet // df4903d5

View file

@ -188,7 +188,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
MOVBU 2916(R24), R3 // 03936d39
MOVBU (R19)(R14<<0), R23 // 777a6e38
MOVBU (R2)(R8.SXTX), R19 // 53e86838
MOVBU (R27)(R23), R14 // MOVBU (R27)(R23*1), R14 // 6e6b7738
MOVBU (R27)(R23), R14 // 6e6b7738
MOVHU.P 107(R14), R13 // cdb54678
MOVHU.W 192(R3), R2 // 620c4c78
MOVHU 6844(R4), R19 // 93787579
@ -201,9 +201,9 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
MOVB 997(R9), R23 // 37958f39
//TODO MOVBW (R2<<1)(R21), R15 // af7ae238
//TODO MOVBW (R26)(R0), R21 // 1568fa38
MOVB (R5)(R15), R16 // MOVB (R5)(R15*1), R16 // b068af38
MOVB (R5)(R15), R16 // b068af38
MOVB (R19)(R26.SXTW), R19 // 73caba38
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
MOVB (R29)(R30), R14 // ae6bbe38
//TODO MOVHW.P 218(R22), R25 // d9a6cd78
MOVH.P 179(R23), R5 // e5368b78
//TODO MOVHW.W 136(R2), R27 // 5b8cc878
@ -357,12 +357,12 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
MOVD R25, -137(R17) // 397217f8
MOVW R4, (R12)(R22.UXTW<<2) // 845936b8
MOVD R27, (R5)(R15.UXTW<<3) // bb582ff8
MOVB R2, (R10)(R16) // MOVB R2, (R10)(R16*1) // 42693038
MOVB R2, (R29)(R26) // MOVB R2, (R29)(R26*1) // a26b3a38
MOVB R2, (R10)(R16) // 42693038
MOVB R2, (R29)(R26) // a26b3a38
MOVH R11, -80(R23) // eb021b78
MOVH R11, (R27)(R14.SXTW<<1) // 6bdb2e78
MOVB R19, (R0)(R4) // MOVB R19, (R0)(R4*1) // 13682438
MOVB R1, (R6)(R4) // MOVB R1, (R6)(R4*1) // c1682438
MOVB R19, (R0)(R4) // 13682438
MOVB R1, (R6)(R4) // c1682438
MOVH R3, (R11)(R13<<1) // 63792d78
//TODO STTR 55(R4), R29 // 9d7803b8
//TODO STTR 124(R5), R25 // b9c807f8
@ -669,6 +669,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
VCMEQ V24.S4, V13.S4, V12.S4 // ac8db86e
VCNT V13.B8, V11.B8 // ab59200e
VMOV V31.B[15], V18 // f2071f5e
VDUP V31.B[15], V18 // f2071f5e
VDUP V31.B[13], V20.B16 // f4071b4e
VEOR V4.B8, V18.B8, V7.B8 // 471e242e
VEXT $4, V2.B8, V1.B8, V3.B8 // 2320022e
@ -679,27 +680,28 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
VLD1 (R24), [V18.D1, V19.D1, V20.D1] // 126f400c
VLD1 (R29), [V14.D1, V15.D1, V16.D1, V17.D1] // ae2f400c
VLD1.P 16(R23), [V1.B16] // e172df4c
VLD1.P (R6)(R11), [V31.D1] // VLD1.P (R6)(R11*1), [V31.D1] // df7ccb0c
VLD1.P (R6)(R11), [V31.D1] // df7ccb0c
VLD1.P 16(R7), [V31.D1, V0.D1] // ffacdf0c
VLD1.P (R19)(R4), [V24.B8, V25.B8] // VLD1.P (R19)(R4*1), [V24.B8, V25.B8] // 78a2c40c
VLD1.P (R20)(R8), [V7.H8, V8.H8, V9.H8] // VLD1.P (R20)(R8*1), [V7.H8, V8.H8, V9.H8] // 8766c84c
VLD1.P (R19)(R4), [V24.B8, V25.B8] // 78a2c40c
VLD1.P (R20)(R8), [V7.H8, V8.H8, V9.H8] // 8766c84c
VLD1.P 32(R30), [V5.B8, V6.B8, V7.B8, V8.B8] // c523df0c
VLD1 (R19), V14.B[15] // 6e1e404d
VLD1 (R29), V0.H[1] // a04b400d
VLD1 (R27), V2.S[0] // 6283400d
VLD1 (R21), V5.D[1] // a586404d
VLD1.P 1(R19), V10.B[14] // 6a1adf4d
VLD1.P (R3)(R14), V16.B[11] // VLD1.P (R3)(R14*1), V16.B[11] // 700cce4d
VLD1.P (R3)(R14), V16.B[11] // 700cce4d
VLD1.P 2(R1), V28.H[2] // 3c50df0d
VLD1.P (R13)(R20), V9.H[2] // VLD1.P (R13)(R20*1), V9.H[2] // a951d40d
VLD1.P (R13)(R20), V9.H[2] // a951d40d
VLD1.P 4(R17), V1.S[3] // 2192df4d
VLD1.P (R14)(R2), V17.S[2] // VLD1.P (R14)(R2*1), V17.S[2] // d181c24d
VLD1.P (R14)(R2), V17.S[2] // d181c24d
VLD1.P 8(R5), V30.D[1] // be84df4d
VLD1.P (R27)(R13), V27.D[0] // VLD1.P (R27)(R13*1), V27.D[0] // 7b87cd0d
VLD1.P (R27)(R13), V27.D[0] // 7b87cd0d
//TODO FMOVS.P -29(RSP), F8 // e8375ebc
//TODO FMOVS.W 71(R29), F28 // bc7f44bc
FMOVS 6160(R4), F23 // 971058bd
VMOV V18.B[10], V27 // 5b06155e
VDUP V18.B[10], V27 // 5b06155e
VMOV V12.B[2], V28.B[12] // 9c15196e
VMOV R30, V4.B[13] // c41f1b4e
VMOV V2.B16, V4.B16 // 441ca24e
@ -732,25 +734,25 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
VSHL $7, V22.D2, V25.D2 // d956474f
VST1 [V14.H4, V15.H4, V16.H4], (R27) // 6e67000c
VST1 [V2.S4, V3.S4, V4.S4, V5.S4], (R14) // c229004c
VST1.P [V25.S4], (R7)(R29) // VST1.P [V25.S4], (R7)(R29*1) // f9789d4c
VST1.P [V25.S4], (R7)(R29) // f9789d4c
VST1.P [V25.D2, V26.D2], 32(R7) // f9ac9f4c
VST1.P [V14.D1, V15.D1], (R7)(R23) // VST1.P [V14.D1, V15.D1], (R7)(R23*1) // eeac970c
VST1.P [V14.D1, V15.D1], (R7)(R23) // eeac970c
VST1.P [V25.D2, V26.D2, V27.D2], 48(R27) // 796f9f4c
VST1.P [V13.H8, V14.H8, V15.H8], (R3)(R14) // VST1.P [V13.H8, V14.H8, V15.H8], (R3)(R14*1) // 6d648e4c
VST1.P [V13.H8, V14.H8, V15.H8], (R3)(R14) // 6d648e4c
VST1.P [V16.S4, V17.S4, V18.S4, V19.S4], 64(R6) // d0289f4c
VST1.P [V19.H4, V20.H4, V21.H4, V22.H4], (R4)(R16) // VST1.P [V19.H4, V20.H4, V21.H4, V22.H4], (R4)(R16*1) // 9324900c
VST1.P [V19.H4, V20.H4, V21.H4, V22.H4], (R4)(R16) // 9324900c
VST1 V12.B[3], (R1) // 2c0c000d
VST1 V12.B[3], (R1) // 2c0c000d
VST1 V25.S[2], (R20) // 9982004d
VST1 V9.D[1], (RSP) // e987004d
VST1.P V30.B[6], 1(R3) // 7e189f0d
VST1.P V8.B[0], (R3)(R21) // VST1.P V8.B[0], (R3)(R21*1) // 6800950d
VST1.P V8.B[0], (R3)(R21) // 6800950d
VST1.P V15.H[5], 2(R10) // 4f499f4d
VST1.P V1.H[7], (R23)(R11) // VST1.P V1.H[7], (R23)(R11*1) // e15a8b4d
VST1.P V1.H[7], (R23)(R11) // e15a8b4d
VST1.P V26.S[0], 4(R11) // 7a819f0d
VST1.P V9.S[1], (R16)(R21) // VST1.P V9.S[1], (R16)(R21*1) // 0992950d
VST1.P V9.S[1], (R16)(R21) // 0992950d
VST1.P V16.D[0], 8(R9) // 30859f0d
VST1.P V23.D[1], (R21)(R16) // VST1.P V23.D[1], (R21)(R16*1) // b786904d
VST1.P V23.D[1], (R21)(R16) // b786904d
VSUB V1, V12, V23 // 9785e17e
VUADDLV V31.S4, V11 // eb3bb06e
UCVTFWS R11, F19 // 7301231e

View file

@ -8,10 +8,48 @@ TEXT errors(SB),$0
ADDSW R7->32, R14, R13 // ERROR "shift amount out of range 0 to 31"
ADD R1.UXTB<<5, R2, R3 // ERROR "shift amount out of range 0 to 4"
ADDS R1.UXTX<<7, R2, R3 // ERROR "shift amount out of range 0 to 4"
ADDS R5, R6, RSP // ERROR "illegal destination register"
SUBS R5, R6, RSP // ERROR "illegal destination register"
ADDSW R5, R6, RSP // ERROR "illegal destination register"
SUBSW R5, R6, RSP // ERROR "illegal destination register"
ADDS $0xff, R6, RSP // ERROR "illegal destination register"
ADDS $0xffff0, R6, RSP // ERROR "illegal destination register"
ADDS $0x1000100010001000, R6, RSP // ERROR "illegal destination register"
ADDS $0x10001000100011, R6, RSP // ERROR "illegal destination register"
ADDSW $0xff, R6, RSP // ERROR "illegal destination register"
ADDSW $0xffff0, R6, RSP // ERROR "illegal destination register"
ADDSW $0x1000100010001000, R6, RSP // ERROR "illegal destination register"
ADDSW $0x10001000100011, R6, RSP // ERROR "illegal destination register"
SUBS $0xff, R6, RSP // ERROR "illegal destination register"
SUBS $0xffff0, R6, RSP // ERROR "illegal destination register"
SUBS $0x1000100010001000, R6, RSP // ERROR "illegal destination register"
SUBS $0x10001000100011, R6, RSP // ERROR "illegal destination register"
SUBSW $0xff, R6, RSP // ERROR "illegal destination register"
SUBSW $0xffff0, R6, RSP // ERROR "illegal destination register"
SUBSW $0x1000100010001000, R6, RSP // ERROR "illegal destination register"
SUBSW $0x10001000100011, R6, RSP // ERROR "illegal destination register"
AND $0x22220000, R2, RSP // ERROR "illegal combination"
ANDS $0x22220000, R2, RSP // ERROR "illegal combination"
ADD R1, R2, R3, R4 // ERROR "illegal combination"
BICW R7@>33, R5, R16 // ERROR "shift amount out of range 0 to 31"
NEGW R7<<33, R5 // ERROR "shift amount out of range 0 to 31"
NEGSW R7<<33, R5 // ERROR "shift amount out of range 0 to 31"
ADD R7@>2, R5, R16 // ERROR "unsupported shift operator"
ADDW R7@>2, R5, R16 // ERROR "unsupported shift operator"
ADDS R7@>2, R5, R16 // ERROR "unsupported shift operator"
ADDSW R7@>2, R5, R16 // ERROR "unsupported shift operator"
SUB R7@>2, R5, R16 // ERROR "unsupported shift operator"
SUBW R7@>2, R5, R16 // ERROR "unsupported shift operator"
SUBS R7@>2, R5, R16 // ERROR "unsupported shift operator"
SUBSW R7@>2, R5, R16 // ERROR "unsupported shift operator"
CMP R7@>2, R5 // ERROR "unsupported shift operator"
CMPW R7@>2, R5 // ERROR "unsupported shift operator"
CMN R7@>2, R5 // ERROR "unsupported shift operator"
CMNW R7@>2, R5 // ERROR "unsupported shift operator"
NEG R7@>2, R5 // ERROR "unsupported shift operator"
NEGW R7@>2, R5 // ERROR "unsupported shift operator"
NEGS R7@>2, R5 // ERROR "unsupported shift operator"
NEGSW R7@>2, R5 // ERROR "unsupported shift operator"
CINC CS, R2, R3, R4 // ERROR "illegal combination"
CSEL LT, R1, R2 // ERROR "illegal combination"
LDP.P 8(R2), (R2, R3) // ERROR "constrained unpredictable behavior"
@ -21,8 +59,8 @@ TEXT errors(SB),$0
LDP (R0), (R3, ZR) // ERROR "invalid register pair"
LDXPW (RSP), (R2, R2) // ERROR "constrained unpredictable behavior"
LDAXPW (R5), (R2, R2) // ERROR "constrained unpredictable behavior"
MOVD.P 300(R2), R3 // ERROR "offset out of range [-255,254]"
MOVD.P R3, 344(R2) // ERROR "offset out of range [-255,254]"
MOVD.P 300(R2), R3 // ERROR "offset out of range [-256,255]"
MOVD.P R3, 344(R2) // ERROR "offset out of range [-256,255]"
MOVD (R3)(R7.SXTX<<2), R8 // ERROR "invalid index shift amount"
MOVWU (R5)(R4.UXTW<<3), R10 // ERROR "invalid index shift amount"
MOVWU (R5)(R4<<1), R10 // ERROR "invalid index shift amount"
@ -58,13 +96,13 @@ TEXT errors(SB),$0
VMOV V8.H[9], R3 // ERROR "register element index out of range 0 to 7"
VMOV V8.S[4], R3 // ERROR "register element index out of range 0 to 3"
VMOV V8.D[2], R3 // ERROR "register element index out of range 0 to 1"
VDUP V8.B[16], R3.B16 // ERROR "register element index out of range 0 to 15"
VDUP V8.B[17], R3.B8 // ERROR "register element index out of range 0 to 15"
VDUP V8.H[9], R3.H4 // ERROR "register element index out of range 0 to 7"
VDUP V8.H[9], R3.H8 // ERROR "register element index out of range 0 to 7"
VDUP V8.S[4], R3.S2 // ERROR "register element index out of range 0 to 3"
VDUP V8.S[4], R3.S4 // ERROR "register element index out of range 0 to 3"
VDUP V8.D[2], R3.D2 // ERROR "register element index out of range 0 to 1"
VDUP V8.B[16], V3.B16 // ERROR "register element index out of range 0 to 15"
VDUP V8.B[17], V3.B8 // ERROR "register element index out of range 0 to 15"
VDUP V8.H[9], V3.H4 // ERROR "register element index out of range 0 to 7"
VDUP V8.H[9], V3.H8 // ERROR "register element index out of range 0 to 7"
VDUP V8.S[4], V3.S2 // ERROR "register element index out of range 0 to 3"
VDUP V8.S[4], V3.S4 // ERROR "register element index out of range 0 to 3"
VDUP V8.D[2], V3.D2 // ERROR "register element index out of range 0 to 1"
VFMLA V1.D2, V12.D2, V3.S2 // ERROR "operand mismatch"
VFMLA V1.S2, V12.S2, V3.D2 // ERROR "operand mismatch"
VFMLA V1.S4, V12.S2, V3.D2 // ERROR "operand mismatch"
@ -109,6 +147,9 @@ TEXT errors(SB),$0
VREV16 V1.D1, V2.D1 // ERROR "invalid arrangement"
VREV16 V1.B8, V2.B16 // ERROR "invalid arrangement"
VREV16 V1.H4, V2.H4 // ERROR "invalid arrangement"
FLDPQ (R0), (R1, R2) // ERROR "invalid register pair"
FLDPQ (R1), (F2, F2) // ERROR "constrained unpredictable behavior"
FSTPQ (R1, R2), (R0) // ERROR "invalid register pair"
FLDPD (R0), (R1, R2) // ERROR "invalid register pair"
FLDPD (R1), (F2, F2) // ERROR "constrained unpredictable behavior"
FLDPS (R2), (F3, F3) // ERROR "constrained unpredictable behavior"
@ -355,10 +396,17 @@ TEXT errors(SB),$0
VBIF V0.D2, V1.D2, V2.D2 // ERROR "invalid arrangement"
VUADDW V9.B8, V12.H8, V14.B8 // ERROR "invalid arrangement"
VUADDW2 V9.B8, V12.S4, V14.S4 // ERROR "operand mismatch"
VUMAX V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement"
VUMIN V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement"
VUMAX V1.B8, V2.B8, V3.B16 // ERROR "operand mismatch"
VUMIN V1.H4, V2.S4, V3.H4 // ERROR "operand mismatch"
VSLI $64, V7.D2, V8.D2 // ERROR "shift out of range"
VUSRA $0, V7.D2, V8.D2 // ERROR "shift out of range"
CASPD (R3, R4), (R2), (R8, R9) // ERROR "source register pair must start from even register"
CASPD (R2, R3), (R2), (R9, R10) // ERROR "destination register pair must start from even register"
CASPD (R2, R4), (R2), (R8, R9) // ERROR "source register pair must be contiguous"
CASPD (R2, R3), (R2), (R8, R10) // ERROR "destination register pair must be contiguous"
ADD R1>>2, RSP, R3 // ERROR "illegal combination"
ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference"
CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4"
RET

View file

@ -407,6 +407,8 @@ label4:
SRLV R27, R6, R17 // 03668816
SRA R11, R19, R20 // 0173a007
SRAV R20, R19, R19 // 02939817
ROTR R19, R18, R20 // 0272a046
ROTRV R9, R13, R16 // 012d8056
// LSHW rreg ',' rreg
// {
@ -418,6 +420,8 @@ label4:
SRLV R27, R6 // 03663016
SRA R11, R19 // 01739807
SRAV R20, R19 // 02939817
ROTR R20, R19 // 02939846
ROTRV R16, R9 // 02094856
// LSHW imm ',' sreg ',' rreg
// {
@ -429,6 +433,8 @@ label4:
SRLV $31, R6, R17 // 00068ffa
SRA $8, R8, R19 // 00089a03
SRAV $19, R8, R7 // 00083cfb
ROTR $12, R8, R3 // 00281b02
ROTRV $8, R22, R22 // 0036b23a
// LSHW imm ',' rreg
// {
@ -440,6 +446,8 @@ label4:
SRLV $31, R17 // 00118ffa
SRA $3, R12 // 000c60c3
SRAV $12, R3 // 00031b3b
ROTR $12, R8 // 00284302
ROTRV $63, R22 // 0036b7fe
// LAND/LXOR/LNOR/LOR rreg ',' rreg

View file

@ -41,6 +41,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVDBR (R3)(R4), R5 // 7ca41c28
MOVWBR (R3)(R4), R5 // 7ca41c2c
MOVHBR (R3)(R4), R5 // 7ca41e2c
MOVD $foo+4009806848(FP), R5 // 3fe1ef0138bfcc20
MOVD $foo(SB), R5 // 3fe0000038bf0000
MOVDU 8(R3), R4 // e8830009
MOVDU (R3)(R4), R5 // 7ca4186a
@ -77,6 +79,15 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVBU R4, 1(R3) // 9c830001
MOVBU R5, (R3)(R4) // 7ca419ee
MOVB $0, R4 // 38800000
MOVBZ $0, R4 // 38800000
MOVH $0, R4 // 38800000
MOVHZ $0, R4 // 38800000
MOVW $0, R4 // 38800000
MOVWZ $0, R4 // 38800000
MOVD $0, R4 // 38800000
MOVD $0, R0 // 38000000
ADD $1, R3 // 38630001
ADD $1, R3, R4 // 38830001
ADD $-1, R4 // 3884ffff
@ -280,11 +291,17 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
ROTLW R3, R4, R5 // 5c85183e
EXTSWSLI $3, R4, R5 // 7c851ef4
RLWMI $7, R3, $65535, R6 // 50663c3e
RLWMI $7, R3, $16, $31, R6 // 50663c3e
RLWMICC $7, R3, $65535, R6 // 50663c3f
RLWMICC $7, R3, $16, $31, R6 // 50663c3f
RLWNM $3, R4, $7, R6 // 54861f7e
RLWNM $3, R4, $29, $31, R6 // 54861f7e
RLWNM R3, R4, $7, R6 // 5c861f7e
RLWNM R3, R4, $29, $31, R6 // 5c861f7e
RLWNMCC $3, R4, $7, R6 // 54861f7f
RLWNMCC $3, R4, $29, $31, R6 // 54861f7f
RLWNMCC R3, R4, $7, R6 // 5c861f7f
RLWNMCC R3, R4, $29, $31, R6 // 5c861f7f
RLDMI $0, R4, $7, R6 // 7886076c
RLDMICC $0, R4, $7, R6 // 7886076d
RLDIMI $0, R4, $7, R6 // 788601cc
@ -303,6 +320,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
RLDICCC $0, R4, $15, R6 // 788603c9
CLRLSLWI $16, R5, $8, R4 // 54a4422e
CLRLSLDI $24, R4, $2, R3 // 78831588
RLDCR $1, R1, $-16, R1 // 78210ee4
RLDCRCC $1, R1, $-16, R1 // 78210ee5
BEQ 0(PC) // 41820000
BEQ CR1,0(PC) // 41860000

View file

@ -280,6 +280,9 @@ start:
MOV $2047, X5 // 9b02f07f
MOV $-2048, X5 // 9b020080
// Converted to load of symbol.
MOV $4294967296, X5 // 97020000
MOV (X5), X6 // 03b30200
MOV 4(X5), X6 // 03b34200
MOVB (X5), X6 // 03830200
@ -325,7 +328,7 @@ start:
// These jumps can get printed as jumps to 2 because they go to the
// second instruction in the function (the first instruction is an
// invisible stack pointer adjustment).
JMP start // JMP 2 // 6ff09fc2
JMP start // JMP 2 // 6ff01fc2
JMP (X5) // 67800200
JMP 4(X5) // 67804200
@ -338,16 +341,16 @@ start:
JMP asmtest(SB) // 970f0000
// Branch pseudo-instructions
BEQZ X5, start // BEQZ X5, 2 // e38602c0
BGEZ X5, start // BGEZ X5, 2 // e3d402c0
BGT X5, X6, start // BGT X5, X6, 2 // e34253c0
BGTU X5, X6, start // BGTU X5, X6, 2 // e36053c0
BGTZ X5, start // BGTZ X5, 2 // e34e50be
BLE X5, X6, start // BLE X5, X6, 2 // e35c53be
BLEU X5, X6, start // BLEU X5, X6, 2 // e37a53be
BLEZ X5, start // BLEZ X5, 2 // e35850be
BLTZ X5, start // BLTZ X5, 2 // e3c602be
BNEZ X5, start // BNEZ X5, 2 // e39402be
BEQZ X5, start // BEQZ X5, 2 // e38202c0
BGEZ X5, start // BGEZ X5, 2 // e3d002c0
BGT X5, X6, start // BGT X5, X6, 2 // e34e53be
BGTU X5, X6, start // BGTU X5, X6, 2 // e36c53be
BGTZ X5, start // BGTZ X5, 2 // e34a50be
BLE X5, X6, start // BLE X5, X6, 2 // e35853be
BLEU X5, X6, start // BLEU X5, X6, 2 // e37653be
BLEZ X5, start // BLEZ X5, 2 // e35450be
BLTZ X5, start // BLTZ X5, 2 // e3c202be
BNEZ X5, start // BNEZ X5, 2 // e39002be
// Set pseudo-instructions
SEQZ X15, X15 // 93b71700

Some files were not shown because too many files have changed in this diff Show more