Compare commits

...

45 Commits

Author SHA1 Message Date
Heschi Kreinick
04cd717a26 [release-branch.go1.16] go1.16.4
Change-Id: I7fb3c30641332961819a79819c7567cf1dbe1ab1
Reviewed-on: https://go-review.googlesource.com/c/go/+/317649
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Trust: Carlos Amedee <carlos@golang.org>
Trust: Heschi Kreinick <heschi@google.com>
2021-05-06 15:00:00 +00:00
Clément Chigot
87ffba35dd [release-branch.go1.16] runtime/pprof: skip tests for AIX
Most of the time, the pprof tests are passing, except
for the builder. The reason is still unknown but I'd rather release
the builder to avoid missing other more important bugs.

Updates #45170

Change-Id: I667543ee1ae309b7319c5b3676a0901b4d0ecf2e
Reviewed-on: https://go-review.googlesource.com/c/go/+/306489
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Trust: Lynn Boger <laboger@linux.vnet.ibm.com>
(cherry picked from commit 7bfd681c2f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/317297
Trust: Heschi Kreinick <heschi@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2021-05-05 21:05:09 +00:00
Andrew G. Morgan
ce04f86bd3 [release-branch.go1.16] syscall: syscall.AllThreadsSyscall signal handling fixes
The runtime support for syscall.AllThreadsSyscall() functions had
some corner case deadlock issues when signal handling was in use.
This was observed in at least 3 build test failures on ppc64 and
amd64 architecture CGO_ENABLED=0 builds over the last few months.

The fixes involve more controlled handling of signals while the
AllThreads mechanism is being executed. Further details are
discussed in bug #44193.

The all-threads syscall support is new in go1.16, so earlier
releases are not affected by this bug.

Fixes #45307

Change-Id: I01ba8508a6e1bb2d872751f50da86dd07911a41d
Reviewed-on: https://go-review.googlesource.com/c/go/+/305149
Reviewed-by: Michael Pratt <mpratt@google.com>
Trust: Michael Pratt <mpratt@google.com>
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
(cherry picked from commit 7e97e4e8cc)
Reviewed-on: https://go-review.googlesource.com/c/go/+/316869
Run-TryBot: Ian Lance Taylor <iant@golang.org>
2021-05-04 20:41:53 +00:00
Paul E. Murphy
7e709791c2 [release-branch.go1.16] cmd/compile: fix ANDI/SRWI merge on ppc64
The shift amount should be masked to avoid rotation values
beyond the numer of bits. In this case, if the shift amount
is 0, it should rotate 0, not 32.

Fixes #45636

Change-Id: I1e764497a39d0ec128e29af42352b70c70b2ecc5
Reviewed-on: https://go-review.googlesource.com/c/go/+/310569
Run-TryBot: Paul Murphy <murp@ibm.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
Reviewed-by: Carlos Eduardo Seo <carlos.seo@linaro.org>
Trust: Carlos Eduardo Seo <carlos.seo@linaro.org>
(cherry picked from commit c8fb0ec5a0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/311378
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Trust: Lynn Boger <laboger@linux.vnet.ibm.com>
2021-05-04 15:18:16 +00:00
Michael Pratt
ea0537f2fc [release-branch.go1.16] runtime: non-strict InlTreeIndex lookup in expandFinalInlineFrame
This is a follow-up to golang.org/cl/301369, which made the same change
in Frames.Next. The same logic applies here: a profile stack may have
been truncated at an invalid PC provided by cgoTraceback.
expandFinalInlineFrame will then try to lookup the inline tree and
crash.

The same fix applies as well: upon encountering a bad PC, simply leave
it as-is and move on.

For #44971
For #45480
Fixes #45482

Change-Id: I2823c67a1f3425466b05384cc6d30f5fc8ee6ddc
Reviewed-on: https://go-review.googlesource.com/c/go/+/309109
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Trust: Michael Pratt <mpratt@google.com>
(cherry picked from commit aad13cbb74)
Reviewed-on: https://go-review.googlesource.com/c/go/+/309551
Run-TryBot: Michael Pratt <mpratt@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
2021-05-04 15:14:17 +00:00
Ian Lance Taylor
e67a58b7cb [release-branch.go1.16] archive/zip: only return directory once via io/fs.FS
While we're here fix the ModTime value for directories.

For #43872
For #45345
Fixes #45347

Change-Id: I155e6517713ef6a9482b9431f1167a44337c6ad2
Reviewed-on: https://go-review.googlesource.com/c/go/+/311530
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
(cherry picked from commit 87e4dcd446)
Reviewed-on: https://go-review.googlesource.com/c/go/+/315249
Trust: Jeremy Faller <jeremy@golang.org>
2021-04-30 19:36:35 +00:00
Katie Hockman
d4adea20f0 [release-branch.go1.16] std: update golang.org/x/net to 20210428183300-3f4a416c7d3b
Steps:
  go get -d golang.org/x/net@internal-branch.go1.16-vendor
  go mod tidy
  go mod vendor

This http2 bundle does not need to be updated.

Fixes #45712

Change-Id: I7c86c31248e0cd250d17495c3f985671cfcf44a3
Reviewed-on: https://go-review.googlesource.com/c/go/+/314789
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Katie Hockman <katie@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2021-04-28 19:55:12 +00:00
Ian Lance Taylor
f12cf7694f [release-branch.go1.16] time: use offset and isDST when caching zone from extend string
If the current time is computed from extend string
and the zone file contains multiple zones with the
same name, the lookup by name might find incorrect
zone.

This happens for example with the slim Europe/Dublin
time zone file in the embedded zip. This zone file
has last transition in 1996 and rest is covered by
extend string.
tzset returns IST as the zone name to use, but there
are two records with IST name. Lookup by name finds
the wrong one. We need to check offset and isDST too.

In case we can't find an existing zone, we allocate
a new zone so that we use correct offset and isDST.

I have renamed zone variable to zones as it shadowed
the zone type that we need to allocate the cached zone.

Backport note: this change also incorporates portions of
CL 264077.

For #45370
Fixes #45385

Change-Id: If7a0cccc1908e27f0509bf422d824133133250fc
Reviewed-on: https://go-review.googlesource.com/c/go/+/307211
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
2021-04-12 21:25:46 +00:00
Dmitri Shuralyov
9baddd3f21 [release-branch.go1.16] go1.16.3
Change-Id: Iace7cfec757a6d0bac25f729be5ecb2ae3b59d74
Reviewed-on: https://go-review.googlesource.com/c/go/+/306569
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Carlos Amedee <carlos@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
2021-04-01 17:26:20 +00:00
Pat Gavlin
96139f2599 [release-branch.go1.16] cmd/compile: fix long RMW bit operations on AMD64
Under certain circumstances, the existing rules for bit operations can
produce code that writes beyond its intended bounds. For example,
consider the following code:

    func repro(b []byte, addr, bit int32) {
	    _ = b[3]
	    v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 | 1<<(bit&31)
	    b[0] = byte(v)
	    b[1] = byte(v >> 8)
	    b[2] = byte(v >> 16)
	    b[3] = byte(v >> 24)
    }

Roughly speaking:

1. The expression `1 << (bit & 31)` is rewritten into `(SHLL 1 bit)`
2. The expression `uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 |
   uint32(b[3])<<24` is rewritten into `(MOVLload &b[0])`
3. The statements `b[0] = byte(v) ... b[3] = byte(v >> 24)` are
   rewritten into `(MOVLstore &b[0], v)`
4. `(ORL (SHLL 1, bit) (MOVLload &b[0]))` is rewritten into
   `(BTSL (MOVLload &b[0]) bit)`. This is a valid transformation because
   the destination is a register: in this case, the bit offset is masked
   by the number of bits in the destination register. This is identical
   to the masking performed by `SHL`.
5. `(MOVLstore &b[0] (BTSL (MOVLload &b[0]) bit))` is rewritten into
   `(BTSLmodify &b[0] bit)`. This is an invalid transformation because
   the destination is memory: in this case, the bit offset is not
   masked, and the chosen instruction may write outside its intended
   32-bit location.

These changes fix the invalid rewrite performed in step (5) by
explicitly maksing the bit offset operand to `BT(S|R|C)(L|Q)modify`. In
the example above, the adjusted rules produce
`(BTSLmodify &b[0] (ANDLconst [31] bit))` in step (5).

These changes also add several new rules to rewrite bit sets, toggles,
and clears that are rooted at `(OR|XOR|AND)(L|Q)modify` operators into
appropriate `BT(S|R|C)(L|Q)modify` operators. These rules catch cases
where `MOV(L|Q)store ((OR|XOR|AND)(L|Q) ...)` is rewritten to
`(OR|XOR|AND)(L|Q)modify` before the `(OR|XOR|AND)(L|Q) ...` can be
rewritten to `BT(S|R|C)(L|Q) ...`.

Overall, compilecmp reports small improvements in code size on
darwin/amd64 when the changes to the compiler itself are exlcuded:

file                               before   after    Δ       %
runtime.s                          536464   536412   -52     -0.010%
bytes.s                            32629    32593    -36     -0.110%
strings.s                          44565    44529    -36     -0.081%
os/signal.s                        7967     7959     -8      -0.100%
cmd/vendor/golang.org/x/sys/unix.s 81686    81678    -8      -0.010%
math/big.s                         188235   188253   +18     +0.010%
cmd/link/internal/loader.s         89295    89056    -239    -0.268%
cmd/link/internal/ld.s             633551   633232   -319    -0.050%
cmd/link/internal/arm.s            18934    18928    -6      -0.032%
cmd/link/internal/arm64.s          31814    31801    -13     -0.041%
cmd/link/internal/riscv64.s        7347     7345     -2      -0.027%
cmd/compile/internal/ssa.s         4029173  4033066  +3893   +0.097%
total                              21298280 21301472 +3192   +0.015%

Fixes #45253

Change-Id: I2e560548b515865129e1724e150e30540e9d29ce
GitHub-Last-Rev: ab94ede1d097f920a9d1d3da403c8e4a3d8f6d44
GitHub-Pull-Request: golang/go#45242
Reviewed-on: https://go-review.googlesource.com/c/go/+/305069
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2021-03-31 17:15:59 +00:00
Michael Pratt
887c0d890f [release-branch.go1.16] runtime: non-strict InlTreeIndex lookup in Frames.Next
When using cgo, some of the frames can be provided by cgoTraceback, a
cgo-provided function to generate C tracebacks. Unlike Go tracebacks,
cgoTraceback has no particular guarantees that it produces valid
tracebacks.

If one of the (invalid) frames happens to put the PC in the alignment
region at the end of a function (filled with int 3's on amd64), then
Frames.Next will find a valid funcInfo for the PC, but pcdatavalue will
panic because PCDATA doesn't cover this PC.

Tolerate this case by doing a non-strict PCDATA lookup. We'll still show
a bogus frame, but at least avoid throwing.

For #44971
Fixes #45303

Change-Id: I9eed728470d6f264179a7615bd19845c941db78c
Reviewed-on: https://go-review.googlesource.com/c/go/+/301369
Trust: Michael Pratt <mpratt@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
(cherry picked from commit e4a4161f1f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/305889
2021-03-31 16:59:18 +00:00
Keith Randall
3a45c13094 [release-branch.go1.16] cmd/compile: disable shortcircuit optimization for intertwined phi values
We need to be careful that when doing value graph surgery, we not
re-substitute a value that has already been substituted. That can lead
to confusing a previous iteration's value with the current iteration's
value.

The simple fix in this CL just aborts the optimization if it detects
intertwined phis (a phi which is the argument to another phi). It
might be possible to keep the optimization with a more complicated
CL, but:
  1) This CL is clearly safe to backport.
  2) There were no instances of this abort triggering in
     all.bash, prior to the test introduced in this CL.

Fixes #45192

Change-Id: I2411dca03948653c053291f6829a76bec0c32330
Reviewed-on: https://go-review.googlesource.com/c/go/+/304251
Trust: Keith Randall <khr@golang.org>
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
(cherry picked from commit 771c57e68e)
Reviewed-on: https://go-review.googlesource.com/c/go/+/304530
2021-03-31 14:33:46 +00:00
Bryan C. Mills
2940614c63 [release-branch.go1.16] cmd/go: allow '+' in package import paths in module mode
This change upgrades x/mod to pull in the fix from CL 300152.

Updates #44776.
Fixes #44885.

Change-Id: I273f41df2abfff76d91315b7f19fce851c8770d8
Reviewed-on: https://go-review.googlesource.com/c/go/+/300176
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
(cherry picked from commit d33e2192a7)
Reviewed-on: https://go-review.googlesource.com/c/go/+/300153
2021-03-31 14:26:53 +00:00
Russ Cox
1d967ab95c [release-branch.go1.16] build: set GOPATH consistently in run.bash, run.bat, run.rc
We used to clear GOPATH in all the build scripts.
Clearing GOPATH is misleading at best, since you just end up
with the default GOPATH (%USERPROFILE%\go on Windows).
Unless that's your GOROOT, in which case you end up with a
fatal error from the go command (#43938).

run.bash changed to setting GOPATH=/dev/null, which has no
clear analogue on Windows.

run.rc still clears GOPATH.

Change them all to set GOPATH to a non-existent directory
/nonexist-gopath or c:\nonexist-gopath.

For #45238.
Fixes #45240.

Change-Id: I51edd66d37ff6a891b0d0541d91ecba97fbbb03d
Reviewed-on: https://go-review.googlesource.com/c/go/+/288818
Trust: Russ Cox <rsc@golang.org>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
(cherry picked from commit bb6efb9609)
Reviewed-on: https://go-review.googlesource.com/c/go/+/304772
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Alexander Rakoczy <alex@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Trust: Carlos Amedee <carlos@golang.org>
2021-03-29 19:16:21 +00:00
Cherry Zhang
9c7463ca90 [release-branch.go1.16] cmd/link: generate trampoline for inter-dependent packages
Currently, in the trampoline generation pass we expect packages
are laid out in dependency order, so a cross-package jump always
has a known target address so we can check if a trampoline is
needed. With linknames, there can be cycles in the package
dependency graph, making this algorithm no longer work. For them,
as the target address is unkown we conservatively generate a
trampoline. This may generate unnecessary trampolines (if the
packages turn out laid together), but package cycles are extremely
rare so this is fine.

Updates #44639.
Fixes #44640.

Change-Id: I2dc2998edacbda27d726fc79452313a21d07787a
Reviewed-on: https://go-review.googlesource.com/c/go/+/292490
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
(cherry picked from commit 098504c73f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/296909
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
2021-03-25 18:34:20 +00:00
Cherry Zhang
ac59d7abb9 [release-branch.go1.16] cmd/compile, cmd/link: dynamically export writable static tmps
Static tmps are private to a package, but with plugins a package
can be shared among multiple DSOs. They need to have a consistent
view of the static tmps, especially for writable ones. So export
them. (Read-only static tmps have the same values anyway, so it
doesn't matter. Also Mach-O doesn't support dynamically exporting
read-only symbols anyway.)

Updates #44956.
Fixes #45030.

Change-Id: I921e25b7ab73cd5d5347800eccdb7931e3448779
Reviewed-on: https://go-review.googlesource.com/c/go/+/301793
Trust: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
(cherry picked from commit de012bc095359e1b552d4ea6fb6b2995f3ab04f5)
Reviewed-on: https://go-review.googlesource.com/c/go/+/302449
2021-03-25 18:33:03 +00:00
Jay Conrod
33fb47921f [release-branch.go1.16] cmd/go/internal/modfetch: detect and recover from missing ziphash file
Previously, if an extracted module directory existed in the module
cache, but the corresponding ziphash file did not, if the sum was
missing from go.sum, we would not verify the sum. This caused 'go get'
not to write missing sums. 'go build' in readonly mode (now the
default) checks for missing sums and doesn't attempt to fetch modules
that can't be verified against go.sum.

With this change, when requesting the module directory with
modfetch.DownloadDir, if the ziphash file is missing, the go command
will re-hash the zip without downloading or re-extracting it again.

Note that the go command creates the ziphash file before the module
directory, but another program could remove it separately, and it
might not be present after a crash.

Fixes #44812

Change-Id: I64551e048a3ba17d069de1ec123d5b8b2757543c
Reviewed-on: https://go-review.googlesource.com/c/go/+/298352
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
(cherry picked from commit 302a400316)
Reviewed-on: https://go-review.googlesource.com/c/go/+/298851
2021-03-25 18:28:35 +00:00
Tao Qingyun
902d16e97b [release-branch.go1.16] testing: update helperNames just before checking it
parent's helperNames has not been set when frameSkip called, moving
helperNames initilazing to frameSkip.

For #44887
Fixes #44888

Change-Id: I5107c5951033e5e47d1ac441eac3ba5344a7bdc0
GitHub-Last-Rev: 44b90b2e2e
GitHub-Pull-Request: golang/go#45071
Reviewed-on: https://go-review.googlesource.com/c/go/+/302469
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
(cherry picked from commit 6704843202)
Reviewed-on: https://go-review.googlesource.com/c/go/+/303189
Trust: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
2021-03-24 20:20:01 +00:00
Jay Conrod
f39c4deee8 [release-branch.go1.16] cmd/go: fix godoc formatting for text from 'go help install'
Fixes #44860

Change-Id: I5a12c6437a91ce59307483ffcc70e084edc32197
Reviewed-on: https://go-review.googlesource.com/c/go/+/301329
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
(cherry picked from commit 86bbf4beee)
Reviewed-on: https://go-review.googlesource.com/c/go/+/301429
2021-03-12 21:52:25 +00:00
Michael Pratt
0da04a662a [release-branch.go1.16] runtime, time: disable preemption in addtimer
The timerpMask optimization updates a mask of Ps (potentially)
containing timers in pidleget / pidleput. For correctness, it depends on
the assumption that new timers can only be added to a P's own heap.

addtimer violates this assumption if it is preempted after computing pp.
That G may then run on a different P, but adding a timer to the original
P's heap.

Avoid this by disabling preemption while pp is in use.

Other uses of doaddtimer should be OK:

* moveTimers: always moves to the current P's heap
* modtimer, cleantimers, addAdjustedTimers, runtimer: does not add net
  new timers to the heap while locked

For #44868
Fixes #44869

Change-Id: I4a5d080865e854931d0a3a09a51ca36879101d72
Reviewed-on: https://go-review.googlesource.com/c/go/+/300610
Trust: Michael Pratt <mpratt@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
(cherry picked from commit aa26687e45)
Reviewed-on: https://go-review.googlesource.com/c/go/+/300611
2021-03-12 20:01:03 +00:00
Carlos Amedee
3979fb9af9 [release-branch.go1.16] go1.16.2
Change-Id: I0513a9731e0e0d57bfeda0ffab1c5787edc916f8
Reviewed-on: https://go-review.googlesource.com/c/go/+/300969
Run-TryBot: Carlos Amedee <carlos@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Trust: Carlos Amedee <carlos@golang.org>
2021-03-11 17:08:05 +00:00
Jay Conrod
5993fbbd48 [release-branch.go1.16] cmd/go: clarify errors for commands run outside a module
The new error message tells the user what was wrong (no go.mod found)
and directs them to 'go help modules', which links to tutorials.

Includes test fix from CL 298794
Fixes #44746

Change-Id: I98f31fec4a8757eb1792b45491519da4c552cb0f
Reviewed-on: https://go-review.googlesource.com/c/go/+/298650
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
(cherry picked from commit b87e9b9f68)
Reviewed-on: https://go-review.googlesource.com/c/go/+/298929
2021-03-10 21:27:07 +00:00
Jay Conrod
6e04188440 [release-branch.go1.16] cmd/go: don't report missing std import errors for tidy and vendor
'go mod tidy' and 'go mod vendor' normally report errors when a
package can't be imported, even if the import appears in a file that
wouldn't be compiled by the current version of Go. These errors are
common for packages introduced in higher versions of Go, like "embed"
in 1.16.

This change causes 'go mod tidy' and 'go mod vendor' to ignore
missing package errors if the import path appears to come from the
standard library because it lacks a dot in the first path element.

Fixes #44793
Updates #27063

Change-Id: I61d6443e77ab95fd8c0d1514f57ef4c8885a77cc
Reviewed-on: https://go-review.googlesource.com/c/go/+/298749
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
(cherry picked from commit 56d52e6611)
Reviewed-on: https://go-review.googlesource.com/c/go/+/298949
2021-03-10 21:25:35 +00:00
Katie Hockman
b5c1b5aa07 [release-branch.go1.16] all: merge release-branch.go1.16-security into release-branch.go1.16
Change-Id: Icc8775f559b0125eae94ce4ffd4dcb4e7146a500
2021-03-10 11:55:14 -05:00
Alexander Rakoczy
e9e0473681 [release-branch.go1.16-security] go1.16.1
Change-Id: I4999d72caf9462554a2a6f1d761244cafec34718
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1014541
Reviewed-by: Katie Hockman <katiehockman@google.com>
2021-03-10 14:25:03 +00:00
Roland Shoemaker
634d28d78c [release-branch.go1.16-security] archive/zip: fix panic in Reader.Open
When operating on a Zip file that contains a file prefixed with "../",
Open(...) would cause a panic in toValidName when attempting to strip
the prefixed path components.

Fixes CVE-2021-27919

Change-Id: Ic755d8126cb0897e2cbbdacf572439c38dde7b35
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1004761
Reviewed-by: Filippo Valsorda <valsorda@google.com>
Reviewed-by: Russ Cox <rsc@google.com>
Reviewed-by: Katie Hockman <katiehockman@google.com>
(cherry picked from commit ce22003b26eaf8e4a690757f699aae7062d41472)
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1013753
Reviewed-by: Roland Shoemaker <bracewell@google.com>
2021-03-09 17:55:16 +00:00
Katie Hockman
d86e53e896 [release-branch.go1.16-security] encoding/xml: prevent infinite loop while decoding
This change properly handles a TokenReader which
returns an EOF in the middle of an open XML
element.

Thanks to Sam Whited for reporting this.

Fixes CVE-2021-27918

Change-Id: Id02a3f3def4a1b415fa2d9a8e3b373eb6cb0f433
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1004594
Reviewed-by: Russ Cox <rsc@google.com>
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Filippo Valsorda <valsorda@google.com>
(cherry picked from commit e7ce1f6746223ec7b4caa3b1ece25d9be3864710)
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1014235
2021-03-09 17:55:05 +00:00
Jay Conrod
3068d55c2f [release-branch.go1.16] cmd: upgrade golang.org/x/mod to relax import path check
This incorporates CL 298009, which allows leading dots in import path
elements but not module path elements. Also added a test.

Fixes #44647
Updates #34992

Change-Id: I2d5faabd8f7b23a7943d3f3ccb6707ab5dc2ce3c
Reviewed-on: https://go-review.googlesource.com/c/go/+/297530
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
(cherry picked from commit 97bdac03ae)
Reviewed-on: https://go-review.googlesource.com/c/go/+/297912
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2021-03-03 17:59:29 +00:00
Jay Conrod
a9ba734e4d [release-branch.go1.16] cmd/go/internal/modload: don't query when fixing canonical versions
If a canonical version is passed to fixVersion when loading the main
go.mod and that version don't match the module path's major version
suffix, don't call Query.

Query doesn't return a useful error in this case when the path is
malformed, for example, when it doens't have a dot in the first path
element. It's better to report the major version mismatch error.

Fixes #44496

Change-Id: I97b1f64aee894fa0db6fb637aa03a51357ee782c
Reviewed-on: https://go-review.googlesource.com/c/go/+/296590
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
(cherry picked from commit 5fafc0bbd4)
Reviewed-on: https://go-review.googlesource.com/c/go/+/297989
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2021-03-03 17:58:41 +00:00
Jay Conrod
047ca22916 [release-branch.go1.16] cmd: upgrade golang.org/x/mod to fix go.mod parser
modfile.Parse passed an empty string to the VersionFixer for the
module path. This caused errors for v2+ versions.

For #44496

Change-Id: I13b86b6ecf6815c4bc9a96ec0668284c9228c205
Reviewed-on: https://go-review.googlesource.com/c/go/+/296131
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
(cherry picked from commit bcac57f89c)
Reviewed-on: https://go-review.googlesource.com/c/go/+/297990
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2021-03-03 17:58:27 +00:00
Jordan Liggitt
2b7243a62f [release-branch.go1.16] cmd/go: add missing newline to retraction warning message
Updates #44674
Fixes #44676

Change-Id: Icbdb79084bf7bd2f52cc0a53abcc1ec6f0c4a1bf
Reviewed-on: https://go-review.googlesource.com/c/go/+/297350
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Jay Conrod <jayconrod@google.com>
(cherry picked from commit 87beecd6df)
Reviewed-on: https://go-review.googlesource.com/c/go/+/297633
Trust: Bryan C. Mills <bcmills@google.com>
2021-03-01 23:40:01 +00:00
Cherry Zhang
a9547ad8ad [release-branch.go1.16] cmd/link: handle types as converted to interface when dynlink
When using plugins, a type (whose value) may be pass to a plugin
and get converted to interface there, or vice versa. We need to
treat the type as potentially converted to interface, and retain
its methods.

Updates #44586.
Fixes #44638.

Change-Id: I80dd35e68baedaa852a317543ccd78d94628d13b
Reviewed-on: https://go-review.googlesource.com/c/go/+/296709
Trust: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
(cherry picked from commit a655208c9e)
Reviewed-on: https://go-review.googlesource.com/c/go/+/296910
2021-03-01 22:31:33 +00:00
Matthew Dempsky
292abd96ae [release-branch.go1.16] cmd/compile: fix escape analysis of heap-allocated results
One of escape analysis's responsibilities is to summarize whether/how
each function parameter flows to the heap so we can correctly
incorporate those flows into callers' escape analysis data flow
graphs.

As an optimization, we separately record when parameters flow to
result parameters, so that we can more precisely analyze parameter
flows based on how the results are used at the call site. However, if
a named result parameter itself needs to be heap allocated, this
optimization isn't safe and the parameter needs to be recorded as
flowing to heap rather than flowing to result.

Escape analysis used to get this correct because it conservatively
rewalked the data-flow graph multiple times. So even though it would
incorrectly record the result parameter flow, it would separately find
a flow to the heap. However, CL 196811 (specifically, case 3)
optimized the walking logic to reduce unnecessary rewalks causing us
to stop finding the extra heap flow.

This CL fixes the issue by correcting location.leakTo to be sensitive
to sink.escapes and not record result-flows when the result parameter
escapes to the heap.

Fixes #44659.

Change-Id: I48742ed35a6cab591094e2d23a439e205bd65c50
Reviewed-on: https://go-review.googlesource.com/c/go/+/297289
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/297290
2021-03-01 22:02:31 +00:00
Ian Lance Taylor
88f91b709e [release-branch.go1.16] time: correct unusual extension string cases
This fixes two uncommon cases.

First, the tzdata code permits timezone offsets up to 24 * 7, although
the POSIX TZ parsing does not. The tzdata code uses this to specify a
day of week in some cases.

Second, we incorrectly rejected a negative time offset for when a time
zone change comes into effect.

For #44385
Fixes #44618

Change-Id: I5f2efc1d385e9bfa974a0de3fa81e7a94b827602
Reviewed-on: https://go-review.googlesource.com/c/go/+/296392
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
(cherry picked from commit d9fd38e68b)
Reviewed-on: https://go-review.googlesource.com/c/go/+/297230
2021-03-01 21:51:11 +00:00
Jason A. Donenfeld
4fd2617cd8 [release-branch.go1.16] syscall: do not overflow key memory in GetQueuedCompletionStatus
The third argument to GetQueuedCompletionStatus is a pointer to a
uintptr, not a uint32. Users of this functions have therefore been
corrupting their memory every time they used it. Either that memory
corruption was silent (dangerous), or their programs didn't work so they
chose a different API to use.

This fixes the problem by passing through an intermediate buffer.

Updates #44538.
Fixes #44593.

Change-Id: Icacd71f705b36e41e52bd8c4d74898559a27522f
Reviewed-on: https://go-review.googlesource.com/c/go/+/296150
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
2021-03-01 21:33:08 +00:00
Bryan C. Mills
e0bd146a13 [release-branch.go1.16] cmd/go: fix version validation in 'go mod edit -exclude'
The fix is to pull in CL 295931 from the x/mod repo.

Updates #44497
Fixes #44498

Change-Id: I008b58d0f4bb48c09d4f1e6ed31d11a714f87dc0
Reviewed-on: https://go-review.googlesource.com/c/go/+/295150
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
(cherry picked from commit 691ac806d2)
Reviewed-on: https://go-review.googlesource.com/c/go/+/295930
2021-03-01 20:40:43 +00:00
Cuong Manh Le
ca9cd629fb [release-branch.go1.16] cmd/compile: fix mishandling of unsafe-uintptr arguments with call method in go/defer
In CL 253457, we did the same fix for direct function calls. But for
method calls, the receiver argument also need to be passed through the
wrapper function, which we are not doing so the compiler crashes with
the code in #44415.

It will be nicer if we can rewrite OCALLMETHOD to normal OCALLFUNC, but
that will be for future CL. The passing receiver argument to wrapper
function is easier for backporting to go1.16 branch.

Fixes #44464

Change-Id: I03607a64429042c6066ce673931db9769deb3124
Reviewed-on: https://go-review.googlesource.com/c/go/+/296490
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/296769
Trust: Bryan C. Mills <bcmills@google.com>
2021-03-01 20:38:01 +00:00
Than McIntosh
18e5d75ffb [release-branch.go1.16] cmd/compile: fix panic in DWARF-gen handling obfuscated code
DWARF generation uses variable source positions (file/line/col) as a
way to uniquely identify locals and parameters, as part of the process
of matching up post-optimization variables with the corresponding
pre-optimization versions (since the DWARF needs to be in terms of the
original source constructs).

This strategy can run into problems when compiling obfuscated or
machine-generated code, where you can in some circumstances wind up
with two local variables that appear to have the same name, file,
line, and column. This patch changes DWARF generation to skip over
such duplicates as opposed to issuing a fatal error (if an
obfuscation tool is in use, it is unlikely that a human being will be
able to make much sense of DWARF info in any case).

Fixes #44433.

Change-Id: I198022d184701aa9ec3dce42c005d29b72d2e321
Reviewed-on: https://go-review.googlesource.com/c/go/+/294289
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Trust: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
(cherry picked from commit e78e04ce39)
Reviewed-on: https://go-review.googlesource.com/c/go/+/294789
2021-03-01 20:13:56 +00:00
Matthew Dempsky
ddeae6b248 [release-branch.go1.16] cmd/compile: declare inlined result params early for empty returns
The code for delayed declaration of inlined result parameters only
handles non-empty return statements. This is generally okay, because
we already early declare if there are any (non-blank) named result
parameters.

But if a user writes a function with only blank result parameters and
with exactly one return statement, which is empty, then they could end
up hitting the dreaded "Value live at entry" ICE.

This CL fixes the issue by ensuring we always early declare inlined
result parameters if there are any empty return statements.

Fixes #44358.

Change-Id: I315f3853be436452883b1ce31da1bdffdf24d506
Reviewed-on: https://go-review.googlesource.com/c/go/+/293293
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/296569
2021-03-01 18:01:46 +00:00
Ian Lance Taylor
b7e0eb49d8 [release-branch.go1.16] syscall: add explicit ios build tag
This permits analysis of the syscall package by tools built with
older versions of Go that do not recognize ios as a GOOS.

For #44459
Fixes #44462

Change-Id: I79cec2ffe0dbcbc2dc45a385e556dc9e62033125
Reviewed-on: https://go-review.googlesource.com/c/go/+/294634
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
(cherry picked from commit 03d36d8198)
Reviewed-on: https://go-review.googlesource.com/c/go/+/294635
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2021-02-25 22:48:20 +00:00
Ian Lance Taylor
0b8c416688 [release-branch.go1.16] README: pull gopher image from website
Fixes breakage accidentally introduced by https://golang.org/cl/291711.

Fixes #44402.
Updates #44295.

Change-Id: I76f3e5577d1d24027d4ed2a725b5b749ab2d059c
Reviewed-on: https://go-review.googlesource.com/c/go/+/292629
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit 6f3da9d2f6)
Reviewed-on: https://go-review.googlesource.com/c/go/+/293843
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2021-02-25 21:27:25 +00:00
Ian Lance Taylor
1a7e9af153 [release-branch.go1.16] runtime/cgo: add cast in C code to avoid C compiler warning
For #44340
Fixes #44346

Change-Id: Id80dd1f44a988b653933732afcc8e49a826affc4
Reviewed-on: https://go-review.googlesource.com/c/go/+/293209
Reviewed-by: Andrew G. Morgan <agm@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit 07ef313525)
Reviewed-on: https://go-review.googlesource.com/c/go/+/293411
TryBot-Result: Go Bot <gobot@golang.org>
2021-02-18 03:06:52 +00:00
Alexander Rakoczy
f21be2fdc6 [release-branch.go1.16] go1.16
Change-Id: I4c1350e0cb74ebfde5832973979e02997476d16c
Reviewed-on: https://go-review.googlesource.com/c/go/+/292609
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Alexander Rakoczy <alex@golang.org>
Run-TryBot: Alexander Rakoczy <alex@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
2021-02-16 18:08:40 +00:00
Alexander Rakoczy
e34168e634 [release-branch.go1.16] all: merge master into release-branch.go1.16
1004a7cb31 runtime/metrics: update documentation to current interface
6530f2617f doc/go1.16: remove draft notice
353e111455 doc/go1.16: fix mismatched id attribute
f0d23c9dbb internal/poll: netpollcheckerr before sendfile
0cb3415154 doc: remove all docs not tied to distribution
626ef08127 doc: remove install.html and install-source.html
30641e36aa internal/poll: if copy_file_range returns 0, assume it failed
33d72fd412 doc/faq: update generics entry to reflect accepted proposal
852ce7c212 cmd/go: provide a more helpful suggestion for "go vet -?"
66c27093d0 cmd/link: fix typo in link_test.go
ff0e93ea31 doc/go1.16: note that package path elements beginning with '.' are disallowed
249da7ec02 CONTRIBUTORS: update for the Go 1.16 release
864d4f1c6b cmd/go: multiple small 'go help' fixes
26ceae85a8 spec: More precise wording in section on function calls.
930c2c9a68 cmd/go: reject embedded files that can't be packed into modules
e5b08e6d5c io/fs: allow backslash in ValidPath, reject in os.DirFS.Open
ed8079096f cmd/compile: mark concrete call of reflect.(*rtype).Method as REFLECTMETHOD
e9c9683597 cmd/go: suppress errors from 'go get -d' for packages that only conditionally exist
e0ac989cf3 archive/tar: detect out of bounds accesses in PAX records resulting from padded lengths
c9d6f45fec runtime/metrics: fix a couple of documentation typpos
cea4e21b52 io/fs: backslash is always a glob meta character
dc725bfb3c doc/go1.16: mention new vet check for asn1.Unmarshal
1901853098 runtime/metrics: fix panic in readingAllMetric example
ed3e4afa12 syscall/plan9: remove spooky fd action at a distance
724d0720b3 doc/go1.16: add missed heading tag in vet section
b54cd94d47 embed, io/fs: clarify that leading and trailing slashes are disallowed
4516afebed testing/fstest: avoid symlink-induced failures in tester
8869086d8f runtime: fix typo in histogram.go
e491c6eea9 math/big: fix comment in divRecursiveStep
fca94ab3ab spec: improve the example in Type assertions section
98f8454a73 cmd/link: don't decode type symbol in shared library in deadcode
1426a571b7 cmd/link: fix off-by-1 error in findShlibSection
32e789f4fb test: fix incorrectly laid out instructions in issue11656.go
0b6cfea634 doc/go1.16: document that on OpenBSD syscalls are now made through libc
26e29aa15a cmd/link: disable TestPIESize if CGO isn't enabled
6ac91e460c doc/go1.16: minor markup fixes
44361140c0 embed: update docs for proposal tweaks
68058edc39 runtime: document pointer write atomicity for memclrNoHeapPointers
c8bd8010ff syscall: generate readlen/writelen for openbsd libc
41bb49b878 cmd/go: revert TestScript/build_trimpath to use ioutil.ReadFile
725a642c2d runtime: correct syscall10/syscall10X on openbsd/amd64
4b068cafb5 doc/go1.16: document go/build/constraint package
376518d77f runtime,syscall: convert syscall on openbsd/arm64 to libc

Change-Id: Icfe3d849f459eda48d7d786d0cd7b082c9c2c325
2021-02-16 12:10:50 -05:00
Alexander Rakoczy
3e06467282 [release-branch.go1.16] go1.16rc1
Change-Id: I978f6df491a19a9c45ab906dbc5194b8665bf4a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/287352
Run-TryBot: Alexander Rakoczy <alex@golang.org>
Trust: Alexander Rakoczy <alex@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2021-01-27 22:19:13 +00:00
96 changed files with 1818 additions and 415 deletions

View File

@@ -3,7 +3,7 @@
Go is an open source programming language that makes it easy to build simple,
reliable, and efficient software.
![Gopher image](doc/gopher/fiveyears.jpg)
![Gopher image](https://golang.org/doc/gopher/fiveyears.jpg)
*Gopher image by [Renee French][rf], licensed under [Creative Commons 3.0 Attributions license][cc3-by].*
Our canonical Git repository is located at https://go.googlesource.com/go.

1
VERSION Normal file
View File

@@ -0,0 +1 @@
go1.16.4

View File

@@ -201,12 +201,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

@@ -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/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

@@ -628,10 +628,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 +641,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 +671,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 +680,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 +729,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 +754,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

@@ -1073,11 +1073,96 @@ 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)
}
}

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

Binary file not shown.

View File

@@ -243,7 +243,8 @@ func makePreinlineDclMap(fnsym *obj.LSym) map[varPos]int {
DeclCol: pos.Col(),
}
if _, found := m[vp]; found {
Fatalf("child dcl collision on symbol %s within %v\n", n.Sym.Name, fnsym.Name)
// We can see collisions (variables with the same name/file/line/col) in obfuscated or machine-generated code -- see issue 44378 for an example. Skip duplicates in such cases, since it is unlikely that a human will be debugging such code.
continue
}
m[vp] = i
}

View File

@@ -1376,9 +1376,10 @@ func containsClosure(f, c *Node) bool {
// leak records that parameter l leaks to sink.
func (l *EscLocation) leakTo(sink *EscLocation, derefs int) {
// If sink is a result parameter and we can fit return bits
// into the escape analysis tag, then record a return leak.
if sink.isName(PPARAMOUT) && sink.curfn == l.curfn {
// If sink is a result parameter that doesn't escape (#44614)
// and we can fit return bits into the escape analysis tag,
// then record as a result leak.
if !sink.escapes && sink.isName(PPARAMOUT) && sink.curfn == l.curfn {
// TODO(mdempsky): Eliminate dependency on Vargen here.
ri := int(sink.n.Name.Vargen) - 1
if ri < numEscResults {

View File

@@ -1053,18 +1053,26 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
}
}
// We can delay declaring+initializing result parameters if:
// (1) there's exactly one "return" statement in the inlined function;
// (2) it's not an empty return statement (#44355); and
// (3) the result parameters aren't named.
delayretvars := true
nreturns := 0
inspectList(asNodes(fn.Func.Inl.Body), func(n *Node) bool {
if n != nil && n.Op == ORETURN {
nreturns++
if n.List.Len() == 0 {
delayretvars = false // empty return statement (case 2)
}
}
return true
})
// We can delay declaring+initializing result parameters if:
// (1) there's only one "return" statement in the inlined
// function, and (2) the result parameters aren't named.
delayretvars := nreturns == 1
if nreturns != 1 {
delayretvars = false // not exactly one return statement (case 1)
}
// temporaries for return values.
var retvars []*Node
@@ -1074,7 +1082,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
m = inlvar(n)
m = typecheck(m, ctxExpr)
inlvars[n] = m
delayretvars = false // found a named result parameter
delayretvars = false // found a named result parameter (case 3)
} else {
// anonymous return values, synthesize names for use in assignment that replaces return
m = retvar(t, i)

View File

@@ -363,15 +363,15 @@ func staticname(t *types.Type) *Node {
n := newname(lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen)))
statuniqgen++
addvar(n, t, PEXTERN)
n.Sym.Linksym().Set(obj.AttrLocal, true)
return n
}
// readonlystaticname returns a name backed by a (writable) static data symbol.
// readonlystaticname returns a name backed by a read-only static data symbol.
func readonlystaticname(t *types.Type) *Node {
n := staticname(t)
n.MarkReadonly()
n.Sym.Linksym().Set(obj.AttrContentAddressable, true)
n.Sym.Linksym().Set(obj.AttrLocal, true)
return n
}

View File

@@ -3927,15 +3927,22 @@ func wrapCall(n *Node, init *Nodes) *Node {
}
}
wrapArgs := n.List.Slice()
// If there's a receiver argument, it needs to be passed through the wrapper too.
if n.Op == OCALLMETH || n.Op == OCALLINTER {
recv := n.Left.Left
wrapArgs = append([]*Node{recv}, wrapArgs...)
}
// origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion.
origArgs := make([]*Node, n.List.Len())
origArgs := make([]*Node, len(wrapArgs))
t := nod(OTFUNC, nil, nil)
for i, arg := range n.List.Slice() {
for i, arg := range wrapArgs {
s := lookupN("a", i)
if !isBuiltinCall && arg.Op == OCONVNOP && arg.Type.IsUintptr() && arg.Left.Type.IsUnsafePtr() {
origArgs[i] = arg
arg = arg.Left
n.List.SetIndex(i, arg)
wrapArgs[i] = arg
}
t.List.Append(symfield(s, arg.Type))
}
@@ -3953,6 +3960,12 @@ func wrapCall(n *Node, init *Nodes) *Node {
arg.Type = origArg.Type
args[i] = arg
}
if n.Op == OCALLMETH || n.Op == OCALLINTER {
// Move wrapped receiver argument back to its appropriate place.
recv := typecheck(args[0], ctxExpr)
n.Left.Left = recv
args = args[1:]
}
call := nod(n.Op, nil, nil)
if !isBuiltinCall {
call.Op = OCALL
@@ -3970,7 +3983,7 @@ func wrapCall(n *Node, init *Nodes) *Node {
call = nod(OCALL, nil, nil)
call.Left = fn.Func.Nname
call.List.Set(n.List.Slice())
call.List.Set(wrapArgs)
call = typecheck(call, ctxStmt)
call = walkexpr(call, init)
return call

View File

@@ -623,6 +623,14 @@
// Recognize bit setting (a |= 1<<b) and toggling (a ^= 1<<b)
(OR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) => (BTS(Q|L) x y)
(XOR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) => (BTC(Q|L) x y)
(ORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem) =>
(BTSLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
(ORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem) =>
(BTSQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
(XORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem) =>
(BTCLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
(XORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem) =>
(BTCQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
// Convert ORconst into BTS, if the code gets smaller, with boundary being
// (ORL $40,AX is 3 bytes, ORL $80,AX is 6 bytes).
@@ -645,6 +653,10 @@
=> (BTRQconst [int8(log64(^c))] x)
(ANDL (MOVLconst [c]) x) && isUint32PowerOfTwo(int64(^c)) && uint64(^c) >= 128
=> (BTRLconst [int8(log32(^c))] x)
(ANDLmodify [off] {sym} ptr (NOTL s:(SHLL (MOVLconst [1]) <t> x)) mem) =>
(BTRLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
(ANDQmodify [off] {sym} ptr (NOTQ s:(SHLQ (MOVQconst [1]) <t> x)) mem) =>
(BTRQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
// Special-case bit patterns on first/last bit.
// generic.rules changes ANDs of high-part/low-part masks into a couple of shifts,
@@ -2050,11 +2062,15 @@
((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem)
((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem)
(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) => ((ADD|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off] {sym} ptr x mem)
(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
((ADD|SUB|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
(MOVLstore {sym} [off] ptr y:((BTC|BTR|BTS)L l:(MOVLload [off] {sym} ptr mem) <t> x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
((BTC|BTR|BTS)Lmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
(MOVQstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Qload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) => ((ADD|AND|OR|XOR)Qmodify [off] {sym} ptr x mem)
(MOVQstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Q l:(MOVQload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off] {sym} ptr x mem)
(MOVQstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)Q l:(MOVQload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
((ADD|SUB|AND|OR|XOR)Qmodify [off] {sym} ptr x mem)
(MOVQstore {sym} [off] ptr y:((BTC|BTR|BTS)Q l:(MOVQload [off] {sym} ptr mem) <t> x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) =>
((BTC|BTR|BTS)Qmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
// Merge ADDQconst and LEAQ into atomic loads.
(MOV(Q|L|B)atomicload [off1] {sym} (ADDQconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) =>

View File

@@ -358,6 +358,11 @@ func init() {
{name: "BTSQconst", argLength: 1, reg: gp11, asm: "BTSQ", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // set bit auxint in arg0, 0 <= auxint < 64
// direct bit operation on memory operand
//
// Note that these operations do not mask the bit offset (arg1), and will write beyond their expected
// bounds if that argument is larger than 64/32 (for BT*Q and BT*L, respectively). If the compiler
// cannot prove that arg1 is in range, it must be explicitly masked (see e.g. the patterns that produce
// BT*modify from (MOVstore (BT* (MOVLload ptr mem) x) mem)).
{name: "BTCQmodify", argLength: 3, reg: gpstore, asm: "BTCQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit arg1 in 64-bit arg0+auxint+aux, arg2=mem
{name: "BTCLmodify", argLength: 3, reg: gpstore, asm: "BTCL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit arg1 in 32-bit arg0+auxint+aux, arg2=mem
{name: "BTSQmodify", argLength: 3, reg: gpstore, asm: "BTSQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // set bit arg1 in 64-bit arg0+auxint+aux, arg2=mem

View File

@@ -1469,7 +1469,7 @@ func mergePPC64AndSrwi(m, s int64) int64 {
if !isPPC64WordRotateMask(mask) {
return 0
}
return encodePPC64RotateMask(32-s, mask, 32)
return encodePPC64RotateMask((32-s)&31, mask, 32)
}
// Test if a shift right feeding into a CLRLSLDI can be merged into RLWINM.

View File

@@ -2998,6 +2998,36 @@ func rewriteValueAMD64_OpAMD64ANDLmodify(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (ANDLmodify [off] {sym} ptr (NOTL s:(SHLL (MOVLconst [1]) <t> x)) mem)
// result: (BTRLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
ptr := v_0
if v_1.Op != OpAMD64NOTL {
break
}
s := v_1.Args[0]
if s.Op != OpAMD64SHLL {
break
}
t := s.Type
x := s.Args[1]
s_0 := s.Args[0]
if s_0.Op != OpAMD64MOVLconst || auxIntToInt32(s_0.AuxInt) != 1 {
break
}
mem := v_2
v.reset(OpAMD64BTRLmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v0 := b.NewValue0(v.Pos, OpAMD64ANDLconst, t)
v0.AuxInt = int32ToAuxInt(31)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (ANDLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
// cond: is32Bit(int64(off1)+int64(off2))
// result: (ANDLmodify [off1+off2] {sym} base val mem)
@@ -3377,6 +3407,36 @@ func rewriteValueAMD64_OpAMD64ANDQmodify(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (ANDQmodify [off] {sym} ptr (NOTQ s:(SHLQ (MOVQconst [1]) <t> x)) mem)
// result: (BTRQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
ptr := v_0
if v_1.Op != OpAMD64NOTQ {
break
}
s := v_1.Args[0]
if s.Op != OpAMD64SHLQ {
break
}
t := s.Type
x := s.Args[1]
s_0 := s.Args[0]
if s_0.Op != OpAMD64MOVQconst || auxIntToInt64(s_0.AuxInt) != 1 {
break
}
mem := v_2
v.reset(OpAMD64BTRQmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v0 := b.NewValue0(v.Pos, OpAMD64ANDQconst, t)
v0.AuxInt = int32ToAuxInt(63)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (ANDQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
// cond: is32Bit(int64(off1)+int64(off2))
// result: (ANDQmodify [off1+off2] {sym} base val mem)
@@ -12709,9 +12769,9 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool {
}
break
}
// match: (MOVLstore {sym} [off] ptr y:(BTCL l:(MOVLload [off] {sym} ptr mem) x) mem)
// match: (MOVLstore {sym} [off] ptr y:(BTCL l:(MOVLload [off] {sym} ptr mem) <t> x) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
// result: (BTCLmodify [off] {sym} ptr x mem)
// result: (BTCLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
@@ -12720,6 +12780,7 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool {
if y.Op != OpAMD64BTCL {
break
}
t := y.Type
x := y.Args[1]
l := y.Args[0]
if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
@@ -12732,12 +12793,15 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool {
v.reset(OpAMD64BTCLmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
v0 := b.NewValue0(l.Pos, OpAMD64ANDLconst, t)
v0.AuxInt = int32ToAuxInt(31)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (MOVLstore {sym} [off] ptr y:(BTRL l:(MOVLload [off] {sym} ptr mem) x) mem)
// match: (MOVLstore {sym} [off] ptr y:(BTRL l:(MOVLload [off] {sym} ptr mem) <t> x) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
// result: (BTRLmodify [off] {sym} ptr x mem)
// result: (BTRLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
@@ -12746,6 +12810,7 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool {
if y.Op != OpAMD64BTRL {
break
}
t := y.Type
x := y.Args[1]
l := y.Args[0]
if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
@@ -12758,12 +12823,15 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool {
v.reset(OpAMD64BTRLmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
v0 := b.NewValue0(l.Pos, OpAMD64ANDLconst, t)
v0.AuxInt = int32ToAuxInt(31)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (MOVLstore {sym} [off] ptr y:(BTSL l:(MOVLload [off] {sym} ptr mem) x) mem)
// match: (MOVLstore {sym} [off] ptr y:(BTSL l:(MOVLload [off] {sym} ptr mem) <t> x) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
// result: (BTSLmodify [off] {sym} ptr x mem)
// result: (BTSLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
@@ -12772,6 +12840,7 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool {
if y.Op != OpAMD64BTSL {
break
}
t := y.Type
x := y.Args[1]
l := y.Args[0]
if l.Op != OpAMD64MOVLload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
@@ -12784,7 +12853,10 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool {
v.reset(OpAMD64BTSLmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
v0 := b.NewValue0(l.Pos, OpAMD64ANDLconst, t)
v0.AuxInt = int32ToAuxInt(31)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (MOVLstore [off] {sym} ptr a:(ADDLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
@@ -13525,6 +13597,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (MOVQstore [off1] {sym} (ADDQconst [off2] ptr) val mem)
// cond: is32Bit(int64(off1)+int64(off2))
// result: (MOVQstore [off1+off2] {sym} ptr val mem)
@@ -13890,9 +13963,9 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool {
}
break
}
// match: (MOVQstore {sym} [off] ptr y:(BTCQ l:(MOVQload [off] {sym} ptr mem) x) mem)
// match: (MOVQstore {sym} [off] ptr y:(BTCQ l:(MOVQload [off] {sym} ptr mem) <t> x) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
// result: (BTCQmodify [off] {sym} ptr x mem)
// result: (BTCQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
@@ -13901,6 +13974,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool {
if y.Op != OpAMD64BTCQ {
break
}
t := y.Type
x := y.Args[1]
l := y.Args[0]
if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
@@ -13913,12 +13987,15 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool {
v.reset(OpAMD64BTCQmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
v0 := b.NewValue0(l.Pos, OpAMD64ANDQconst, t)
v0.AuxInt = int32ToAuxInt(63)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (MOVQstore {sym} [off] ptr y:(BTRQ l:(MOVQload [off] {sym} ptr mem) x) mem)
// match: (MOVQstore {sym} [off] ptr y:(BTRQ l:(MOVQload [off] {sym} ptr mem) <t> x) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
// result: (BTRQmodify [off] {sym} ptr x mem)
// result: (BTRQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
@@ -13927,6 +14004,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool {
if y.Op != OpAMD64BTRQ {
break
}
t := y.Type
x := y.Args[1]
l := y.Args[0]
if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
@@ -13939,12 +14017,15 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool {
v.reset(OpAMD64BTRQmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
v0 := b.NewValue0(l.Pos, OpAMD64ANDQconst, t)
v0.AuxInt = int32ToAuxInt(63)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (MOVQstore {sym} [off] ptr y:(BTSQ l:(MOVQload [off] {sym} ptr mem) x) mem)
// match: (MOVQstore {sym} [off] ptr y:(BTSQ l:(MOVQload [off] {sym} ptr mem) <t> x) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y, l)
// result: (BTSQmodify [off] {sym} ptr x mem)
// result: (BTSQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
@@ -13953,6 +14034,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool {
if y.Op != OpAMD64BTSQ {
break
}
t := y.Type
x := y.Args[1]
l := y.Args[0]
if l.Op != OpAMD64MOVQload || auxIntToInt32(l.AuxInt) != off || auxToSym(l.Aux) != sym {
@@ -13965,7 +14047,10 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool {
v.reset(OpAMD64BTSQmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v.AddArg3(ptr, x, mem)
v0 := b.NewValue0(l.Pos, OpAMD64ANDQconst, t)
v0.AuxInt = int32ToAuxInt(63)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (MOVQstore [off] {sym} ptr a:(ADDQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
@@ -18352,6 +18437,33 @@ func rewriteValueAMD64_OpAMD64ORLmodify(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (ORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem)
// result: (BTSLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
ptr := v_0
s := v_1
if s.Op != OpAMD64SHLL {
break
}
t := s.Type
x := s.Args[1]
s_0 := s.Args[0]
if s_0.Op != OpAMD64MOVLconst || auxIntToInt32(s_0.AuxInt) != 1 {
break
}
mem := v_2
v.reset(OpAMD64BTSLmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v0 := b.NewValue0(v.Pos, OpAMD64ANDLconst, t)
v0.AuxInt = int32ToAuxInt(31)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (ORLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
// cond: is32Bit(int64(off1)+int64(off2))
// result: (ORLmodify [off1+off2] {sym} base val mem)
@@ -19979,6 +20091,33 @@ func rewriteValueAMD64_OpAMD64ORQmodify(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (ORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem)
// result: (BTSQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
ptr := v_0
s := v_1
if s.Op != OpAMD64SHLQ {
break
}
t := s.Type
x := s.Args[1]
s_0 := s.Args[0]
if s_0.Op != OpAMD64MOVQconst || auxIntToInt64(s_0.AuxInt) != 1 {
break
}
mem := v_2
v.reset(OpAMD64BTSQmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v0 := b.NewValue0(v.Pos, OpAMD64ANDQconst, t)
v0.AuxInt = int32ToAuxInt(63)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (ORQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
// cond: is32Bit(int64(off1)+int64(off2))
// result: (ORQmodify [off1+off2] {sym} base val mem)
@@ -28014,6 +28153,33 @@ func rewriteValueAMD64_OpAMD64XORLmodify(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (XORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem)
// result: (BTCLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
ptr := v_0
s := v_1
if s.Op != OpAMD64SHLL {
break
}
t := s.Type
x := s.Args[1]
s_0 := s.Args[0]
if s_0.Op != OpAMD64MOVLconst || auxIntToInt32(s_0.AuxInt) != 1 {
break
}
mem := v_2
v.reset(OpAMD64BTCLmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v0 := b.NewValue0(v.Pos, OpAMD64ANDLconst, t)
v0.AuxInt = int32ToAuxInt(31)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (XORLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
// cond: is32Bit(int64(off1)+int64(off2))
// result: (XORLmodify [off1+off2] {sym} base val mem)
@@ -28382,6 +28548,33 @@ func rewriteValueAMD64_OpAMD64XORQmodify(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (XORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem)
// result: (BTCQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem)
for {
off := auxIntToInt32(v.AuxInt)
sym := auxToSym(v.Aux)
ptr := v_0
s := v_1
if s.Op != OpAMD64SHLQ {
break
}
t := s.Type
x := s.Args[1]
s_0 := s.Args[0]
if s_0.Op != OpAMD64MOVQconst || auxIntToInt64(s_0.AuxInt) != 1 {
break
}
mem := v_2
v.reset(OpAMD64BTCQmodify)
v.AuxInt = int32ToAuxInt(off)
v.Aux = symToAux(sym)
v0 := b.NewValue0(v.Pos, OpAMD64ANDQconst, t)
v0.AuxInt = int32ToAuxInt(63)
v0.AddArg(x)
v.AddArg3(ptr, v0, mem)
return true
}
// match: (XORQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
// cond: is32Bit(int64(off1)+int64(off2))
// result: (XORQmodify [off1+off2] {sym} base val mem)

View File

@@ -205,6 +205,7 @@ func TestMergePPC64AndSrwi(t *testing.T) {
{0x00000000, 4, false, 0, 0},
{0xF0000000, 4, false, 0, 0},
{0xF0000000, 32, false, 0, 0},
{0xFFFFFFFF, 0, true, 0, 0xFFFFFFFF},
}
for i, v := range tests {
result := mergePPC64AndSrwi(v.and, v.srw)

View File

@@ -138,6 +138,24 @@ func shortcircuitBlock(b *Block) bool {
if len(b.Values) != nval+nOtherPhi {
return false
}
if nOtherPhi > 0 {
// Check for any phi which is the argument of another phi.
// These cases are tricky, as substitutions done by replaceUses
// are no longer trivial to do in any ordering. See issue 45175.
m := make(map[*Value]bool, 1+nOtherPhi)
for _, v := range b.Values {
if v.Op == OpPhi {
m[v] = true
}
}
for v := range m {
for _, a := range v.Args {
if a != v && m[a] {
return false
}
}
}
}
// Locate index of first const phi arg.
cidx := -1

View File

@@ -6,7 +6,7 @@ require (
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/mod v0.4.1
golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff
)

View File

@@ -14,8 +14,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea h1:zAn46O7Vmm6KdLXx+635hPZSArrt/wNctv4Ab70Jw3k=
golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=

View File

@@ -692,18 +692,22 @@
// arguments must satisfy the following constraints:
//
// - Arguments must be package paths or package patterns (with "..." wildcards).
// They must not be standard packages (like fmt), meta-patterns (std, cmd,
// all), or relative or absolute file paths.
// They must not be standard packages (like fmt), meta-patterns (std, cmd,
// all), or relative or absolute file paths.
//
// - All arguments must have the same version suffix. Different queries are not
// allowed, even if they refer to the same version.
// allowed, even if they refer to the same version.
//
// - All arguments must refer to packages in the same module at the same version.
//
// - No module is considered the "main" module. If the module containing
// packages named on the command line has a go.mod file, it must not contain
// directives (replace and exclude) that would cause it to be interpreted
// differently than if it were the main module. The module must not require
// a higher version of itself.
// packages named on the command line has a go.mod file, it must not contain
// directives (replace and exclude) that would cause it to be interpreted
// differently than if it were the main module. The module must not require
// a higher version of itself.
//
// - Package path arguments must refer to main packages. Pattern arguments
// will only match main packages.
// will only match main packages.
//
// If the arguments don't have version suffixes, "go install" may run in
// module-aware mode or GOPATH mode, depending on the GO111MODULE environment

View File

@@ -431,7 +431,7 @@ func downloadPackage(p *load.Package) error {
}
importPrefix = importPrefix[:slash]
}
if err := module.CheckImportPath(importPrefix); err != nil {
if err := checkImportPath(importPrefix); err != nil {
return fmt.Errorf("%s: invalid import path: %v", p.ImportPath, err)
}
security := web.SecureOnly
@@ -591,3 +591,31 @@ func selectTag(goVersion string, tags []string) (match string) {
}
return ""
}
// checkImportPath is like module.CheckImportPath, but it forbids leading dots
// in path elements. This can lead to 'go get' creating .git and other VCS
// directories in places we might run VCS tools later.
func checkImportPath(path string) error {
if err := module.CheckImportPath(path); err != nil {
return err
}
checkElem := func(elem string) error {
if elem[0] == '.' {
return fmt.Errorf("malformed import path %q: leading dot in path element", path)
}
return nil
}
elemStart := 0
for i, r := range path {
if r == '/' {
if err := checkElem(path[elemStart:]); err != nil {
return err
}
elemStart = i + 1
}
}
if err := checkElem(path[elemStart:]); err != nil {
return err
}
return nil
}

View File

@@ -62,10 +62,11 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) {
modload.RootMode = modload.NeedRoot
modload.LoadPackages(ctx, modload.PackageOpts{
Tags: imports.AnyTags(),
ResolveMissingImports: true,
LoadTests: true,
AllowErrors: tidyE,
Tags: imports.AnyTags(),
ResolveMissingImports: true,
LoadTests: true,
AllowErrors: tidyE,
SilenceMissingStdImports: true,
}, "all")
modload.TidyBuildList()

View File

@@ -64,10 +64,11 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) {
modload.RootMode = modload.NeedRoot
loadOpts := modload.PackageOpts{
Tags: imports.AnyTags(),
ResolveMissingImports: true,
UseVendorAll: true,
AllowErrors: vendorE,
Tags: imports.AnyTags(),
ResolveMissingImports: true,
UseVendorAll: true,
AllowErrors: vendorE,
SilenceMissingStdImports: true,
}
_, pkgs := modload.LoadPackages(ctx, loadOpts, "all")

View File

@@ -84,6 +84,7 @@ func DownloadDir(m module.Version) (string, error) {
return "", err
}
// Check whether the directory itself exists.
dir := filepath.Join(cfg.GOMODCACHE, enc+"@"+encVer)
if fi, err := os.Stat(dir); os.IsNotExist(err) {
return dir, err
@@ -92,6 +93,9 @@ func DownloadDir(m module.Version) (string, error) {
} else if !fi.IsDir() {
return dir, &DownloadDirPartialError{dir, errors.New("not a directory")}
}
// Check if a .partial file exists. This is created at the beginning of
// a download and removed after the zip is extracted.
partialPath, err := CachePath(m, "partial")
if err != nil {
return dir, err
@@ -101,6 +105,19 @@ func DownloadDir(m module.Version) (string, error) {
} else if !os.IsNotExist(err) {
return dir, err
}
// Check if a .ziphash file exists. It should be created before the
// zip is extracted, but if it was deleted (by another program?), we need
// to re-calculate it.
ziphashPath, err := CachePath(m, "ziphash")
if err != nil {
return dir, err
}
if _, err := os.Stat(ziphashPath); os.IsNotExist(err) {
return dir, &DownloadDirPartialError{dir, errors.New("ziphash file is missing")}
} else if err != nil {
return dir, err
}
return dir, nil
}

View File

@@ -170,13 +170,16 @@ func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err e
if err != nil {
return cached{"", err}
}
ziphashfile := zipfile + "hash"
// Skip locking if the zipfile already exists.
// Return without locking if the zip and ziphash files exist.
if _, err := os.Stat(zipfile); err == nil {
return cached{zipfile, nil}
if _, err := os.Stat(ziphashfile); err == nil {
return cached{zipfile, nil}
}
}
// The zip file does not exist. Acquire the lock and create it.
// The zip or ziphash file does not exist. Acquire the lock and create them.
if cfg.CmdName != "mod download" {
fmt.Fprintf(os.Stderr, "go: downloading %s %s\n", mod.Path, mod.Version)
}
@@ -186,14 +189,6 @@ func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err e
}
defer unlock()
// Double-check that the zipfile was not created while we were waiting for
// the lock.
if _, err := os.Stat(zipfile); err == nil {
return cached{zipfile, nil}
}
if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil {
return cached{"", err}
}
if err := downloadZip(ctx, mod, zipfile); err != nil {
return cached{"", err}
}
@@ -206,6 +201,25 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
ctx, span := trace.StartSpan(ctx, "modfetch.downloadZip "+zipfile)
defer span.Done()
// Double-check that the zipfile was not created while we were waiting for
// the lock in DownloadZip.
ziphashfile := zipfile + "hash"
var zipExists, ziphashExists bool
if _, err := os.Stat(zipfile); err == nil {
zipExists = true
}
if _, err := os.Stat(ziphashfile); err == nil {
ziphashExists = true
}
if zipExists && ziphashExists {
return nil
}
// Create parent directories.
if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil {
return err
}
// Clean up any remaining tempfiles from previous runs.
// This is only safe to do because the lock file ensures that their
// writers are no longer active.
@@ -217,6 +231,12 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
}
}
// If the zip file exists, the ziphash file must have been deleted
// or lost after a file system crash. Re-hash the zip without downloading.
if zipExists {
return hashZip(mod, zipfile, ziphashfile)
}
// From here to the os.Rename call below is functionally almost equivalent to
// renameio.WriteToFile, with one key difference: we want to validate the
// contents of the file (by hashing it) before we commit it. Because the file
@@ -289,15 +309,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
}
// Hash the zip file and check the sum before renaming to the final location.
hash, err := dirhash.HashZip(f.Name(), dirhash.DefaultHash)
if err != nil {
return err
}
if err := checkModSum(mod, hash); err != nil {
return err
}
if err := renameio.WriteFile(zipfile+"hash", []byte(hash), 0666); err != nil {
if err := hashZip(mod, f.Name(), ziphashfile); err != nil {
return err
}
if err := os.Rename(f.Name(), zipfile); err != nil {
@@ -309,6 +321,22 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
return nil
}
// hashZip reads the zip file opened in f, then writes the hash to ziphashfile,
// overwriting that file if it exists.
//
// If the hash does not match go.sum (or the sumdb if enabled), hashZip returns
// an error and does not write ziphashfile.
func hashZip(mod module.Version, zipfile, ziphashfile string) error {
hash, err := dirhash.HashZip(zipfile, dirhash.DefaultHash)
if err != nil {
return err
}
if err := checkModSum(mod, hash); err != nil {
return err
}
return renameio.WriteFile(ziphashfile, []byte(hash), 0666)
}
// makeDirsReadOnly makes a best-effort attempt to remove write permissions for dir
// and its transitive contents.
func makeDirsReadOnly(dir string) {
@@ -452,11 +480,6 @@ func HaveSum(mod module.Version) bool {
// checkMod checks the given module's checksum.
func checkMod(mod module.Version) {
if cfg.GOMODCACHE == "" {
// Do not use current directory.
return
}
// Do the file I/O before acquiring the go.sum lock.
ziphash, err := CachePath(mod, "ziphash")
if err != nil {
@@ -464,10 +487,6 @@ func checkMod(mod module.Version) {
}
data, err := renameio.ReadFile(ziphash)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// This can happen if someone does rm -rf GOPATH/src/cache/download. So it goes.
return
}
base.Fatalf("verifying %v", module.VersionError(mod, err))
}
h := strings.TrimSpace(string(data))

View File

@@ -1514,7 +1514,7 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns
}
}
if retractPath != "" {
fmt.Fprintf(os.Stderr, "go: to switch to the latest unretracted version, run:\n\tgo get %s@latest", retractPath)
fmt.Fprintf(os.Stderr, "go: to switch to the latest unretracted version, run:\n\tgo get %s@latest\n", retractPath)
}
}

View File

@@ -186,7 +186,7 @@ func (q *query) validate() error {
if q.pattern == "all" {
// If there is no main module, "all" is not meaningful.
if !modload.HasModRoot() {
return fmt.Errorf(`cannot match "all": working directory is not part of a module`)
return fmt.Errorf(`cannot match "all": %v`, modload.ErrNoModRoot)
}
if !versionOkForMainModule(q.version) {
// TODO(bcmills): "all@none" seems like a totally reasonable way to

View File

@@ -51,7 +51,7 @@ func (e *ImportMissingError) Error() string {
if e.isStd {
return fmt.Sprintf("package %s is not in GOROOT (%s)", e.Path, filepath.Join(cfg.GOROOT, "src", e.Path))
}
if e.QueryErr != nil {
if e.QueryErr != nil && e.QueryErr != ErrNoModRoot {
return fmt.Sprintf("cannot find module providing package %s: %v", e.Path, e.QueryErr)
}
if cfg.BuildMod == "mod" || (cfg.BuildMod == "readonly" && allowMissingModuleImports) {
@@ -66,13 +66,11 @@ func (e *ImportMissingError) Error() string {
return fmt.Sprintf("module %s provides package %s and is replaced but not required; to add it:\n\tgo get %s", e.replaced.Path, e.Path, suggestArg)
}
suggestion := ""
if !HasModRoot() {
suggestion = ": working directory is not part of a module"
} else {
suggestion = fmt.Sprintf("; to add it:\n\tgo get %s", e.Path)
message := fmt.Sprintf("no required module provides package %s", e.Path)
if e.QueryErr != nil {
return fmt.Sprintf("%s: %v", message, e.QueryErr)
}
return fmt.Sprintf("no required module provides package %s%s", e.Path, suggestion)
return fmt.Sprintf("%s; to add it:\n\tgo get %s", message, e.Path)
}
if e.newMissingVersion != "" {
@@ -318,7 +316,11 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
return mods[0], dirs[0], nil
}
return module.Version{}, "", &ImportMissingError{Path: path, isStd: pathIsStd}
var queryErr error
if !HasModRoot() {
queryErr = ErrNoModRoot
}
return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd}
}
// queryImport attempts to locate a module that can be added to the current

View File

@@ -177,7 +177,7 @@ func Init() {
base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.")
}
if RootMode == NeedRoot {
base.Fatalf("go: cannot find main module; see 'go help modules'")
base.Fatalf("go: %v", ErrNoModRoot)
}
if !mustUseModules {
// GO111MODULE is 'auto', and we can't find a module root.
@@ -338,9 +338,11 @@ func die() {
}
base.Fatalf("go: cannot find main module, but found %s in %s\n\tto create a module there, run:\n\t%sgo mod init", name, dir, cdCmd)
}
base.Fatalf("go: cannot find main module; see 'go help modules'")
base.Fatalf("go: %v", ErrNoModRoot)
}
var ErrNoModRoot = errors.New("go.mod file not found in current directory or any parent directory; see 'go help modules'")
// LoadModFile sets Target and, if there is a main module, parses the initial
// build list from its go.mod file.
//
@@ -539,9 +541,10 @@ func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer {
}
}
if vers != "" && module.CanonicalVersion(vers) == vers {
if err := module.CheckPathMajor(vers, pathMajor); err == nil {
return vers, nil
if err := module.CheckPathMajor(vers, pathMajor); err != nil {
return "", module.VersionError(module.Version{Path: path, Version: vers}, err)
}
return vers, nil
}
info, err := Query(ctx, path, vers, "", nil)

View File

@@ -73,7 +73,7 @@ func listModules(ctx context.Context, args []string, listVersions, listRetracted
base.Fatalf("go: cannot use relative path %s to specify module", arg)
}
if !HasModRoot() && (arg == "all" || strings.Contains(arg, "...")) {
base.Fatalf("go: cannot match %q: working directory is not part of a module", arg)
base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
}
if i := strings.Index(arg, "@"); i >= 0 {
path := arg[:i]

View File

@@ -170,6 +170,12 @@ type PackageOpts struct {
// that occur while loading packages. SilenceErrors implies AllowErrors.
SilenceErrors bool
// SilenceMissingStdImports indicates that LoadPackages should not print
// errors or terminate the process if an imported package is missing, and the
// import path looks like it might be in the standard library (perhaps in a
// future version).
SilenceMissingStdImports bool
// SilenceUnmatchedWarnings suppresses the warnings normally emitted for
// patterns that did not match any packages.
SilenceUnmatchedWarnings bool
@@ -287,8 +293,13 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
sumErr.importerIsTest = importer.testOf != nil
}
}
silence := opts.SilenceErrors
if stdErr := (*ImportMissingError)(nil); errors.As(pkg.err, &stdErr) &&
stdErr.isStd && opts.SilenceMissingStdImports {
silence = true
}
if !opts.SilenceErrors {
if !silence {
if opts.AllowErrors {
fmt.Fprintf(os.Stderr, "%s: %v\n", pkg.stackText(), pkg.err)
} else {

View File

@@ -96,28 +96,12 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
base.Fatalf("go run: no go files listed")
}
cmdArgs := args[i:]
if p.Error != nil {
base.Fatalf("%s", p.Error)
}
load.CheckPackageErrors([]*load.Package{p})
p.Internal.OmitDebug = true
if len(p.DepsErrors) > 0 {
// Since these are errors in dependencies,
// the same error might show up multiple times,
// once in each package that depends on it.
// Only print each once.
printed := map[*load.PackageError]bool{}
for _, err := range p.DepsErrors {
if !printed[err] {
printed[err] = true
base.Errorf("%s", err)
}
}
}
base.ExitIfErrors()
if p.Name != "main" {
base.Fatalf("go run: cannot run non-main package")
}
p.Internal.OmitDebug = true
p.Target = "" // must build - not up to date
if p.Internal.CmdlineFiles {
//set executable name if go file is given as cmd-argument

View File

@@ -482,18 +482,22 @@ To eliminate ambiguity about which module versions are used in the build, the
arguments must satisfy the following constraints:
- Arguments must be package paths or package patterns (with "..." wildcards).
They must not be standard packages (like fmt), meta-patterns (std, cmd,
all), or relative or absolute file paths.
They must not be standard packages (like fmt), meta-patterns (std, cmd,
all), or relative or absolute file paths.
- All arguments must have the same version suffix. Different queries are not
allowed, even if they refer to the same version.
allowed, even if they refer to the same version.
- All arguments must refer to packages in the same module at the same version.
- No module is considered the "main" module. If the module containing
packages named on the command line has a go.mod file, it must not contain
directives (replace and exclude) that would cause it to be interpreted
differently than if it were the main module. The module must not require
a higher version of itself.
packages named on the command line has a go.mod file, it must not contain
directives (replace and exclude) that would cause it to be interpreted
differently than if it were the main module. The module must not require
a higher version of itself.
- Package path arguments must refer to main packages. Pattern arguments
will only match main packages.
will only match main packages.
If the arguments don't have version suffixes, "go install" may run in
module-aware mode or GOPATH mode, depending on the GO111MODULE environment

View File

@@ -18,7 +18,7 @@ stdout '^m$'
# Test that we ignore directories when trying to find alternate config files.
cd $WORK/gopkgdir/x
! go list .
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
! stderr 'Gopkg.lock'
-- $WORK/test/Gopkg.lock --

View File

@@ -16,9 +16,9 @@ cmpenv go.mod $WORK/go.mod.init
cmpenv go.mod $WORK/go.mod.init
# go mod edits
go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' -retract=v1.6.0 -retract=[v1.1.0,v1.2.0] -retract=[v1.3.0,v1.4.0] -retract=v1.0.0
go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -exclude=x.1@v2.0.0+incompatible -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' -retract=v1.6.0 -retract=[v1.1.0,v1.2.0] -retract=[v1.3.0,v1.4.0] -retract=v1.0.0
cmpenv go.mod $WORK/go.mod.edit1
go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0 -dropretract=v1.0.0 -dropretract=[v1.1.0,v1.2.0]
go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropexclude=x.1@v2.0.0+incompatible -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0 -dropretract=v1.0.0 -dropretract=[v1.1.0,v1.2.0]
cmpenv go.mod $WORK/go.mod.edit2
# -exclude and -retract reject invalid versions.
@@ -27,6 +27,17 @@ stderr '^go mod: -exclude=example.com/m@bad: version "bad" invalid: must be of t
! go mod edit -retract=bad
stderr '^go mod: -retract=bad: version "bad" invalid: must be of the form v1.2.3$'
! go mod edit -exclude=example.com/m@v2.0.0
stderr '^go mod: -exclude=example.com/m@v2\.0\.0: version "v2\.0\.0" invalid: should be v2\.0\.0\+incompatible \(or module example\.com/m/v2\)$'
! go mod edit -exclude=example.com/m/v2@v1.0.0
stderr '^go mod: -exclude=example.com/m/v2@v1\.0\.0: version "v1\.0\.0" invalid: should be v2, not v1$'
! go mod edit -exclude=gopkg.in/example.v1@v2.0.0
stderr '^go mod: -exclude=gopkg\.in/example\.v1@v2\.0\.0: version "v2\.0\.0" invalid: should be v1, not v2$'
cmpenv go.mod $WORK/go.mod.edit2
# go mod edit -json
go mod edit -json
cmpenv stdout $WORK/go.mod.json
@@ -88,6 +99,7 @@ require x.1 v1.0.0
exclude (
x.1 v1.2.0
x.1 v1.2.1
x.1 v2.0.0+incompatible
)
replace (

View File

@@ -49,7 +49,7 @@ rm go.mod
# Test that we ignore directories when trying to find go.mod.
cd $WORK/gomoddir
! go list .
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
[!symlink] stop

View File

@@ -0,0 +1,55 @@
# Test that if the module cache contains an extracted source directory but not
# a ziphash, 'go build' complains about a missing sum, and 'go get' adds
# the sum. Verifies #44749.
# With a tidy go.sum, go build succeeds. This also populates the module cache.
cp go.sum.tidy go.sum
go build -n use
env GOPROXY=off
env GOSUMDB=off
# Control case: if we delete the hash for rsc.io/quote v1.5.2,
# 'go build' reports an error. 'go get' adds the sum.
cp go.sum.bug go.sum
! go build -n use
stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$'
go get -d use
cmp go.sum go.sum.tidy
go build -n use
# If we delete the hash *and* the ziphash file, we should see the same behavior.
cp go.sum.bug go.sum
rm $WORK/gopath/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.ziphash
! go build -n use
stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$'
go get -d use
cmp go.sum go.sum.tidy
go build -n use
-- go.mod --
module use
go 1.17
require rsc.io/quote v1.5.2
-- go.sum.tidy --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
-- go.sum.bug --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
-- use.go --
package use
import _ "rsc.io/quote"

View File

@@ -11,7 +11,7 @@ cp go.mod.orig go.mod
go mod edit -require example.com/retract/self/prev@v1.9.0
go get -d example.com/retract/self/prev
stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$'
stderr '^go: to switch to the latest unretracted version, run:\n\tgo get example.com/retract/self/prev@latest$'
stderr '^go: to switch to the latest unretracted version, run:\n\tgo get example.com/retract/self/prev@latest\n$'
go list -m example.com/retract/self/prev
stdout '^example.com/retract/self/prev v1.9.0$'

View File

@@ -59,9 +59,9 @@ rm $GOPATH/bin
env GO111MODULE=on
go mod download rsc.io/fortune@v1.0.0
! go install $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
stderr '^go: cannot find main module; see ''go help modules''$'
stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
! go install ../pkg/mod/rsc.io/fortune@v1.0.0
stderr '^go: cannot find main module; see ''go help modules''$'
stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
mkdir tmp
cd tmp
go mod init tmp

View File

@@ -23,6 +23,20 @@ cd $WORK/gopath/src/badname
! go list .
stderr 'invalid module path'
# Test that an import path containing an element with a leading dot is valid,
# but such a module path is not.
# Verifies #43985.
cd $WORK/gopath/src/dotname
go list ./.dot
stdout '^example.com/dotname/.dot$'
go list ./use
stdout '^example.com/dotname/use$'
! go list -m example.com/dotname/.dot@latest
stderr '^go list -m: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$'
go get -d example.com/dotname/.dot
go get -d example.com/dotname/use
go mod tidy
-- mod/go.mod --
-- mod/foo.go --
@@ -38,3 +52,13 @@ module .\.
-- badname/foo.go --
package badname
-- dotname/go.mod --
module example.com/dotname
go 1.16
-- dotname/.dot/dot.go --
package dot
-- dotname/use/use.go --
package use
import _ "example.com/dotname/.dot"

View File

@@ -0,0 +1,32 @@
# https://golang.org/issue/44776
# The '+' character should be disallowed in module paths, but allowed in package
# paths within valid modules.
go get -d example.net/cmd
go list example.net/cmd/x++
! go list -versions -m 'example.net/bad++'
stderr '^go list -m: module example.net/bad\+\+: malformed module path "example.net/bad\+\+": invalid char ''\+''$'
# TODO(bcmills): 'go get -d example.net/cmd/x++' should also work, but currently
# it does not. This might be fixed by https://golang.org/cl/297891.
! go get -d example.net/cmd/x++
stderr '^go get: malformed module path "example.net/cmd/x\+\+": invalid char ''\+''$'
-- go.mod --
module example.com/m
go 1.16
replace (
example.net/cmd => ./cmd
)
-- cmd/go.mod --
module example.net/cmd
go 1.16
-- cmd/x++/main.go --
package main
func main() {}

View File

@@ -12,13 +12,13 @@ stdout 'NUL|/dev/null'
# 'go list' without arguments implicitly operates on the current directory,
# which is not in a module.
! go list
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
go list -m
stdout '^command-line-arguments$'
# 'go list' in the working directory should fail even if there is a a 'package
# main' present: without a main module, we do not know its package path.
! go list ./needmod
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go list all' lists the transitive import graph of the main module,
# which is empty if there is no main module.
@@ -41,7 +41,7 @@ stdout 'command-line-arguments'
# 'go list' on a package from a module should fail.
! go list example.com/printversion
stderr '^no required module provides package example.com/printversion: working directory is not part of a module$'
stderr '^no required module provides package example.com/printversion: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go list -m' with an explicit version should resolve that version.
@@ -54,19 +54,19 @@ stdout 'v1.0.0\s+v1.0.1\s+v1.1.0'
# 'go list -m all' should fail. "all" is not meaningful outside of a module.
! go list -m all
stderr 'go: cannot match "all": working directory is not part of a module'
stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go list -m <mods> all' should also fail.
! go list -m example.com/printversion@v1.0.0 all
stderr 'go: cannot match "all": working directory is not part of a module'
stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
! stdout 'example.com/version'
# 'go list -m' with wildcards should fail. Wildcards match modules in the
# build list, so they aren't meaningful outside a module.
! go list -m ...
stderr 'go: cannot match "...": working directory is not part of a module'
stderr 'go: cannot match "...": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
! go list -m rsc.io/quote/...
stderr 'go: cannot match "rsc.io/quote/...": working directory is not part of a module'
stderr 'go: cannot match "rsc.io/quote/...": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go clean' should skip the current directory if it isn't in a module.
@@ -76,20 +76,20 @@ go clean -n
# 'go mod graph' should fail, since there's no module graph.
! go mod graph
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go mod why' should fail, since there is no main module to depend on anything.
! go mod why -m example.com/version
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go mod edit', 'go mod tidy', and 'go mod fmt' should fail:
# there is no go.mod file to edit.
! go mod tidy
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
! go mod edit -fmt
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
! go mod edit -require example.com/version@v1.0.0
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go mod download' without arguments should report an error.
@@ -104,33 +104,33 @@ exists $GOPATH/pkg/mod/cache/download/example.com/printversion/@v/v1.0.0.zip
# 'go mod download all' should fail. "all" is not meaningful outside of a module.
! go mod download all
stderr 'go: cannot match "all": working directory is not part of a module'
stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go mod vendor' should fail: it starts by clearing the existing vendor
# directory, and we don't know where that is.
! go mod vendor
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go mod verify' should fail: we have no modules to verify.
! go mod verify
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go get' without arguments implicitly operates on the main module, and thus
# should fail.
! go get
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
! go get -u
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
! go get -u ./needmod
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go get -u all' upgrades the transitive import graph of the main module,
# which is empty.
! go get -u all
stderr 'go get: cannot match "all": working directory is not part of a module'
stderr '^go get: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go get' should check the proposed module graph for consistency,
# even though we won't write it anywhere.
@@ -147,16 +147,16 @@ exists $GOPATH/pkg/mod/example.com/version@v1.0.0
# 'go build' without arguments implicitly operates on the current directory, and should fail.
cd needmod
! go build
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
cd ..
# 'go build' of a non-module directory should fail too.
! go build ./needmod
stderr 'cannot find main module'
stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go build' of source files should fail if they import anything outside std.
! go build -n ./needmod/needmod.go
stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: working directory is not part of a module$'
stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go build' of source files should succeed if they do not import anything outside std.
go build -n -o ignore ./stdonly/stdonly.go
@@ -179,7 +179,7 @@ go doc fmt
# 'go doc' should fail for a package path outside a module.
! go doc example.com/version
stderr 'doc: no required module provides package example.com/version: working directory is not part of a module'
stderr 'doc: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go install' with a version should succeed if all constraints are met.
# See mod_install_pkg_version.
@@ -194,7 +194,7 @@ stderr '^go install: version is required when current directory is not in a modu
# 'go install' should fail if a source file imports a package that must be
# resolved to a module.
! go install ./needmod/needmod.go
stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: working directory is not part of a module'
stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go install' should succeed with a package in GOROOT.
go install cmd/addr2line
@@ -206,12 +206,12 @@ stderr 'can only use path@version syntax with'
# 'go run' should fail if a package argument must be resolved to a module.
! go run example.com/printversion
stderr '^no required module provides package example.com/printversion: working directory is not part of a module$'
stderr '^no required module provides package example.com/printversion: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go run' should fail if a source file imports a package that must be
# resolved to a module.
! go run ./needmod/needmod.go
stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: working directory is not part of a module$'
stderr '^needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
# 'go fmt' should be able to format files outside of a module.

View File

@@ -0,0 +1,48 @@
# retract must not be used without a module directive.
! go list -m all
stderr 'go.mod:3: no module directive found, so retract cannot be used$'
# Commands that update go.mod should fix non-canonical versions in
# retract directives.
# Verifies #44494.
go mod edit -module=rsc.io/quote/v2
! go list -m all
stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
go mod tidy
go list -m all
cmp go.mod go.mod.want
# If a retracted version doesn't match the module's major version suffx,
# an error should be reported.
! go mod edit -retract=v3.0.1
stderr '^go mod: -retract=v3.0.1: version "v3.0.1" invalid: should be v2, not v3$'
cp go.mod.mismatch-v2 go.mod
! go list -m all
stderr 'go.mod:3: retract rsc.io/quote/v2: version "v3.0.1" invalid: should be v2, not v3$'
cp go.mod.mismatch-v1 go.mod
! go list -m all
stderr 'go.mod:3: retract rsc.io/quote: version "v3.0.1" invalid: should be v0 or v1, not v3$'
-- go.mod --
go 1.16
retract latest
-- go.mod.want --
go 1.16
retract v2.0.1
module rsc.io/quote/v2
-- go.mod.mismatch-v2 --
go 1.16
retract v3.0.1
module rsc.io/quote/v2
-- go.mod.mismatch-v1 --
go 1.16
retract v3.0.1
module rsc.io/quote

View File

@@ -4,12 +4,12 @@ env GO111MODULE=on
# 'go mod tidy' and 'go mod vendor' should not hide loading errors.
! go mod tidy
stderr '^issue27063 imports\n\tnonexist: package nonexist is not in GOROOT \(.*\)'
! stderr 'package nonexist is not in GOROOT'
stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com'
stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist'
! go mod vendor
stderr '^issue27063 imports\n\tnonexist: package nonexist is not in GOROOT \(.*\)'
! stderr 'package nonexist is not in GOROOT'
stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com'
stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist'

View File

@@ -48,10 +48,13 @@ go mod tidy
grep '^rsc.io/quote v1.1.0/go.mod ' go.sum
grep '^rsc.io/quote v1.1.0 ' go.sum
# sync should ignore missing ziphash; verify should not
# verify should fail on a missing ziphash. tidy should restore it.
rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.ziphash
go mod tidy
! go mod verify
stderr '^rsc.io/quote v1.1.0: missing ziphash: open '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]rsc.io[/\\]quote[/\\]@v[/\\]v1.1.0.ziphash'
go mod tidy
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.ziphash
go mod verify
# Packages below module root should not be mentioned in go.sum.
rm go.sum

View File

@@ -370,10 +370,16 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
r := relocs.At(ri)
switch r.Type() {
case objabi.R_CALLARM:
// r.Add is the instruction
// low 24-bit encodes the target address
t := (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4
if t > 0x7fffff || t < -0x800000 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
var t int64
// ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet
// laid out. Conservatively use a trampoline. This should be rare, as we lay out packages
// in dependency order.
if ldr.SymValue(rs) != 0 {
// r.Add is the instruction
// low 24-bit encodes the target address
t = (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4
}
if t > 0x7fffff || t < -0x800000 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
// direct call too far, need to insert trampoline.
// look up existing trampolines first. if we found one within the range
// of direct call, we can reuse it. otherwise create a new one.
@@ -445,7 +451,7 @@ func gentramp(arch *sys.Arch, linkmode ld.LinkMode, ldr *loader.Loader, tramp *l
arch.ByteOrder.PutUint32(P[8:], o3)
tramp.SetData(P)
if linkmode == ld.LinkExternal {
if linkmode == ld.LinkExternal || ldr.SymValue(target) == 0 {
r, _ := tramp.AddRel(objabi.R_ADDR)
r.SetOff(8)
r.SetSiz(4)

View File

@@ -106,14 +106,12 @@ func trampoline(ctxt *Link, s loader.Sym) {
}
rs = ldr.ResolveABIAlias(rs)
if ldr.SymValue(rs) == 0 && (ldr.SymType(rs) != sym.SDYNIMPORT && ldr.SymType(rs) != sym.SUNDEFEXT) {
if ldr.SymPkg(rs) != ldr.SymPkg(s) {
if !isRuntimeDepPkg(ldr.SymPkg(s)) || !isRuntimeDepPkg(ldr.SymPkg(rs)) {
ctxt.Errorf(s, "unresolved inter-package jump to %s(%s) from %s", ldr.SymName(rs), ldr.SymPkg(rs), ldr.SymPkg(s))
}
// runtime and its dependent packages may call to each other.
// they are fine, as they will be laid down together.
if ldr.SymPkg(rs) == ldr.SymPkg(s) {
continue // symbols in the same package are laid out together
}
if isRuntimeDepPkg(ldr.SymPkg(s)) && isRuntimeDepPkg(ldr.SymPkg(rs)) {
continue // runtime packages are laid out together
}
continue
}
thearch.Trampoline(ctxt, ldr, ri, rs, s)

View File

@@ -24,6 +24,7 @@ type deadcodePass struct {
ifaceMethod map[methodsig]bool // methods declared in reached interfaces
markableMethods []methodref // methods of reached types
reflectSeen bool // whether we have seen a reflect method call
dynlink bool
methodsigstmp []methodsig // scratch buffer for decoding method signatures
}
@@ -34,6 +35,7 @@ func (d *deadcodePass) init() {
if objabi.Fieldtrack_enabled != 0 {
d.ldr.Reachparent = make([]loader.Sym, d.ldr.NSym())
}
d.dynlink = d.ctxt.DynlinkingGo()
if d.ctxt.BuildMode == BuildModeShared {
// Mark all symbols defined in this library as reachable when
@@ -111,6 +113,11 @@ func (d *deadcodePass) flood() {
var usedInIface bool
if isgotype {
if d.dynlink {
// When dynaamic linking, a type may be passed across DSO
// boundary and get converted to interface at the other side.
d.ldr.SetAttrUsedInIface(symIdx, true)
}
usedInIface = d.ldr.AttrUsedInIface(symIdx)
}

View File

@@ -31,6 +31,7 @@
package ld
import (
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
@@ -102,10 +103,14 @@ func putelfsym(ctxt *Link, x loader.Sym, typ elf.SymType, curbind elf.SymBind) {
elfshnum = xosect.Elfsect.(*ElfShdr).shnum
}
sname := ldr.SymExtname(x)
// One pass for each binding: elf.STB_LOCAL, elf.STB_GLOBAL,
// maybe one day elf.STB_WEAK.
bind := elf.STB_GLOBAL
if ldr.IsFileLocal(x) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
if ldr.IsFileLocal(x) && !isStaticTmp(sname) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
// Static tmp is package local, but a package can be shared among multiple DSOs.
// They need to have a single view of the static tmp that are writable.
bind = elf.STB_LOCAL
}
@@ -140,8 +145,6 @@ func putelfsym(ctxt *Link, x loader.Sym, typ elf.SymType, curbind elf.SymBind) {
other |= 3 << 5
}
sname := ldr.SymExtname(x)
// When dynamically linking, we create Symbols by reading the names from
// the symbol tables of the shared libraries and so the names need to
// match exactly. Tools like DTrace will have to wait for now.
@@ -823,3 +826,7 @@ func setCarrierSize(typ sym.SymKind, sz int64) {
}
CarrierSymByType[typ].Size = sz
}
func isStaticTmp(name string) bool {
return strings.Contains(name, "."+obj.StaticNamePref)
}

View File

@@ -656,13 +656,19 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
relocs := ldr.Relocs(s)
r := relocs.At(ri)
t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
var t int64
// ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet
// laid out. Conservatively use a trampoline. This should be rare, as we lay out packages
// in dependency order.
if ldr.SymValue(rs) != 0 {
t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
}
switch r.Type() {
case objabi.R_CALLPOWER:
// If branch offset is too far then create a trampoline.
if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
var tramp loader.Sym
for i := 0; ; i++ {
@@ -749,7 +755,7 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta
// With external linking, the target address must be
// relocated using LO and HA
if ctxt.IsExternal() {
if ctxt.IsExternal() || ldr.SymValue(target) == 0 {
r, _ := tramp.AddRel(objabi.R_ADDRPOWER)
r.SetOff(0)
r.SetSiz(8) // generates 2 relocations: HA + LO

View File

@@ -125,6 +125,12 @@ func (f *File) AddComment(text string) {
type VersionFixer func(path, version string) (string, error)
// errDontFix is returned by a VersionFixer to indicate the version should be
// left alone, even if it's not canonical.
var dontFixRetract VersionFixer = func(_, vers string) (string, error) {
return vers, nil
}
// Parse parses the data, reported in errors as being from file,
// into a File struct. It applies fix, if non-nil, to canonicalize all module versions found.
func Parse(file string, data []byte, fix VersionFixer) (*File, error) {
@@ -142,7 +148,7 @@ func ParseLax(file string, data []byte, fix VersionFixer) (*File, error) {
return parseToFile(file, data, fix, false)
}
func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File, error) {
func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parsed *File, err error) {
fs, err := parse(file, data)
if err != nil {
return nil, err
@@ -150,8 +156,18 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File
f := &File{
Syntax: fs,
}
var errs ErrorList
// fix versions in retract directives after the file is parsed.
// We need the module path to fix versions, and it might be at the end.
defer func() {
oldLen := len(errs)
f.fixRetract(fix, &errs)
if len(errs) > oldLen {
parsed, err = nil, errs
}
}()
for _, x := range fs.Stmt {
switch x := x.(type) {
case *Line:
@@ -370,7 +386,7 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a
case "retract":
rationale := parseRetractRationale(block, line)
vi, err := parseVersionInterval(verb, &args, fix)
vi, err := parseVersionInterval(verb, "", &args, dontFixRetract)
if err != nil {
if strict {
wrapError(err)
@@ -397,6 +413,47 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a
}
}
// fixRetract applies fix to each retract directive in f, appending any errors
// to errs.
//
// Most versions are fixed as we parse the file, but for retract directives,
// the relevant module path is the one specified with the module directive,
// and that might appear at the end of the file (or not at all).
func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) {
if fix == nil {
return
}
path := ""
if f.Module != nil {
path = f.Module.Mod.Path
}
var r *Retract
wrapError := func(err error) {
*errs = append(*errs, Error{
Filename: f.Syntax.Name,
Pos: r.Syntax.Start,
Err: err,
})
}
for _, r = range f.Retract {
if path == "" {
wrapError(errors.New("no module directive found, so retract cannot be used"))
return // only print the first one of these
}
args := r.Syntax.Token
if args[0] == "retract" {
args = args[1:]
}
vi, err := parseVersionInterval("retract", path, &args, fix)
if err != nil {
wrapError(err)
}
r.VersionInterval = vi
}
}
// isIndirect reports whether line has a "// indirect" comment,
// meaning it is in go.mod only for its effect on indirect dependencies,
// so that it can be dropped entirely once the effective version of the
@@ -491,13 +548,13 @@ func AutoQuote(s string) string {
return s
}
func parseVersionInterval(verb string, args *[]string, fix VersionFixer) (VersionInterval, error) {
func parseVersionInterval(verb string, path string, args *[]string, fix VersionFixer) (VersionInterval, error) {
toks := *args
if len(toks) == 0 || toks[0] == "(" {
return VersionInterval{}, fmt.Errorf("expected '[' or version")
}
if toks[0] != "[" {
v, err := parseVersion(verb, "", &toks[0], fix)
v, err := parseVersion(verb, path, &toks[0], fix)
if err != nil {
return VersionInterval{}, err
}
@@ -509,7 +566,7 @@ func parseVersionInterval(verb string, args *[]string, fix VersionFixer) (Versio
if len(toks) == 0 {
return VersionInterval{}, fmt.Errorf("expected version after '['")
}
low, err := parseVersion(verb, "", &toks[0], fix)
low, err := parseVersion(verb, path, &toks[0], fix)
if err != nil {
return VersionInterval{}, err
}
@@ -523,7 +580,7 @@ func parseVersionInterval(verb string, args *[]string, fix VersionFixer) (Versio
if len(toks) == 0 {
return VersionInterval{}, fmt.Errorf("expected version after ','")
}
high, err := parseVersion(verb, "", &toks[0], fix)
high, err := parseVersion(verb, path, &toks[0], fix)
if err != nil {
return VersionInterval{}, err
}
@@ -631,8 +688,7 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string
}
}
if fix != nil {
var err error
t, err = fix(path, t)
fixed, err := fix(path, t)
if err != nil {
if err, ok := err.(*module.ModuleError); ok {
return "", &Error{
@@ -643,19 +699,23 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string
}
return "", err
}
t = fixed
} else {
cv := module.CanonicalVersion(t)
if cv == "" {
return "", &Error{
Verb: verb,
ModPath: path,
Err: &module.InvalidVersionError{
Version: t,
Err: errors.New("must be of the form v1.2.3"),
},
}
}
t = cv
}
if v := module.CanonicalVersion(t); v != "" {
*s = v
return *s, nil
}
return "", &Error{
Verb: verb,
ModPath: path,
Err: &module.InvalidVersionError{
Version: t,
Err: errors.New("must be of the form v1.2.3"),
},
}
*s = t
return *s, nil
}
func modulePathMajor(path string) (string, error) {
@@ -835,11 +895,8 @@ func (f *File) DropRequire(path string) error {
// AddExclude adds a exclude statement to the mod file. Errors if the provided
// version is not a canonical version string
func (f *File) AddExclude(path, vers string) error {
if !isCanonicalVersion(vers) {
return &module.InvalidVersionError{
Version: vers,
Err: errors.New("must be of the form v1.2.3"),
}
if err := checkCanonicalVersion(path, vers); err != nil {
return err
}
var hint *Line
@@ -916,17 +973,15 @@ func (f *File) DropReplace(oldPath, oldVers string) error {
// AddRetract adds a retract statement to the mod file. Errors if the provided
// version interval does not consist of canonical version strings
func (f *File) AddRetract(vi VersionInterval, rationale string) error {
if !isCanonicalVersion(vi.High) {
return &module.InvalidVersionError{
Version: vi.High,
Err: errors.New("must be of the form v1.2.3"),
}
var path string
if f.Module != nil {
path = f.Module.Mod.Path
}
if !isCanonicalVersion(vi.Low) {
return &module.InvalidVersionError{
Version: vi.Low,
Err: errors.New("must be of the form v1.2.3"),
}
if err := checkCanonicalVersion(path, vi.High); err != nil {
return err
}
if err := checkCanonicalVersion(path, vi.Low); err != nil {
return err
}
r := &Retract{
@@ -1086,8 +1141,40 @@ func lineRetractLess(li, lj *Line) bool {
return semver.Compare(vii.High, vij.High) > 0
}
// isCanonicalVersion tests if the provided version string represents a valid
// canonical version.
func isCanonicalVersion(vers string) bool {
return vers != "" && semver.Canonical(vers) == vers
// checkCanonicalVersion returns a non-nil error if vers is not a canonical
// version string or does not match the major version of path.
//
// If path is non-empty, the error text suggests a format with a major version
// corresponding to the path.
func checkCanonicalVersion(path, vers string) error {
_, pathMajor, pathMajorOk := module.SplitPathVersion(path)
if vers == "" || vers != module.CanonicalVersion(vers) {
if pathMajor == "" {
return &module.InvalidVersionError{
Version: vers,
Err: fmt.Errorf("must be of the form v1.2.3"),
}
}
return &module.InvalidVersionError{
Version: vers,
Err: fmt.Errorf("must be of the form %s.2.3", module.PathMajorPrefix(pathMajor)),
}
}
if pathMajorOk {
if err := module.CheckPathMajor(vers, pathMajor); err != nil {
if pathMajor == "" {
// In this context, the user probably wrote "v2.3.4" when they meant
// "v2.3.4+incompatible". Suggest that instead of "v0 or v1".
return &module.InvalidVersionError{
Version: vers,
Err: fmt.Errorf("should be %s+incompatible (or module %s/%v)", vers, path, semver.Major(vers)),
}
}
return err
}
}
return nil
}

View File

@@ -224,12 +224,16 @@ func firstPathOK(r rune) bool {
'a' <= r && r <= 'z'
}
// pathOK reports whether r can appear in an import path element.
// modPathOK reports whether r can appear in a module path element.
// Paths can be ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~.
// This matches what "go get" has historically recognized in import paths.
//
// This matches what "go get" has historically recognized in import paths,
// and avoids confusing sequences like '%20' or '+' that would change meaning
// if used in a URL.
//
// TODO(rsc): We would like to allow Unicode letters, but that requires additional
// care in the safe encoding (see "escaped paths" above).
func pathOK(r rune) bool {
func modPathOK(r rune) bool {
if r < utf8.RuneSelf {
return r == '-' || r == '.' || r == '_' || r == '~' ||
'0' <= r && r <= '9' ||
@@ -239,6 +243,17 @@ func pathOK(r rune) bool {
return false
}
// modPathOK reports whether r can appear in a package import path element.
//
// Import paths are intermediate between module paths and file paths: we allow
// disallow characters that would be confusing or ambiguous as arguments to
// 'go get' (such as '@' and ' ' ), but allow certain characters that are
// otherwise-unambiguous on the command line and historically used for some
// binary names (such as '++' as a suffix for compiler binaries and wrappers).
func importPathOK(r rune) bool {
return modPathOK(r) || r == '+'
}
// fileNameOK reports whether r can appear in a file name.
// For now we allow all Unicode letters but otherwise limit to pathOK plus a few more punctuation characters.
// If we expand the set of allowed characters here, we have to
@@ -270,7 +285,7 @@ func fileNameOK(r rune) bool {
// CheckPath checks that a module path is valid.
// A valid module path is a valid import path, as checked by CheckImportPath,
// with two additional constraints.
// with three additional constraints.
// First, the leading path element (up to the first slash, if any),
// by convention a domain name, must contain only lower-case ASCII letters,
// ASCII digits, dots (U+002E), and dashes (U+002D);
@@ -280,8 +295,9 @@ func fileNameOK(r rune) bool {
// and must not contain any dots. For paths beginning with "gopkg.in/",
// this second requirement is replaced by a requirement that the path
// follow the gopkg.in server's conventions.
// Third, no path element may begin with a dot.
func CheckPath(path string) error {
if err := checkPath(path, false); err != nil {
if err := checkPath(path, modulePath); err != nil {
return fmt.Errorf("malformed module path %q: %v", path, err)
}
i := strings.Index(path, "/")
@@ -315,7 +331,7 @@ func CheckPath(path string) error {
//
// A valid path element is a non-empty string made up of
// ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~.
// It must not begin or end with a dot (U+002E), nor contain two dots in a row.
// It must not end with a dot (U+002E), nor contain two dots in a row.
//
// The element prefix up to the first dot must not be a reserved file name
// on Windows, regardless of case (CON, com1, NuL, and so on). The element
@@ -326,19 +342,29 @@ func CheckPath(path string) error {
// top-level package documentation for additional information about
// subtleties of Unicode.
func CheckImportPath(path string) error {
if err := checkPath(path, false); err != nil {
if err := checkPath(path, importPath); err != nil {
return fmt.Errorf("malformed import path %q: %v", path, err)
}
return nil
}
// pathKind indicates what kind of path we're checking. Module paths,
// import paths, and file paths have different restrictions.
type pathKind int
const (
modulePath pathKind = iota
importPath
filePath
)
// checkPath checks that a general path is valid.
// It returns an error describing why but not mentioning path.
// Because these checks apply to both module paths and import paths,
// the caller is expected to add the "malformed ___ path %q: " prefix.
// fileName indicates whether the final element of the path is a file name
// (as opposed to a directory name).
func checkPath(path string, fileName bool) error {
func checkPath(path string, kind pathKind) error {
if !utf8.ValidString(path) {
return fmt.Errorf("invalid UTF-8")
}
@@ -357,39 +383,45 @@ func checkPath(path string, fileName bool) error {
elemStart := 0
for i, r := range path {
if r == '/' {
if err := checkElem(path[elemStart:i], fileName); err != nil {
if err := checkElem(path[elemStart:i], kind); err != nil {
return err
}
elemStart = i + 1
}
}
if err := checkElem(path[elemStart:], fileName); err != nil {
if err := checkElem(path[elemStart:], kind); err != nil {
return err
}
return nil
}
// checkElem checks whether an individual path element is valid.
// fileName indicates whether the element is a file name (not a directory name).
func checkElem(elem string, fileName bool) error {
func checkElem(elem string, kind pathKind) error {
if elem == "" {
return fmt.Errorf("empty path element")
}
if strings.Count(elem, ".") == len(elem) {
return fmt.Errorf("invalid path element %q", elem)
}
if elem[0] == '.' && !fileName {
if elem[0] == '.' && kind == modulePath {
return fmt.Errorf("leading dot in path element")
}
if elem[len(elem)-1] == '.' {
return fmt.Errorf("trailing dot in path element")
}
charOK := pathOK
if fileName {
charOK = fileNameOK
}
for _, r := range elem {
if !charOK(r) {
ok := false
switch kind {
case modulePath:
ok = modPathOK(r)
case importPath:
ok = importPathOK(r)
case filePath:
ok = fileNameOK(r)
default:
panic(fmt.Sprintf("internal error: invalid kind %v", kind))
}
if !ok {
return fmt.Errorf("invalid char %q", r)
}
}
@@ -406,7 +438,7 @@ func checkElem(elem string, fileName bool) error {
}
}
if fileName {
if kind == filePath {
// don't check for Windows short-names in file names. They're
// only an issue for import paths.
return nil
@@ -444,7 +476,7 @@ func checkElem(elem string, fileName bool) error {
// top-level package documentation for additional information about
// subtleties of Unicode.
func CheckFilePath(path string) error {
if err := checkPath(path, true); err != nil {
if err := checkPath(path, filePath); err != nil {
return fmt.Errorf("malformed file path %q: %v", path, err)
}
return nil
@@ -647,7 +679,7 @@ func EscapePath(path string) (escaped string, err error) {
// Versions are allowed to be in non-semver form but must be valid file names
// and not contain exclamation marks.
func EscapeVersion(v string) (escaped string, err error) {
if err := checkElem(v, true); err != nil || strings.Contains(v, "!") {
if err := checkElem(v, filePath); err != nil || strings.Contains(v, "!") {
return "", &InvalidVersionError{
Version: v,
Err: fmt.Errorf("disallowed version string"),
@@ -706,7 +738,7 @@ func UnescapeVersion(escaped string) (v string, err error) {
if !ok {
return "", fmt.Errorf("invalid escaped version %q", escaped)
}
if err := checkElem(v, true); err != nil {
if err := checkElem(v, filePath); err != nil {
return "", fmt.Errorf("invalid escaped version %q: %v", v, err)
}
return v, nil

View File

@@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
golang.org/x/crypto/ed25519
golang.org/x/crypto/ed25519/internal/edwards25519
golang.org/x/crypto/ssh/terminal
# golang.org/x/mod v0.4.1
# golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea
## explicit
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile

View File

@@ -271,7 +271,7 @@ func NewTokenDecoder(t TokenReader) *Decoder {
// it will return an error.
//
// Token implements XML name spaces as described by
// https://www.w3.org/TR/REC-xml-names/. Each of the
// https://www.w3.org/TR/REC-xml-names/. Each of the
// Name structures contained in the Token has the Space
// set to the URL identifying its name space when known.
// If Token encounters an unrecognized name space prefix,
@@ -285,16 +285,17 @@ func (d *Decoder) Token() (Token, error) {
if d.nextToken != nil {
t = d.nextToken
d.nextToken = nil
} else if t, err = d.rawToken(); err != nil {
switch {
case err == io.EOF && d.t != nil:
err = nil
case err == io.EOF && d.stk != nil && d.stk.kind != stkEOF:
err = d.syntaxError("unexpected EOF")
} else {
if t, err = d.rawToken(); t == nil && err != nil {
if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF {
err = d.syntaxError("unexpected EOF")
}
return nil, err
}
return t, err
// We still have a token to process, so clear any
// errors (e.g. EOF) and proceed.
err = nil
}
if !d.Strict {
if t1, ok := d.autoClose(t); ok {
d.nextToken = t

View File

@@ -33,30 +33,90 @@ func (t *toks) Token() (Token, error) {
func TestDecodeEOF(t *testing.T) {
start := StartElement{Name: Name{Local: "test"}}
t.Run("EarlyEOF", func(t *testing.T) {
d := NewTokenDecoder(&toks{earlyEOF: true, t: []Token{
start,
start.End(),
}})
err := d.Decode(&struct {
XMLName Name `xml:"test"`
}{})
if err != nil {
t.Error(err)
tests := []struct {
name string
tokens []Token
ok bool
}{
{
name: "OK",
tokens: []Token{
start,
start.End(),
},
ok: true,
},
{
name: "Malformed",
tokens: []Token{
start,
StartElement{Name: Name{Local: "bad"}},
start.End(),
},
ok: false,
},
}
for _, tc := range tests {
for _, eof := range []bool{true, false} {
name := fmt.Sprintf("%s/earlyEOF=%v", tc.name, eof)
t.Run(name, func(t *testing.T) {
d := NewTokenDecoder(&toks{
earlyEOF: eof,
t: tc.tokens,
})
err := d.Decode(&struct {
XMLName Name `xml:"test"`
}{})
if tc.ok && err != nil {
t.Fatalf("d.Decode: expected nil error, got %v", err)
}
if _, ok := err.(*SyntaxError); !tc.ok && !ok {
t.Errorf("d.Decode: expected syntax error, got %v", err)
}
})
}
})
t.Run("LateEOF", func(t *testing.T) {
d := NewTokenDecoder(&toks{t: []Token{
start,
start.End(),
}})
err := d.Decode(&struct {
XMLName Name `xml:"test"`
}{})
if err != nil {
t.Error(err)
}
}
type toksNil struct {
returnEOF bool
t []Token
}
func (t *toksNil) Token() (Token, error) {
if len(t.t) == 0 {
if !t.returnEOF {
// Return nil, nil before returning an EOF. It's legal, but
// discouraged.
t.returnEOF = true
return nil, nil
}
})
return nil, io.EOF
}
var tok Token
tok, t.t = t.t[0], t.t[1:]
return tok, nil
}
func TestDecodeNilToken(t *testing.T) {
for _, strict := range []bool{true, false} {
name := fmt.Sprintf("Strict=%v", strict)
t.Run(name, func(t *testing.T) {
start := StartElement{Name: Name{Local: "test"}}
bad := StartElement{Name: Name{Local: "bad"}}
d := NewTokenDecoder(&toksNil{
// Malformed
t: []Token{start, bad, start.End()},
})
d.Strict = strict
err := d.Decode(&struct {
XMLName Name `xml:"test"`
}{})
if _, ok := err.(*SyntaxError); !ok {
t.Errorf("d.Decode: expected syntax error, got %v", err)
}
})
}
}
const testInput = `

View File

@@ -4,7 +4,7 @@ go 1.16
require (
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11
golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
golang.org/x/text v0.3.4 // indirect
)

View File

@@ -2,8 +2,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b h1:SQCMv1JDt7RN/Vp0bjtNMSufVVHgpFVzmDFdCLL31yY=
golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@@ -612,7 +612,7 @@ func TestImportPackageOutsideModule(t *testing.T) {
ctxt.GOPATH = gopath
ctxt.Dir = filepath.Join(gopath, "src/example.com/p")
want := "working directory is not part of a module"
want := "go.mod file not found in current directory or any parent directory"
if _, err := ctxt.Import("example.com/p", gopath, FindOnly); err == nil {
t.Fatal("importing package when no go.mod is present succeeded unexpectedly")
} else if errStr := err.Error(); !strings.Contains(errStr, want) {

View File

@@ -15,6 +15,7 @@ import (
"os"
"os/exec"
"runtime"
"runtime/trace"
"strconv"
"sync"
"syscall"
@@ -853,3 +854,44 @@ func TestNotifyContextStringer(t *testing.T) {
t.Errorf("c.String() = %q, want %q", got, want)
}
}
// #44193 test signal handling while stopping and starting the world.
func TestSignalTrace(t *testing.T) {
done := make(chan struct{})
quit := make(chan struct{})
c := make(chan os.Signal, 1)
Notify(c, syscall.SIGHUP)
// Source and sink for signals busy loop unsynchronized with
// trace starts and stops. We are ultimately validating that
// signals and runtime.(stop|start)TheWorldGC are compatible.
go func() {
defer close(done)
defer Stop(c)
pid := syscall.Getpid()
for {
select {
case <-quit:
return
default:
syscall.Kill(pid, syscall.SIGHUP)
}
waitSig(t, c, syscall.SIGHUP)
}
}()
for i := 0; i < 100; i++ {
buf := new(bytes.Buffer)
if err := trace.Start(buf); err != nil {
t.Fatalf("[%d] failed to start tracing: %v", i, err)
}
time.After(1 * time.Microsecond)
trace.Stop()
size := buf.Len()
if size == 0 {
t.Fatalf("[%d] trace is empty", i)
}
}
close(quit)
<-done
}

View File

@@ -23,15 +23,7 @@ fi
eval $(../bin/go env)
export GOROOT # The api test requires GOROOT to be set, so set it to match ../bin/go.
# We disallow local import for non-local packages, if $GOROOT happens
# to be under $GOPATH, then some tests below will fail. $GOPATH needs
# to be set to a non-empty string, else Go will set a default value
# that may also conflict with $GOROOT. The $GOPATH value doesn't need
# to point to an actual directory, it just needs to pass the semantic
# checks performed by Go. Use $GOROOT to define $GOPATH so that we
# don't blunder into a user-defined symbolic link.
export GOPATH=/dev/null
export GOPATH=/nonexist-gopath
unset CDPATH # in case user has it set
export GOBIN=$GOROOT/bin # Issue 14340

View File

@@ -18,9 +18,7 @@ setlocal
set GOBUILDFAIL=0
:: we disallow local import for non-local packages, if %GOROOT% happens
:: to be under %GOPATH%, then some tests below will fail
set GOPATH=
set GOPATH=c:\nonexist-gopath
:: Issue 14340: ignore GOBIN during all.bat.
set GOBIN=
set GOFLAGS=

View File

@@ -12,10 +12,9 @@ if(! test -f ../bin/go){
eval `{../bin/go env}
GOPATH = () # we disallow local import for non-local packages, if $GOROOT happens
# to be under $GOPATH, then some tests below will fail
GOBIN = () # Issue 14340
GOFLAGS = ()
GO111MODULE = ()
GOPATH=/nonexist-gopath
GOBIN=() # Issue 14340
GOFLAGS=()
GO111MODULE=()
exec ../bin/go tool dist test -rebuild $*

View File

@@ -32,7 +32,7 @@ typedef struct {
#define SET_RETVAL(fn) \
uintptr_t ret = (uintptr_t) fn ; \
if (ret == -1) { \
if (ret == (uintptr_t) -1) { \
x->retval = (uintptr_t) errno; \
} else \
x->retval = ret

View File

@@ -279,7 +279,8 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri
broken := false
switch runtime.GOOS {
case "darwin", "ios", "dragonfly", "netbsd", "illumos", "solaris":
// See https://golang.org/issue/45170 for AIX.
case "darwin", "ios", "dragonfly", "netbsd", "illumos", "solaris", "aix":
broken = true
case "openbsd":
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {

View File

@@ -1338,6 +1338,9 @@ func mPark() {
g := getg()
for {
notesleep(&g.m.park)
// Note, because of signal handling by this parked m,
// a preemptive mDoFixup() may actually occur via
// mDoFixupAndOSYield(). (See golang.org/issue/44193)
noteclear(&g.m.park)
if !mDoFixup() {
return
@@ -1571,6 +1574,22 @@ func syscall_runtime_doAllThreadsSyscall(fn func(bool) bool) {
for atomic.Load(&sched.sysmonStarting) != 0 {
osyield()
}
// We don't want this thread to handle signals for the
// duration of this critical section. The underlying issue
// being that this locked coordinating m is the one monitoring
// for fn() execution by all the other m's of the runtime,
// while no regular go code execution is permitted (the world
// is stopped). If this present m were to get distracted to
// run signal handling code, and find itself waiting for a
// second thread to execute go code before being able to
// return from that signal handling, a deadlock will result.
// (See golang.org/issue/44193.)
lockOSThread()
var sigmask sigset
sigsave(&sigmask)
sigblock(false)
stopTheWorldGC("doAllThreadsSyscall")
if atomic.Load(&newmHandoff.haveTemplateThread) != 0 {
// Ensure that there are no in-flight thread
@@ -1622,6 +1641,7 @@ func syscall_runtime_doAllThreadsSyscall(fn func(bool) bool) {
// the possibility of racing with mp.
lock(&mp.mFixup.lock)
mp.mFixup.fn = fn
atomic.Store(&mp.mFixup.used, 1)
if mp.doesPark {
// For non-service threads this will
// cause the wakeup to be short lived
@@ -1638,9 +1658,7 @@ func syscall_runtime_doAllThreadsSyscall(fn func(bool) bool) {
if mp.procid == tid {
continue
}
lock(&mp.mFixup.lock)
done = done && (mp.mFixup.fn == nil)
unlock(&mp.mFixup.lock)
done = atomic.Load(&mp.mFixup.used) == 0
}
if done {
break
@@ -1667,6 +1685,8 @@ func syscall_runtime_doAllThreadsSyscall(fn func(bool) bool) {
unlock(&mFixupRace.lock)
}
startTheWorldGC()
msigrestore(sigmask)
unlockOSThread()
}
// runSafePointFn runs the safe point function, if any, for this P.
@@ -2157,9 +2177,21 @@ var mFixupRace struct {
// mDoFixup runs any outstanding fixup function for the running m.
// Returns true if a fixup was outstanding and actually executed.
//
// Note: to avoid deadlocks, and the need for the fixup function
// itself to be async safe, signals are blocked for the working m
// while it holds the mFixup lock. (See golang.org/issue/44193)
//
//go:nosplit
func mDoFixup() bool {
_g_ := getg()
if used := atomic.Load(&_g_.m.mFixup.used); used == 0 {
return false
}
// slow path - if fixup fn is used, block signals and lock.
var sigmask sigset
sigsave(&sigmask)
sigblock(false)
lock(&_g_.m.mFixup.lock)
fn := _g_.m.mFixup.fn
if fn != nil {
@@ -2176,7 +2208,6 @@ func mDoFixup() bool {
// is more obviously safe.
throw("GC must be disabled to protect validity of fn value")
}
*(*uintptr)(unsafe.Pointer(&_g_.m.mFixup.fn)) = 0
if _g_.racectx != 0 || !raceenabled {
fn(false)
} else {
@@ -2191,11 +2222,24 @@ func mDoFixup() bool {
_g_.racectx = 0
unlock(&mFixupRace.lock)
}
*(*uintptr)(unsafe.Pointer(&_g_.m.mFixup.fn)) = 0
atomic.Store(&_g_.m.mFixup.used, 0)
}
unlock(&_g_.m.mFixup.lock)
msigrestore(sigmask)
return fn != nil
}
// mDoFixupAndOSYield is called when an m is unable to send a signal
// because the allThreadsSyscall mechanism is in progress. That is, an
// mPark() has been interrupted with this signal handler so we need to
// ensure the fixup is executed from this context.
//go:nosplit
func mDoFixupAndOSYield() {
mDoFixup()
osyield()
}
// templateThread is a thread in a known-good state that exists solely
// to start new threads in known-good states when the calling thread
// may not be in a good state.

View File

@@ -537,10 +537,13 @@ type m struct {
syscalltick uint32
freelink *m // on sched.freem
// mFixup is used to synchronize OS related m state (credentials etc)
// use mutex to access.
// mFixup is used to synchronize OS related m state
// (credentials etc) use mutex to access. To avoid deadlocks
// an atomic.Load() of used being zero in mDoFixupFn()
// guarantees fn is nil.
mFixup struct {
lock mutex
used uint32
fn func(bool) bool
}

View File

@@ -119,7 +119,7 @@ Send:
}
case sigFixup:
// nothing to do - we need to wait for sigIdle.
osyield()
mDoFixupAndOSYield()
}
}

View File

@@ -102,7 +102,9 @@ func (ci *Frames) Next() (frame Frame, more bool) {
name := funcname(funcInfo)
if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil {
inltree := (*[1 << 20]inlinedCall)(inldata)
ix := pcdatavalue(funcInfo, _PCDATA_InlTreeIndex, pc, nil)
// Non-strict as cgoTraceback may have added bogus PCs
// with a valid funcInfo but invalid PCDATA.
ix := pcdatavalue1(funcInfo, _PCDATA_InlTreeIndex, pc, nil, false)
if ix >= 0 {
// Note: entry is not modified. It always refers to a real frame, not an inlined one.
f = nil
@@ -183,7 +185,9 @@ func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr {
var cache pcvalueCache
inltree := (*[1 << 20]inlinedCall)(inldata)
for {
ix := pcdatavalue(f, _PCDATA_InlTreeIndex, tracepc, &cache)
// Non-strict as cgoTraceback may have added bogus PCs
// with a valid funcInfo but invalid PCDATA.
ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, tracepc, &cache, false)
if ix < 0 {
break
}

View File

@@ -8,6 +8,7 @@ import (
"runtime"
"strings"
"testing"
"unsafe"
)
func TestCaller(t *testing.T) {
@@ -165,3 +166,87 @@ func TestNilName(t *testing.T) {
t.Errorf("Name() = %q, want %q", got, "")
}
}
var dummy int
func inlined() {
// Side effect to prevent elimination of this entire function.
dummy = 42
}
// A function with an InlTree. Returns a PC within the function body.
//
// No inline to ensure this complete function appears in output.
//
//go:noinline
func tracebackFunc(t *testing.T) uintptr {
// This body must be more complex than a single call to inlined to get
// an inline tree.
inlined()
inlined()
// Acquire a PC in this function.
pc, _, _, ok := runtime.Caller(0)
if !ok {
t.Fatalf("Caller(0) got ok false, want true")
}
return pc
}
// Test that CallersFrames handles PCs in the alignment region between
// functions (int 3 on amd64) without crashing.
//
// Go will never generate a stack trace containing such an address, as it is
// not a valid call site. However, the cgo traceback function passed to
// runtime.SetCgoTraceback may not be completely accurate and may incorrect
// provide PCs in Go code or the alignement region between functions.
//
// Go obviously doesn't easily expose the problematic PCs to running programs,
// so this test is a bit fragile. Some details:
//
// * tracebackFunc is our target function. We want to get a PC in the
// alignment region following this function. This function also has other
// functions inlined into it to ensure it has an InlTree (this was the source
// of the bug in issue 44971).
//
// * We acquire a PC in tracebackFunc, walking forwards until FuncForPC says
// we're in a new function. The last PC of the function according to FuncForPC
// should be in the alignment region (assuming the function isn't already
// perfectly aligned).
//
// This is a regression test for issue 44971.
func TestFunctionAlignmentTraceback(t *testing.T) {
pc := tracebackFunc(t)
// Double-check we got the right PC.
f := runtime.FuncForPC(pc)
if !strings.HasSuffix(f.Name(), "tracebackFunc") {
t.Fatalf("Caller(0) = %+v, want tracebackFunc", f)
}
// Iterate forward until we find a different function. Back up one
// instruction is (hopefully) an alignment instruction.
for runtime.FuncForPC(pc) == f {
pc++
}
pc--
// Is this an alignment region filler instruction? We only check this
// on amd64 for simplicity. If this function has no filler, then we may
// get a false negative, but will never get a false positive.
if runtime.GOARCH == "amd64" {
code := *(*uint8)(unsafe.Pointer(pc))
if code != 0xcc { // INT $3
t.Errorf("PC %v code got %#x want 0xcc", pc, code)
}
}
// Finally ensure that Frames.Next doesn't crash when processing this
// PC.
frames := runtime.CallersFrames([]uintptr{pc})
frame, _ := frames.Next()
if frame.Func != f {
t.Errorf("frames.Next() got %+v want %+v", frame.Func, f)
}
}

View File

@@ -263,6 +263,9 @@ func addtimer(t *timer) {
when := t.when
// Disable preemption while using pp to avoid changing another P's heap.
mp := acquirem()
pp := getg().m.p.ptr()
lock(&pp.timersLock)
cleantimers(pp)
@@ -270,6 +273,8 @@ func addtimer(t *timer) {
unlock(&pp.timersLock)
wakeNetPoller(when)
releasem(mp)
}
// doaddtimer adds t to the current P's heap.

View File

@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build ios
// +build ios
package syscall
// Nosplit because it is called from forkAndExecInChild.

View File

@@ -213,9 +213,9 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys SetEndOfFile(handle Handle) (err error)
//sys GetSystemTimeAsFileTime(time *Filetime)
//sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff]
//sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error)
//sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error)
//sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error)
//sys createIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) = CreateIoCompletionPort
//sys getQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) = GetQueuedCompletionStatus
//sys postQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) = PostQueuedCompletionStatus
//sys CancelIo(s Handle) (err error)
//sys CancelIoEx(s Handle, o *Overlapped) (err error)
//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW
@@ -1209,3 +1209,31 @@ func Readlink(path string, buf []byte) (n int, err error) {
return n, nil
}
// Deprecated: CreateIoCompletionPort has the wrong function signature. Use x/sys/windows.CreateIoCompletionPort.
func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) {
return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt)
}
// Deprecated: GetQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.GetQueuedCompletionStatus.
func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error {
var ukey uintptr
var pukey *uintptr
if key != nil {
ukey = uintptr(*key)
pukey = &ukey
}
err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout)
if key != nil {
*key = uint32(ukey)
if uintptr(*key) != ukey && err == nil {
err = errorspkg.New("GetQueuedCompletionStatus returned key overflow")
}
}
return err
}
// Deprecated: PostQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.PostQueuedCompletionStatus.
func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error {
return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped)
}

View File

@@ -515,7 +515,7 @@ func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr
return
}
func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) {
func createIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) {
r0, _, e1 := Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0)
handle = Handle(r0)
if handle == 0 {
@@ -822,7 +822,7 @@ func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime,
return
}
func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) {
func getQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) {
r1, _, e1 := Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0)
if r1 == 0 {
err = errnoErr(e1)
@@ -954,7 +954,7 @@ func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err
return
}
func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) {
func postQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) {
r1, _, e1 := Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)

View File

@@ -71,6 +71,38 @@ func TestTBHelperParallel(t *T) {
}
}
func TestTBHelperLineNumer(t *T) {
var buf bytes.Buffer
ctx := newTestContext(1, newMatcher(regexp.MatchString, "", ""))
t1 := &T{
common: common{
signal: make(chan bool),
w: &buf,
},
context: ctx,
}
t1.Run("Test", func(t *T) {
helperA := func(t *T) {
t.Helper()
t.Run("subtest", func(t *T) {
t.Helper()
t.Fatal("fatal error message")
})
}
helperA(t)
})
want := "helper_test.go:92: fatal error message"
got := ""
lines := strings.Split(strings.TrimSpace(buf.String()), "\n")
if len(lines) > 0 {
got = strings.TrimSpace(lines[len(lines)-1])
}
if got != want {
t.Errorf("got output:\n\n%v\nwant:\n\n%v", got, want)
}
}
type noopWriter int
func (nw *noopWriter) Write(b []byte) (int, error) { return len(b), nil }

View File

@@ -509,6 +509,13 @@ func (c *common) frameSkip(skip int) runtime.Frame {
}
return prevFrame
}
// If more helper PCs have been added since we last did the conversion
if c.helperNames == nil {
c.helperNames = make(map[string]struct{})
for pc := range c.helperPCs {
c.helperNames[pcToName(pc)] = struct{}{}
}
}
if _, ok := c.helperNames[frame.Function]; !ok {
// Found a frame that wasn't inside a helper function.
return frame
@@ -521,14 +528,6 @@ func (c *common) frameSkip(skip int) runtime.Frame {
// and inserts the final newline if needed and indentation spaces for formatting.
// This function must be called with c.mu held.
func (c *common) decorate(s string, skip int) string {
// If more helper PCs have been added since we last did the conversion
if c.helperNames == nil {
c.helperNames = make(map[string]struct{})
for pc := range c.helperPCs {
c.helperNames[pcToName(pc)] = struct{}{}
}
}
frame := c.frameSkip(skip)
file := frame.File
line := frame.Line

View File

@@ -511,6 +511,22 @@ func TestZeroTimerStopPanics(t *testing.T) {
tr.Stop()
}
// Test that zero duration timers aren't missed by the scheduler. Regression test for issue 44868.
func TestZeroTimer(t *testing.T) {
if testing.Short() {
t.Skip("-short")
}
for i := 0; i < 1000000; i++ {
s := Now()
ti := NewTimer(0)
<-ti.C
if diff := Since(s); diff > 2*Second {
t.Errorf("Expected time to get value from Timer channel in less than 2 sec, took %v", diff)
}
}
}
// Benchmark timer latency when the thread that creates the timer is busy with
// other work and the timers must be serviced by other threads.
// https://golang.org/issue/38860

View File

@@ -178,7 +178,7 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64)
// If we're at the end of the known zone transitions,
// try the extend string.
if lo == len(tx)-1 && l.extend != "" {
if ename, eoffset, estart, eend, ok := tzset(l.extend, end, sec); ok {
if ename, eoffset, estart, eend, _, ok := tzset(l.extend, end, sec); ok {
return ename, eoffset, estart, eend
}
}
@@ -244,7 +244,7 @@ func (l *Location) firstZoneUsed() bool {
// We call this a tzset string since in C the function tzset reads TZ.
// The return values are as for lookup, plus ok which reports whether the
// parse succeeded.
func tzset(s string, initEnd, sec int64) (name string, offset int, start, end int64, ok bool) {
func tzset(s string, initEnd, sec int64) (name string, offset int, start, end int64, isDST, ok bool) {
var (
stdName, dstName string
stdOffset, dstOffset int
@@ -255,7 +255,7 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
stdOffset, s, ok = tzsetOffset(s)
}
if !ok {
return "", 0, 0, 0, false
return "", 0, 0, 0, false, false
}
// The numbers in the tzset string are added to local time to get UTC,
@@ -265,7 +265,7 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
if len(s) == 0 || s[0] == ',' {
// No daylight savings time.
return stdName, stdOffset, initEnd, omega, true
return stdName, stdOffset, initEnd, omega, false, true
}
dstName, s, ok = tzsetName(s)
@@ -278,7 +278,7 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
}
}
if !ok {
return "", 0, 0, 0, false
return "", 0, 0, 0, false, false
}
if len(s) == 0 {
@@ -287,19 +287,19 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
}
// The TZ definition does not mention ';' here but tzcode accepts it.
if s[0] != ',' && s[0] != ';' {
return "", 0, 0, 0, false
return "", 0, 0, 0, false, false
}
s = s[1:]
var startRule, endRule rule
startRule, s, ok = tzsetRule(s)
if !ok || len(s) == 0 || s[0] != ',' {
return "", 0, 0, 0, false
return "", 0, 0, 0, false, false
}
s = s[1:]
endRule, s, ok = tzsetRule(s)
if !ok || len(s) > 0 {
return "", 0, 0, 0, false
return "", 0, 0, 0, false, false
}
year, _, _, yday := absDate(uint64(sec+unixToInternal+internalToAbsolute), false)
@@ -313,10 +313,15 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
startSec := int64(tzruleTime(year, startRule, stdOffset))
endSec := int64(tzruleTime(year, endRule, dstOffset))
dstIsDST, stdIsDST := true, false
// Note: this is a flipping of "DST" and "STD" while retaining the labels
// This happens in southern hemispheres. The labelling here thus is a little
// inconsistent with the goal.
if endSec < startSec {
startSec, endSec = endSec, startSec
stdName, dstName = dstName, stdName
stdOffset, dstOffset = dstOffset, stdOffset
stdIsDST, dstIsDST = dstIsDST, stdIsDST
}
// The start and end values that we return are accurate
@@ -324,11 +329,11 @@ func tzset(s string, initEnd, sec int64) (name string, offset int, start, end in
// just the start and end of the year. That suffices for
// the only caller that cares, which is Date.
if ysec < startSec {
return stdName, stdOffset, abs, startSec + abs, true
return stdName, stdOffset, abs, startSec + abs, stdIsDST, true
} else if ysec >= endSec {
return stdName, stdOffset, endSec + abs, abs + 365*secondsPerDay, true
return stdName, stdOffset, endSec + abs, abs + 365*secondsPerDay, stdIsDST, true
} else {
return dstName, dstOffset, startSec + abs, endSec + abs, true
return dstName, dstOffset, startSec + abs, endSec + abs, dstIsDST, true
}
}
@@ -377,8 +382,10 @@ func tzsetOffset(s string) (offset int, rest string, ok bool) {
neg = true
}
// The tzdata code permits values up to 24 * 7 here,
// although POSIX does not.
var hours int
hours, s, ok = tzsetNum(s, 0, 24)
hours, s, ok = tzsetNum(s, 0, 24*7)
if !ok {
return 0, "", false
}
@@ -487,7 +494,7 @@ func tzsetRule(s string) (rule, string, bool) {
}
offset, s, ok := tzsetOffset(s[1:])
if !ok || offset < 0 {
if !ok {
return rule{}, "", false
}
r.time = offset

View File

@@ -247,8 +247,8 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
// This also avoids a panic later when we add and then use a fake transition (golang.org/issue/29437).
return nil, badData
}
zone := make([]zone, nzone)
for i := range zone {
zones := make([]zone, nzone)
for i := range zones {
var ok bool
var n uint32
if n, ok = zonedata.big4(); !ok {
@@ -257,22 +257,22 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
if uint32(int(n)) != n {
return nil, badData
}
zone[i].offset = int(int32(n))
zones[i].offset = int(int32(n))
var b byte
if b, ok = zonedata.byte(); !ok {
return nil, badData
}
zone[i].isDST = b != 0
zones[i].isDST = b != 0
if b, ok = zonedata.byte(); !ok || int(b) >= len(abbrev) {
return nil, badData
}
zone[i].name = byteString(abbrev[b:])
zones[i].name = byteString(abbrev[b:])
if runtime.GOOS == "aix" && len(name) > 8 && (name[:8] == "Etc/GMT+" || name[:8] == "Etc/GMT-") {
// There is a bug with AIX 7.2 TL 0 with files in Etc,
// GMT+1 will return GMT-1 instead of GMT+1 or -01.
if name != "Etc/GMT+0" {
// GMT+0 is OK
zone[i].name = name[4:]
zones[i].name = name[4:]
}
}
}
@@ -295,7 +295,7 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
}
}
tx[i].when = n
if int(txzones[i]) >= len(zone) {
if int(txzones[i]) >= len(zones) {
return nil, badData
}
tx[i].index = txzones[i]
@@ -314,7 +314,7 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
}
// Committed to succeed.
l := &Location{zone: zone, tx: tx, name: name, extend: extend}
l := &Location{zone: zones, tx: tx, name: name, extend: extend}
// Fill in the cache with information about right now,
// since that will be the most common lookup.
@@ -323,26 +323,27 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
l.cacheStart = tx[i].when
l.cacheEnd = omega
zoneIdx := tx[i].index
l.cacheZone = &l.zone[tx[i].index]
if i+1 < len(tx) {
l.cacheEnd = tx[i+1].when
} else if l.extend != "" {
// If we're at the end of the known zone transitions,
// try the extend string.
if name, _, estart, eend, ok := tzset(l.extend, l.cacheEnd, sec); ok {
if name, offset, estart, eend, isDST, ok := tzset(l.extend, l.cacheEnd, sec); ok {
l.cacheStart = estart
l.cacheEnd = eend
// Find the zone that is returned by tzset,
// the last transition is not always the correct zone.
for i, z := range l.zone {
if z.name == name {
zoneIdx = uint8(i)
break
// Find the zone that is returned by tzset to avoid allocation if possible.
if zoneIdx := findZone(l.zone, name, offset, isDST); zoneIdx != -1 {
l.cacheZone = &l.zone[zoneIdx]
} else {
l.cacheZone = &zone{
name: name,
offset: offset,
isDST: isDST,
}
}
}
}
l.cacheZone = &l.zone[zoneIdx]
break
}
}
@@ -350,6 +351,15 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
return l, nil
}
func findZone(zones []zone, name string, offset int, isDST bool) int {
for i, z := range zones {
if z.name == name && z.offset == offset && z.isDST == isDST {
return i
}
}
return -1
}
// loadTzinfoFromDirOrZip returns the contents of the file with the given name
// in dir. dir can either be an uncompressed zip file, or a directory.
func loadTzinfoFromDirOrZip(dir, name string) ([]byte, error) {

File diff suppressed because one or more lines are too long

View File

@@ -137,11 +137,13 @@ func trimOWS(x string) string {
// contains token amongst its comma-separated tokens, ASCII
// case-insensitively.
func headerValueContainsToken(v string, token string) bool {
v = trimOWS(v)
if comma := strings.IndexByte(v, ','); comma != -1 {
return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
for comma := strings.IndexByte(v, ','); comma != -1; comma = strings.IndexByte(v, ',') {
if tokenEqual(trimOWS(v[:comma]), token) {
return true
}
v = v[comma+1:]
}
return tokenEqual(v, token)
return tokenEqual(trimOWS(v), token)
}
// lowerASCII returns the ASCII lowercase version of b.

View File

@@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519
golang.org/x/crypto/hkdf
golang.org/x/crypto/internal/subtle
golang.org/x/crypto/poly1305
# golang.org/x/net v0.0.0-20201209123823-ac852fbbde11
# golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b
## explicit
golang.org/x/net/dns/dnsmessage
golang.org/x/net/http/httpguts

View File

@@ -262,8 +262,8 @@ func bitcompl32(a, b uint32) (n uint32) {
return n
}
// check direct operation on memory with constant source
func bitOpOnMem(a []uint32) {
// check direct operation on memory with constant and shifted constant sources
func bitOpOnMem(a []uint32, b, c, d uint32) {
// amd64:`ANDL\s[$]200,\s\([A-Z]+\)`
a[0] &= 200
// amd64:`ORL\s[$]220,\s4\([A-Z]+\)`
@@ -276,6 +276,12 @@ func bitOpOnMem(a []uint32) {
a[4] |= 0x4000
// amd64:`BTCL\s[$]13,\s20\([A-Z]+\)`,-`XORL`
a[5] ^= 0x2000
// amd64:`BTRL\s[A-Z]+,\s24\([A-Z]+\)`
a[6] &^= 1 << (b & 31)
// amd64:`BTSL\s[A-Z]+,\s28\([A-Z]+\)`
a[7] |= 1 << (c & 31)
// amd64:`BTCL\s[A-Z]+,\s32\([A-Z]+\)`
a[8] ^= 1 << (d & 31)
}
func bitcheckMostNegative(b uint8) bool {

View File

@@ -269,3 +269,14 @@ func f28369(n int) int {
return 1 + f28369(n-1)
}
// Issue 44614: parameters that flow to a heap-allocated result
// parameter must be recorded as a heap-flow rather than a
// result-flow.
// N.B., must match "leaking param: p",
// but *not* "leaking param: p to result r level=0".
func f(p *int) (r *int) { // ERROR "leaking param: p$" "moved to heap: r"
sink4 = &r
return p
}

View File

@@ -48,6 +48,14 @@ func f() int {
return test("return", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
}
type S struct{}
//go:noinline
//go:uintptrescapes
func (S) test(s string, p, q uintptr, rest ...uintptr) int {
return test(s, p, q, rest...)
}
func main() {
test("normal", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
<-done
@@ -60,6 +68,29 @@ func main() {
}()
<-done
func() {
for {
defer test("defer in for loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
break
}
}()
<-done
func() {
s := &S{}
defer s.test("method call", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
}()
<-done
func() {
s := &S{}
for {
defer s.test("defer method loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
break
}
}()
<-done
f()
<-done
}

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 a
func F() (_ *int) { return nil }

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 b
import "./a"
var _ = a.F()

View File

@@ -0,0 +1,7 @@
// compiledir
// 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 ignored

View File

@@ -0,0 +1,40 @@
// compile
// 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.
// This test case caused a panic in the compiler's DWARF gen code.
// Note to future maintainers of this code:
//
// ** Do NOT run gofmt when editing this file **
//
// In order for the buggy behavior to be triggered in the compiler,
// we need to have a the function of interest all on one gigantic line.
package a
type O interface{}
type IO int
type OS int
type A struct {
x int
}
// original versions of the two function
func (p *A) UO(o O) {
p.r(o, o)
}
func (p *A) r(o1, o2 O) {
switch x := o1.(type) {
case *IO:
p.x = int(*x)
case *OS:
p.x = int(*x + 2)
}
}
// see note above about the importance of all this code winding up on one line.
var myverylongname0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 int ; func (p *A) UO2(o O) { p.r2(o, o); }; func (p *A) r2(o1, o2 O) { switch x := o1.(type) { case *IO: p.x = int(*x); case *OS: p.x = int(*x + 2); } }

View File

@@ -0,0 +1,29 @@
// run
// 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
//go:noinline
func f(c bool) int {
b := true
x := 0
y := 1
for b {
b = false
y = x
x = 2
if c {
return 3
}
}
return y
}
func main() {
if got := f(false); got != 0 {
panic(got)
}
}