Compare commits

...

47 Commits

Author SHA1 Message Date
Gopher Robot
5d5ed57b13 [release-branch.go1.19] go1.19.3
Change-Id: I167308920eeb7480efb626ce75f777a335e870b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/446958
Run-TryBot: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-11-01 16:45:23 +00:00
Damien Neil
2a7adf4ccd [release-branch.go1.19] syscall, os/exec: reject environment variables containing NULs
Check for and reject environment variables containing NULs.

The conventions for passing environment variables to subprocesses
cause most or all systems to interpret a NUL as a separator. The
syscall package rejects environment variables containing a NUL
on most systems, but erroneously did not do so on Windows. This
causes an environment variable such as "FOO=a\x00BAR=b" to be
interpreted as "FOO=a", "BAR=b".

Check for and reject NULs in environment variables passed to
syscall.StartProcess on Windows.

Add a redundant check to os/exec as extra insurance.

Updates #56284
Fixes #56328
Fixes CVE-2022-41716

Change-Id: I2950e2b0cb14ebd26e5629be1521858f66a7d4ae
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1609434
Run-TryBot: Damien Neil <dneil@google.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-by: Roland Shoemaker <bracewell@google.com>
TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
(cherry picked from commit 845accdebb2772c5344ed0c96df9910f3b02d741)
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1617553
Run-TryBot: Tatiana Bradley <tatianabradley@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/446879
Reviewed-by: Tatiana Bradley <tatiana@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-11-01 16:15:30 +00:00
Cuong Manh Le
0618956b31 [release-branch.go1.19] cmd/compile: fix missing walk pass for static initialization slice
CL 403995 fixed static init of literal contains dynamic exprs, by
ensuring their init are ordered properly. However, we still need to walk
the generated init codes before appending to parent init. Otherwise,
codes that requires desugaring will be unhandled, causing the compiler
backend crashing.

Fixes #56106

Change-Id: Ic25fd4017473f5412c8e960a91467797a234edfd
Reviewed-on: https://go-review.googlesource.com/c/go/+/440455
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/441995
Reviewed-by: Joedian Reid <joedian@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2022-10-24 19:05:12 +00:00
Cuong Manh Le
e73130cf45 [release-branch.go1.19] all: prevent fakePC overflow on 386 in libfuzzer mode
fakePC uses hash.Sum32, which returns an uint32. However, libfuzzer
trace/hook functions declare fakePC argument as int, causing overflow on
386 archs.

Fixing this by changing fakePC argument to uint to prevent the overflow.

Fixes #56168

Change-Id: I3994c461319983ab70065f90bf61539a363e0a2a
Reviewed-on: https://go-review.googlesource.com/c/go/+/441996
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/442435
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2022-10-24 17:29:11 +00:00
Michael Pratt
0cc20ecc28 [release-branch.go1.19] runtime: always keep global reference to mp until mexit completes
Ms are allocated via standard heap allocation (`new(m)`), which means we
must keep them alive (i.e., reachable by the GC) until we are completely
done using them.

Ms are primarily reachable through runtime.allm. However, runtime.mexit
drops the M from allm fairly early, long before it is done using the M
structure. If that was the last reference to the M, it is now at risk of
being freed by the GC and used for some other allocation, leading to
memory corruption.

Ms with a Go-allocated stack coincidentally already keep a reference to
the M in sched.freem, so that the stack can be freed lazily. This
reference has the side effect of keeping this Ms reachable. However, Ms
with an OS stack skip this and are at risk of corruption.

Fix this lifetime by extending sched.freem use to all Ms, with the value
of mp.freeWait determining whether the stack needs to be freed or not.

For #56243.
Fixes #56309.

Change-Id: Ic0c01684775f5646970df507111c9abaac0ba52e
Reviewed-on: https://go-review.googlesource.com/c/go/+/443716
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
(cherry picked from commit e252dcf9d3)
Reviewed-on: https://go-review.googlesource.com/c/go/+/443815
Reviewed-by: Austin Clements <austin@google.com>
2022-10-24 17:28:39 +00:00
Bryan C. Mills
8d10cc0261 [release-branch.go1.19] cmd/go/internal/modload: update TestQueryImport to pass with tagged versions of x/net
For #48523.

Change-Id: Ied35d15462cbae1002e1db1e6e119a6c9f8323da
Reviewed-on: https://go-review.googlesource.com/c/go/+/444156
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
(cherry picked from commit 3e6ca3a506)
Reviewed-on: https://go-review.googlesource.com/c/go/+/444435
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-10-20 15:56:34 +00:00
Gopher Robot
895664482c [release-branch.go1.19] go1.19.2
Change-Id: Ia5de3a0fa07f212c5c19f9e01b0ed2cfab739e95
Reviewed-on: https://go-review.googlesource.com/c/go/+/438598
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
Run-TryBot: Gopher Robot <gobot@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-10-04 17:43:19 +00:00
Russ Cox
645abfe529 [release-branch.go1.19] regexp: limit size of parsed regexps
Set a 128 MB limit on the amount of space used by []syntax.Inst
in the compiled form corresponding to a given regexp.

Also set a 128 MB limit on the rune storage in the *syntax.Regexp
tree itself.

Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting this issue.

Fixes CVE-2022-41715.
Updates #55949.
Fixes #55951.

Change-Id: Ia656baed81564436368cf950e1c5409752f28e1b
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1592047
Reviewed-by: Julie Qiu <julieqiu@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Run-TryBot: Roland Shoemaker <bracewell@google.com>
TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/438499
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Carlos Amedee <carlos@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2022-10-04 17:08:16 +00:00
Damien Neil
4fa773cdef [release-branch.go1.19] archive/tar: limit size of headers
Set a 1MiB limit on special file blocks (PAX headers, GNU long names,
GNU link names), to avoid reading arbitrarily large amounts of data
into memory.

Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting
this issue.

Fixes CVE-2022-2879
Updates #54853
Fixes #55926

Change-Id: I85136d6ff1e0af101a112190e027987ab4335680
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1565555
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Run-TryBot: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Roland Shoemaker <bracewell@google.com>
(cherry picked from commit 6ee768cef6b82adf7a90dcf367a1699ef694f3b2)
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1591053
Reviewed-by: Julie Qiu <julieqiu@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/438498
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Carlos Amedee <carlos@golang.org>
2022-10-04 17:07:45 +00:00
Damien Neil
f6d844510d [release-branch.go1.19] net/http/httputil: avoid query parameter smuggling
Query parameter smuggling occurs when a proxy's interpretation
of query parameters differs from that of a downstream server.
Change ReverseProxy to avoid forwarding ignored query parameters.

Remove unparsable query parameters from the outbound request

   * if req.Form != nil after calling ReverseProxy.Director; and
   * before calling ReverseProxy.Rewrite.

This change preserves the existing behavior of forwarding the
raw query untouched if a Director hook does not parse the query
by calling Request.ParseForm (possibly indirectly).

Fixes #55843
For #54663
For CVE-2022-2880

Change-Id: If1621f6b0e73a49d79059dae9e6b256e0ff18ca9
Reviewed-on: https://go-review.googlesource.com/c/go/+/432976
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/433735
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2022-09-28 16:36:28 +00:00
Cuong Manh Le
2614985ef7 [release-branch.go1.19] cmd/compile/internal/typebits: relax alignment check
Now we have 8-byte alignment types on 32-bit system, so in some rare
case, e.g, generated wrapper for embedded interface, the function
argument may need more than 4 byte alignment. We could pad somehow, but
this is a rare case which makes it hard to ensure that we've got it right.

So relaxing the check for argument and return value region of the stack.

Fixes #55152

Change-Id: I34986e17a920254392a39439ad3dcb323da2ea8d
Reviewed-on: https://go-review.googlesource.com/c/go/+/431098
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/431895
2022-09-21 22:25:31 +00:00
Matthew Dempsky
3747bb2482 [release-branch.go1.19] cmd/compile: skip emitting dictionaries with missing method expressions
The nounified frontend currently tries to construct dictionaries that
correspond to invalid instantiations (i.e., instantiations T[X] where
X does not satisfy the constraints specified on T's type parameter).
As a consequence, we may fail to find method expressions needed by the
dictionary.

The real fix for this is to avoid creating those dictionaries in the
first place, because they should never actually be needed at runtime.
But that seems scary for a backport: we've repeatedly attempted to
backport generics fixes, which have fixed one issue but introduced
another.

This CL is a minimally invasive solution to #54225, which avoids the
ICE by instead skipping emitting the invalid dictionary. If the
dictionary ends up not being needed (which I believe will always be
the case), then the linker's reachability analysis will simply ignore
its absence.

Or worst case, if the dictionary *is* reachable somehow, we've simply
turned an ICE into a link-time missing symbol failure. That's not
great for user experience, but it seems like a small trade off to
avoid risking breaking any other currently working code.

Fixes #55270.

Change-Id: Ic379696079f4729b1dd6a66994a58cca50281a84
Reviewed-on: https://go-review.googlesource.com/c/go/+/429655
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/429895
Reviewed-by: Keith Randall <khr@google.com>
2022-09-21 21:03:45 +00:00
Cherry Mui
11728b38dc [release-branch.go1.19] cmd/link: suppress -no_pie deprecation warning on darwin
Apparently the new darwin linker starts to emit a warning about
-no_pie deprecation. Maybe we want to switch to PIE by default.
For now, suppress the warning. This also makes it easier for
backporting to previous releases.

Fixes #55114.
Updates #55112, #54482.

Change-Id: I1a3b74c237a9d00ec3b030fc3a9940a31e5cd37e
Reviewed-on: https://go-review.googlesource.com/c/go/+/430937
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 706d84fca2)
Reviewed-on: https://go-review.googlesource.com/c/go/+/431517
2022-09-21 21:01:06 +00:00
Cherry Mui
064f34f048 [release-branch.go1.19] cmd/link: stop passing -pagezero_size to darwin linker
We added -pagezero_size in CL 72730, where it was intented for iOS.
The current code passes it only on macOS/AMD64 instead. It is not
really necessary there. Also, the new darwin linker starts to emit
a warning about deprecation of the flag. Stop passing it.

For #55114.
Updates #55112, #54482.

Change-Id: If9db7a1645c37d4284e48f075856912df8d8c1a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/430936
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
(cherry picked from commit 5231ba2f05)
Reviewed-on: https://go-review.googlesource.com/c/go/+/431515
Reviewed-by: Austin Clements <austin@google.com>
2022-09-21 20:30:26 +00:00
Robert Griesemer
a366ed5982 [release-branch.go1.19] go/types, types2: allow (string...) signature with NewSignatureType
Includes cases where the core type of the variadic parameter is
a slice or bytestring. Permits a client to create the signature
for various instantiations of append.

Fixes #55149.

Change-Id: I0f4983eb00c088cbe1d87954ee0b2df0ccc3bc49
Reviewed-on: https://go-review.googlesource.com/c/go/+/430455
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/431935
2022-09-21 20:26:19 +00:00
Keith Randall
4b0e03da0e [release-branch.go1.19] cmd/compile: avoid using destination pointer base type in memmove optimization
The type of the source and destination of a memmove call isn't
always accurate. It will always be a pointer (or an unsafe.Pointer), but
the base type might not be accurate. This comes about because multiple
copies of a pointer with different base types are coalesced into a single value.

In the failing example, the IData selector of the input argument is a
*[32]byte in one branch of the type switch, and a *[]byte in the other branch.
During the expand_calls pass both IDatas become just copies of the input
register. Those copies are deduped and an arbitrary one wins (in this case,
*[]byte is the unfortunate winner).

Generally an op v can rely on v.Type during rewrite rules. But relying
on v.Args[i].Type is discouraged.

Fixes #55124

Change-Id: I348fd9accf2058a87cd191eec01d39cda612f120
Reviewed-on: https://go-review.googlesource.com/c/go/+/431496
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
(cherry picked from commit e283473ebb)
Reviewed-on: https://go-review.googlesource.com/c/go/+/431917
2022-09-21 20:24:34 +00:00
Matthew Dempsky
225bcec98b [release-branch.go1.19] cmd/compile/internal/inline: fix latent CalleeEffects issue
ir.ClosureExpr implements ir.InitNode, so ir.InitExpr can prepend init
statements to it. However, CalleeEffects wasn't aware of this and
could cause the init statements to get dropped when inlining a call to
a closure.

This isn't an issue today, because we don't create closures with init
statements. But I ran into this within unified IR.

Easy and robust solution: just take advantage that ir.TakeInit can
handle any node.

Fixes #54917.

Change-Id: Ica05fbf6a8c5be4b11927daf84491a1140da5431
Reviewed-on: https://go-review.googlesource.com/c/go/+/422196
Reviewed-by: Than McIntosh <thanm@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/429896
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2022-09-19 21:52:24 +00:00
Austin Clements
19d792c1eb [release-branch.go1.19] runtime/cgo: add -fno-stack-protector to CFLAGS
Some compilers default to having -fstack-protector on, which breaks
when using internal linking because the linker doesn't know how to
find the support functions.

Fixes #54764

(Original fix by Ian Lance Taylor <iant@golang.org>)

Change-Id: I2d8cb7fb780de4cd37314af3957b8f429b1e4b70
Reviewed-on: https://go-review.googlesource.com/c/go/+/429138
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
2022-09-13 17:33:29 +00:00
Damien Neil
00ece11be1 [release-branch.go1.19] all: upgrade golang.org/x/net to v0.0.0-20220907013720-d52c520e3766
Restore vendoring after go1.19.1 security release.

For #54376

Change-Id: Ie1512aa2bf77e5f448893c89e4841cb14896da9b
Reviewed-on: https://go-review.googlesource.com/c/go/+/429317
Reviewed-by: Carlos Amedee <carlos@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-09-09 17:18:16 +00:00
Gopher Robot
4a4127bccc [release-branch.go1.19] go1.19.1
Change-Id: Iada84ba9c8e727e89cfb4ac21a27e085fa7f60e9
Reviewed-on: https://go-review.googlesource.com/c/go/+/428697
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Gopher Robot <gobot@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
2022-09-06 16:17:26 +00:00
Damien Neil
9cfe4e258b [release-branch.go1.19] net/http: update bundled golang.org/x/net/http2
Disable cmd/internal/moddeps test, since this update includes PRIVATE
track fixes.

Fixes CVE-2022-27664
Fixes #54376
For #54658

Change-Id: I747900a66d7276e7d0bd246cd8cd0da95305c3ca
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1554417
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/428655
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Tatiana Bradley <tatiana@golang.org>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-09-06 15:49:24 +00:00
Cherry Mui
86e9e0ea87 [release-branch.go1.19 cmd/compile: align stack offset to alignment larger than PtrSize
In typebits.Set we check that the offset is a multiple of the
alignment, which makes perfect sense. But for values like
atomic.Int64, which has 8-byte alignment even on 32-bit platforms
(i.e. the alignment is larger than PtrSize), if it is on stack it
may be under-aligned, as the stack frame is only PtrSize aligned.

Normally we would prevent such values on stack, as the escape
analysis force values with higher alignment to heap. But for a
composite literal assignment like x = AlignedType{...}, the
compiler creates an autotmp for the RHS then copies it to the LHS.
The autotmp is on stack and may be under-aligned. Currently this
may cause an ICE in the typebits.Set check.

This CL makes it align the _offset_ of the autotmp to 8 bytes,
which satisfies the check. Note that this is actually lying: the
actual address at run time may not necessarily be 8-byte
aligned as we only align SP to 4 bytes.

The under-alignment is probably okay. The only purpose for the
autotmp is to copy the value to the LHS, and the copying code we
generate (at least currently) doesn't care the alignment beyond
stack alignment.

Updates #54638.
Fixes #54697.

Change-Id: I13c16afde2eea017479ff11dfc24092bcb8aba6a
Reviewed-on: https://go-review.googlesource.com/c/go/+/425256
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 1211a62bdc)
Reviewed-on: https://go-review.googlesource.com/c/go/+/425935
2022-08-31 16:31:45 +00:00
Cherry Mui
0bba4d2fe6 [release-branch.go1.19] runtime: mark morestack_noctxt SPWRITE on LR architectures
On LR architectures, morestack (and morestack_noctxt) are called
with a special calling convention, where the caller doesn't save
LR on stack but passes it as a register, which morestack will save
to g.sched.lr. The stack unwinder currently doesn't understand it,
and would fail to unwind from it. morestack already writes SP (as
it switches stack), but morestack_noctxt (which tailcalls
morestack) doesn't. If a profiling signal lands right in
morestack_noctxt, the unwinder will try to unwind the stack and
go off, and possibly crash.

Marking morestack_noctxt SPWRITE stops the unwinding.

Ideally we could teach the unwinder about the special calling
convention, or change the calling convention to be less special
(so the unwinder doesn't need to fetch a register from the signal
context). This is a stop-gap solution, to stop the unwinder from
crashing.

Updates #54332.
Fixes #54675.

Change-Id: I75295f2e27ddcf05f1ea0b541aedcb9000ae7576
Reviewed-on: https://go-review.googlesource.com/c/go/+/425396
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
(cherry picked from commit e4be2ac79f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/425615
2022-08-31 16:31:38 +00:00
Paul E. Murphy
823e5d8afa [release-branch.go1.19] runtime: fix ppc64 startup on newer linux kernels
R0 needs to be cleared at startup as it may not always be cleared
by the kernel on newer kernels.

Fixes #54665

Change-Id: Id7055699aaa8d8b193b7e3e784f075ce29ac3f1d
Reviewed-on: https://go-review.googlesource.com/c/go/+/424927
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Paul Murphy <murp@ibm.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/425394
Reviewed-by: Ian Lance Taylor <iant@google.com>
2022-08-31 16:31:23 +00:00
Cuong Manh Le
11033eac90 [release-branch.go1.19] cmd/compile: only inline method wrapper if method don't contain closures
CL 327871 changes methodWrapper to always perform inlining after global
escape analysis. However, inlining the method may reveal closures, which
require walking all function bodies to decide whether to capture free
variables by value or by ref.

To fix it, just not doing inline if the method contains any closures.

Fixes #54726

Change-Id: I4b0255b86257cc6fe7e5fafbc545cc5cff9113e1
Reviewed-on: https://go-review.googlesource.com/c/go/+/426334
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/426160
2022-08-31 16:23:03 +00:00
Zeke Lu
4580d6dc6d [release-branch.go1.19] cmd/go/internal/imports: recognize "unix" build tag
For #20322
For #51572
Updates #54712
Fixes #54736

Change-Id: I22fcfa820e83323bfdf1a40deee7286240f02b3e
GitHub-Last-Rev: cd2c6536b0
GitHub-Pull-Request: golang/go#54716
Reviewed-on: https://go-review.googlesource.com/c/go/+/426296
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
(cherry picked from commit 3c6a5cdb9a)
Reviewed-on: https://go-review.googlesource.com/c/go/+/426814
Run-TryBot: Bryan Mills <bcmills@google.com>
2022-08-30 20:08:38 +00:00
Jeremy Quirke
62aa93010d [release-branch.go1.19] cmd/link: fix trampolines breaking DWARF line info
When trampolines are needed (e.g. Darwin ARM64), the DWARF LPT (Line
Program Table - see DWARF section 6.1) generation fails because the
replacement symbols are marked as external symbols and skipped during
the DWARF LPT generation phase.

Fixes #54406

Change-Id: I6c93f5378f50e5edf30d5121402a48214abb1ce2
GitHub-Last-Rev: 085bbc55db
GitHub-Pull-Request: golang/go#54321
Reviewed-on: https://go-review.googlesource.com/c/go/+/422154
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 2340d37179)
Reviewed-on: https://go-review.googlesource.com/c/go/+/423214
Run-TryBot: Cherry Mui <cherryyz@google.com>
2022-08-29 20:10:29 +00:00
Filippo Valsorda
15b234b830 [release-branch.go1.19] crypto/tls: support ECDHE when ec_point_formats is missing
Updates #49126
Fixes #54643

Change-Id: I9d6f6392b1a6748bdac1d2c6371b22d75829a2b6
Reviewed-on: https://go-review.googlesource.com/c/go/+/425295
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Alex Scheel <alex.scheel@hashicorp.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: David Chase <drchase@google.com>
(cherry picked from commit 1df2a03b17)
Reviewed-on: https://go-review.googlesource.com/c/go/+/425635
2022-08-29 19:17:57 +00:00
Zeke Lu
4da9d6aa10 [release-branch.go1.19] cmd/go/internal/imports: include ToolTags in the Tags map
This fixes a regression introduced when the "race" mode tag was moved to
the ToolTags field in CL 358539.

Fixes #54660
Updates #54468

Change-Id: I107771948a4fe9d743cc13d1c15f324212b08e03
GitHub-Last-Rev: d211e351ef
GitHub-Pull-Request: golang/go#54618
Reviewed-on: https://go-review.googlesource.com/c/go/+/425154
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 6ba2674ddc)
Reviewed-on: https://go-review.googlesource.com/c/go/+/426434
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-08-29 19:17:28 +00:00
Bryan C. Mills
4b1c16cc45 [release-branch.go1.19] cmd/go: avoid registering AtExit handlers in tests
Ever since 'go build' was added (in CL 5483069), it has used an atexit
handler to clean up working directories.

CL 154109 introduced 'cc' command to the script test framework that
called Init on a builder once per invocation. Unfortunately, since
base.AtExit is unsynchronized, the Init added there caused any script
that invokes that command to be unsafe for concurrent use.

This change fixes the race by having the 'cc' command pass in its
working directory instead of allowing the Builder to allocate one.
Following modern Go best practices, it also replaces the in-place Init
method (which is prone to typestate and aliasing bugs) with a
NewBuilder constructor function.

Updates #54423.
Fixes #54637.

Change-Id: I8fc2127a7d877bb39a1174e398736bb51d03d4d2
Reviewed-on: https://go-review.googlesource.com/c/go/+/425205
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
(cherry picked from commit d5aa088d82)
Reviewed-on: https://go-review.googlesource.com/c/go/+/425207
2022-08-29 19:15:41 +00:00
Filippo Valsorda
2553a09e31 [release-branch.go1.19] crypto/x509: don't panic marshaling invalid ECDSA keys
MarshalPKIXPublicKey, CreateCertificate, CreateCertificateRequest,
MarshalECPrivateKey, and MarshalPKCS8PrivateKey started raising a panic
when encoding an invalid ECDSA key in Go 1.19. Since they have an error
return value, they should return an error instead.

Updates #54288
Fixes #54295

Change-Id: Iba132cd2f890ece36bb7d0396eb9a9a77bdb81df
Reviewed-on: https://go-review.googlesource.com/c/go/+/422298
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
(cherry picked from commit f64f12f0b3)
Reviewed-on: https://go-review.googlesource.com/c/go/+/425634
2022-08-29 19:14:33 +00:00
Damien Neil
2833550891 [release-branch.go1.19] net/url: consistently remove ../ elements in JoinPath
JoinPath would fail to remove relative elements from the start of
the path when the first path element is "".

In addition, JoinPath would return the original path unmodified
when provided with no elements to join, violating the documented
behavior of always cleaning the resulting path.

Correct both these cases.

    JoinPath("http://go.dev", "../go")
    // before: http://go.dev/../go
    // after:  http://go.dev/go

    JoinPath("http://go.dev/../go")
    // before: http://go.dev/../go
    // after:  http://go.dev/go

For #54385.
Fixes #54635.
Fixes CVE-2022-32190.

Change-Id: I6d22cd160d097c50703dd96e4f453c6c118fd5d9
Reviewed-on: https://go-review.googlesource.com/c/go/+/423514
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
(cherry picked from commit 0765da5884)
Reviewed-on: https://go-review.googlesource.com/c/go/+/425357
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-08-29 19:13:49 +00:00
Bryan C. Mills
d2bcb22ce0 [release-branch.go1.19] cmd/go: avoid overwriting cached Origin metadata
Fixes #54633.
Updates #54631.

Change-Id: I17d2fa282642aeb1ae2a6e29a0756b8960bea34b
Reviewed-on: https://go-review.googlesource.com/c/go/+/425255
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
(cherry picked from commit e3004d96b6899945d76e5dd373756324c8ff98fb)
Reviewed-on: https://go-review.googlesource.com/c/go/+/425211
2022-08-29 19:13:20 +00:00
Keith Randall
d39fd4f2b7 [release-branch.go1.19] cmd/compile: handle partially overlapping assignments
Normally, when moving Go values of type T from one location to another,
we don't need to worry about partial overlaps. The two Ts must either be
in disjoint (nonoverlapping) memory or in exactly the same location.
There are 2 cases where this isn't true:
 1) Using unsafe you can arrange partial overlaps.
 2) Since Go 1.17, you can use a cast from a slice to a ptr-to-array.
    https://go.dev/ref/spec#Conversions_from_slice_to_array_pointer
    This feature can be used to construct partial overlaps of array types.
      var a [3]int
      p := (*[2]int)(a[:])
      q := (*[2]int)(a[1:])
      *p = *q
We don't care about solving 1. Or at least, we haven't historically
and no one has complained.
For 2, we need to ensure that if there might be partial overlap,
then we can't use OpMove; we must use memmove instead.
(memmove handles partial overlap by copying in the correct
direction. OpMove does not.)

Note that we have to be careful here not to introduce a call when
we're marshaling arguments to a call or unmarshaling results from a call.

Fixes #54629

Change-Id: I1ca6aba8041576849c1d85f1fa33ae61b80a373d
Reviewed-on: https://go-review.googlesource.com/c/go/+/425076
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
(cherry picked from commit 332a5981d0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/425234
2022-08-29 19:12:54 +00:00
Ian Lance Taylor
f1b38e8b41 [release-branch.go1.19] misc/cgo/testcarchive: permit SIGQUIT for TestSignalForwardingExternal
Occasionally the signal will be sent to a Go thread, which will cause
the program to exit with SIGQUIT rather than SIGSEGV.

Add TestSignalForwardingGo to test the case where the signal is
expected to be delivered to a Go thread.

This is a roll forward of CL 419014 which was rolled back in CL 424954.
This CL differs from 419014 in that it skips TestSignalForwardingGo
on darwin-amd64.

For #53907
Fixes #54239

Change-Id: I5df3fd610c068df3bd48d9b3d7a9379248b97999
Reviewed-on: https://go-review.googlesource.com/c/go/+/425002
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
(cherry picked from commit d05ce23756)
Reviewed-on: https://go-review.googlesource.com/c/go/+/425487
Reviewed-by: David Chase <drchase@google.com>
2022-08-29 19:08:33 +00:00
Cuong Manh Le
2b59f4dd19 [release-branch.go1.19] cmd/compile: correct alignment of atomic.Int64
Same as CL 417555, but for cmd/compile.

Fixes #54235

Change-Id: I4cc6deaf0a87c952f636888b4ab73f81a44bfebd
Reviewed-on: https://go-review.googlesource.com/c/go/+/420975
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/422034
Reviewed-by: Than McIntosh <thanm@google.com>
2022-08-29 19:08:15 +00:00
Michael Pratt
2375ef8df6 [release-branch.go1.19] cmd: vendor github.com/google/pprof to fix mangled type parameter symbol names
Updates github.com/google/pprof to bring in the commit from
https://github.com/google/pprof/pull/717 which fixes mangled
symbol names for type parameters.

For #54105
Fixes #54420

Change-Id: I01af9f780aba3338b960a03b30906a23642e4448
Reviewed-on: https://go-review.googlesource.com/c/go/+/420234
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Than McIntosh <thanm@google.com>
(cherry picked from commit cd9cd925bb)
Reviewed-on: https://go-review.googlesource.com/c/go/+/423356
Run-TryBot: Michael Pratt <mpratt@google.com>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
2022-08-19 18:40:16 +00:00
Cuong Manh Le
16c2b3615a [release-branch.go1.19] cmd/compile: fix wrong typeparams for selector expr with embedded generic type
For selector expression "x.M" where "M" is a promoted method, irgen is using
the type of receiver "x" for determining the typeparams for instantiation.
However, because M is a promoted method, so its associated receiver is
not "x", but "x.T" where "T" is the embedded field of "x". That casues a
mismatch when converting non-shape types arguments.

Fixing it by using the actual receiver which has the method, instead of
using the base receiver.

Fixes #54243

Change-Id: I1836fc422d734df14e9e6664d4bd014503960bfc
Reviewed-on: https://go-review.googlesource.com/c/go/+/419294
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/423114
Reviewed-by: Carlos Amedee <carlos@golang.org>
2022-08-17 15:12:12 +00:00
Matthew Dempsky
3c200d6c81 [release-branch.go1.19] cmd/compile: fix import/export of ODYNAMICDOTTYPE
The RType field isn't needed when performing type assertions from
non-empty interface types, because we use the ITab field instead. But
the inline body exporter didn't know to expect this.

It's possible we could use a single bool to distinguish whether
we're serializing the RType or ITab field, but using two is simpler
and seems safer.

Fixes #54309.

Change-Id: I9ddac72784fb2241fee0a0dee30493d868a2c259
Reviewed-on: https://go-review.googlesource.com/c/go/+/421755
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
(cherry picked from commit 0c4db1e347)
Reviewed-on: https://go-review.googlesource.com/c/go/+/421715
Reviewed-by: Than McIntosh <thanm@google.com>
2022-08-11 12:53:59 +00:00
Gopher Robot
43456202a1 [release-branch.go1.19] go1.19
Change-Id: Iea643b04a7eea7c882d7eec481b67e4ecc08a559
Reviewed-on: https://go-review.googlesource.com/c/go/+/420834
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2022-08-02 16:54:47 +00:00
Matthew Dempsky
56ec1163e3 [release-branch.go1.19] test: improve generic type assertion test
The test added in CL 420674 only tested that the type assertions
compiled at all. This CL changes it into a run test to make sure the
type assertions compile and also run correctly.

Updates #54135.

Change-Id: Id17469faad1bb55ff79b0bb4163ef50179330033
Reviewed-on: https://go-review.googlesource.com/c/go/+/420421
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
(cherry picked from commit f2a9f3e2e0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/420675
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2022-08-01 22:43:15 +00:00
Wayne Zuo
ec7bf2007e [release-branch.go1.19] cmd/compile: fix wrong dict pass condition for type assertions
Updates #54135.

Change-Id: I2b27af8124014b2699ea44bdc765e1fb8f6c8028
Reviewed-on: https://go-review.googlesource.com/c/go/+/420394
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
(cherry picked from commit 27038b70f8)
Reviewed-on: https://go-review.googlesource.com/c/go/+/420674
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
2022-08-01 22:42:56 +00:00
Dmitri Shuralyov
46ab46c7c5 [release-branch.go1.19] all: merge master (e99f53f) into release-branch.go1.19
Merge List:

+ 2022-08-01 e99f53fed9 doc: move Go 1.19 release notes to x/website
+ 2022-08-01 8b13a073a1 doc: mention removal of cmd/compile's -importmap and -installsuffix flags
+ 2022-08-01 e95fd4c238 doc/go1.19: fix typo: EM_LONGARCH -> EM_LOONGARCH
+ 2022-08-01 dee3efd9f8 doc/go1.19: fix a few links that were missing trailing slashes
+ 2022-07-30 f32519e5fb runtime: fix typos
+ 2022-07-29 9a2001a8cc cmd/dist: always pass -short=true with -quick
+ 2022-07-28 5c8ec89cb5 doc/go1.19: minor adjustments and links
+ 2022-07-28 417be37048 doc/go1.19: improve the loong64 release notes
+ 2022-07-28 027855e8d8 os/exec: add GODEBUG setting to opt out of ErrDot changes
+ 2022-07-27 462b78fe70 misc/cgo/test: use fewer threads in TestSetgidStress in long mode
+ 2022-07-27 055113ef36 math/big: check buffer lengths in GobDecode
+ 2022-07-27 4248146154 net: document UDPConn.ReadFromUDPAddrPort's AddrPort result more
+ 2022-07-26 faf4e97200 net: fix WriteMsgUDPAddrPort addr handling
+ 2022-07-26 caa225dd29 doc/go1.19: note that updated race syso files require GNU ld 2.26
+ 2022-07-26 ceefd3a37b bytes: document that Reader.Reset affects the result of Size
+ 2022-07-26 3e97294663 runtime/cgo: use frame address to set g0 stack bound
+ 2022-07-25 24dc27a3c0 cmd/compile: fix blank label code
+ 2022-07-25 9fcc8b2c1e runtime: fix runtime.Breakpoint() on windows/arm64
+ 2022-07-25 795a88d0c3 cmd/go: add space after comma in 'go help test'
+ 2022-07-25 9eb3992ddd doc/go1.19: minor fixes
+ 2022-07-25 dcea1ee6e3 time: clarify documentation for allowed formats and add tests to prove them
+ 2022-07-25 37c8112b82 internal/fuzz: fix typo in function comments
+ 2022-07-25 850d547d2d doc/go1.19: expand crypto release notes
+ 2022-07-24 64f2829c9c runtime: fix typo in function comments
+ 2022-07-24 2ff563a00e cmd/compile/internal/noder: correct spelling errors for instantiation
+ 2022-07-22 c5da4fb7ac cmd/compile: make jump table symbol local
+ 2022-07-22 774fa58d1d A+C: delete AUTHORS and CONTRIBUTORS
+ 2022-07-21 2d655fb15a unsafe: document when Sizeof/Offsetof/Alignof are not constant
+ 2022-07-21 076c3d7f07 net/http: remove accidental heading in Head documentation
+ 2022-07-21 c4a6d3048b cmd/dist: enable race detector test on S390X
+ 2022-07-20 244c8b0500 cmd/cgo: allow cgo to pass strings or []bytes bigger than 1<<30
+ 2022-07-20 df38614bd7 test: use go tool from tree, not path
+ 2022-07-20 bb1749ba3b cmd/compile: improve GOAMD64=v1 violation test
+ 2022-07-19 176b63e711 crypto/internal/nistec,debug/gosym: fix typos
+ 2022-07-19 8e1e64c16a cmd/compile: fix mknode script
+ 2022-07-19 28be440d34 A+C: add Weizhi Yan
+ 2022-07-19 85a482fc24 runtime: revert to using the precomputed trigger for pacer calculations
+ 2022-07-19 ae7340ab68 CONTRIBUTORS: update for the Go 1.19 release
+ 2022-07-18 de8101d21b runtime: fix typos
+ 2022-07-18 967a3d985d cmd/compile: revert "remove -installsuffix flag"
+ 2022-07-18 c0c1bbde17 http: improve Get documentation
+ 2022-07-15 2aa473cc54 go/types, types2: correct alignment of atomic.Int64
+ 2022-07-15 4651ebf961 encoding/gob: s/TestIngoreDepthLimit/TestIgnoreDepthLimit/
+ 2022-07-14 dc00aed6de go/parser: skip TestParseDepthLimit for short tests
+ 2022-07-14 783ff7dfc4 encoding/xml: skip TestCVE202230633 for short tests
+ 2022-07-14 aa80228526 cmd/go/internal/modfetch: avoid duplicating path components in Git fetch errors
+ 2022-07-14 b9d5a25442 cmd/go: save zip sums for downloaded modules in 'go mod download' in a workspace
+ 2022-07-14 a906d3dd09 cmd/go: avoid re-enqueuing workspace dependencies with errors
+ 2022-07-14 266c70c263 doc/go1.19: add a release note for 'go list -json=SomeField'
+ 2022-07-13 558785a0a9 cmd/compile: remove -installsuffix flag
+ 2022-07-13 1355ea3045 cmd/compile: remove -importmap flag
+ 2022-07-13 f71f3d1b86 misc/cgo/testshared: run tests only in GOPATH mode
+ 2022-07-13 feada53661 misc/cgo/testcshared: don't rely on an erroneous install target in tests
+ 2022-07-13 c006b7ac27 runtime: clear timerModifiedEarliest when last timer is deleted
+ 2022-07-13 923740a8cc cmd/compile: fix type assert in dict pass
+ 2022-07-12 bf2ef26be3 cmd/go: in script tests, avoid checking non-main packages for staleness
+ 2022-07-12 5f5cae7200 cmd/go: avoid indexing GOROOT packages when the compiler is 'gccgo'
+ 2022-07-12 c2edb2c841 cmd/go: port TestIssue16471 to a script test and add verbose logging
+ 2022-07-12 9c2526e637 cmd/go/internal/modfetch/codehost: add missing newline in '# lock' log message
+ 2022-07-12 85486bcccb image/jpeg: increase TestLargeImageWithShortData timeout by an order of magnitude
+ 2022-07-12 27794c4d4a cmd/go/internal/modload: ignore disallowed errors when checking for updates

Change-Id: Ic05832c8c7c33ab016386bf7e85d6bad62a8fb98
2022-08-01 14:19:15 -04:00
Gopher Robot
ad672e7ce1 [release-branch.go1.19] go1.19rc2
Change-Id: I1dbe540826135c2f25e2efc49e384b9ec892a72c
Reviewed-on: https://go-review.googlesource.com/c/go/+/417179
Auto-Submit: Gopher Robot <gobot@golang.org>
Run-TryBot: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-12 22:09:01 +00:00
Michael Anthony Knyszek
392548f147 [release-branch.go1.19] all: merge master (b2b8872) into release-branch.go1.19
Merge List:

+ 2022-07-12 b2b8872c87 compress/gzip: fix stack exhaustion bug in Reader.Read
+ 2022-07-12 ac68c6c683 path/filepath: fix stack exhaustion in Glob
+ 2022-07-12 fa2d41d0ca io/fs: fix stack exhaustion in Glob
+ 2022-07-12 6fa37e98ea encoding/gob: add a depth limit for ignored fields
+ 2022-07-12 695be961d5 go/parser: limit recursion depth
+ 2022-07-12 08c46ed43d encoding/xml: use iterative Skip, rather than recursive
+ 2022-07-12 c4c1993fd2 encoding/xml: limit depth of nesting in unmarshal
+ 2022-07-12 913d05133c cmd/go: avoid spurious readdir during fsys.Walk
+ 2022-07-12 d3d7998756 net/http: clarify that MaxBytesReader returns *MaxBytesError
+ 2022-07-11 126c22a098 syscall: gofmt after CL 412114
+ 2022-07-11 123a6328b7 internal/trace: don't report regions on system goroutines
+ 2022-07-11 846490110a runtime/race: update amd64 syso images to avoid sse4
+ 2022-07-11 b75ad09cae cmd/trace: fix typo in web documentation
+ 2022-07-11 7510e597de cmd/go: make module index loading O(1)
+ 2022-07-11 b8bf820d5d cmd/nm: don't rely on an erroneous install target in tests
+ 2022-07-11 ad641e8521 misc/cgo/testcarchive: don't rely on an erroneous install target in tests
+ 2022-07-11 bf5898ef53 net/url: use EscapedPath for url.JoinPath
+ 2022-07-11 398dcd1cf0 database/sql: make TestTxContextWaitNoDiscard test more robust
+ 2022-07-11 f956941b0f cmd/go: use package index for std in load.loadPackageData
+ 2022-07-11 59ab6f351a net/http: remove Content-Encoding in writeNotModified
+ 2022-07-08 c1a4e0fe01 cmd/compile: fix libfuzzer instrumentation line number
+ 2022-07-08 5c1a13e7a4 cmd/go: avoid setting variables for '/' and ':' in TestScript subprocess environments
+ 2022-07-08 180bcad33d net/http: wait for listeners to exit in Server.Close and Shutdown
+ 2022-07-08 14abe8aa73 cmd/compile: don't convert to interface{} for un-comparable types in generic switch
+ 2022-07-07 1ebc983000 runtime: overestimate the amount of allocated memory in heapLive
+ 2022-07-07 c177d9d98a crypto/x509: restrict CRL number to <=20 octets
+ 2022-07-07 486fc01770 crypto/x509: correctly parse CRL entry extensions
+ 2022-07-07 8ac58de185 crypto/x509: populate Number and AKI of parsed CRLs
+ 2022-07-07 0c7fcf6bd1 cmd/link: explicitly disable PIE for windows/amd64 -race mode
+ 2022-07-07 eaf2125654 cmd/go: default to "exe" build mode for windows -race
+ 2022-07-06 1243ec9c17 cmd/compile: only check implicit dots for method call enabled by a type bound
+ 2022-07-06 c391156f96 cmd/go: set up git identity for build_buildvcs_auto.txt

Change-Id: Ib2b544e080fc7fce20614d4ed310767c2591931f
2022-07-12 16:00:39 +00:00
Gopher Robot
bac4eb53d6 [release-branch.go1.19] go1.19rc1
Change-Id: I85a6dcfda4fd6b871959e0ba8498a5b85c3c557e
Reviewed-on: https://go-review.googlesource.com/c/go/+/416314
Run-TryBot: Gopher Robot <gobot@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: David Chase <drchase@google.com>
2022-07-06 21:33:10 +00:00
Heschi Kreinick
18033a0b56 [release-branch.go1.19] update codereview.cfg for release-branch.go1.19
Following go.dev/cl/334376.

Change-Id: I7e5e1b89243d1980274d27be5362acf8034998ef
Reviewed-on: https://go-review.googlesource.com/c/go/+/416176
Run-TryBot: Heschi Kreinick <heschi@google.com>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-06 17:32:58 +00:00
141 changed files with 1878 additions and 410 deletions

1
VERSION Normal file
View File

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

View File

@@ -1 +1,2 @@
branch: master
branch: release-branch.go1.19
parent-branch: master

View File

@@ -19,6 +19,7 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"syscall"
"testing"
"time"
@@ -519,38 +520,13 @@ func TestEarlySignalHandler(t *testing.T) {
func TestSignalForwarding(t *testing.T) {
checkSignalForwardingTest(t)
buildSignalForwardingTest(t)
if !testWork {
defer func() {
os.Remove("libgo2.a")
os.Remove("libgo2.h")
os.Remove("testp" + exeSuffix)
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
}()
}
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
if out, err := cmd.CombinedOutput(); err != nil {
t.Logf("%s", out)
t.Fatal(err)
}
checkLineComments(t, "libgo2.h")
checkArchive(t, "libgo2.a")
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
if runtime.Compiler == "gccgo" {
ccArgs = append(ccArgs, "-lgo")
}
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
t.Logf("%s", out)
t.Fatal(err)
}
cmd = exec.Command(bin[0], append(bin[1:], "1")...)
cmd := exec.Command(bin[0], append(bin[1:], "1")...)
out, err := cmd.CombinedOutput()
t.Logf("%v\n%s", cmd.Args, out)
expectSignal(t, err, syscall.SIGSEGV)
expectSignal(t, err, syscall.SIGSEGV, 0)
// SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
if runtime.GOOS != "darwin" && runtime.GOOS != "ios" {
@@ -561,7 +537,7 @@ func TestSignalForwarding(t *testing.T) {
if len(out) > 0 {
t.Logf("%s", out)
}
expectSignal(t, err, syscall.SIGPIPE)
expectSignal(t, err, syscall.SIGPIPE, 0)
}
}
@@ -572,32 +548,7 @@ func TestSignalForwardingExternal(t *testing.T) {
t.Skipf("skipping on %s/%s: runtime does not permit SI_USER SIGSEGV", GOOS, GOARCH)
}
checkSignalForwardingTest(t)
if !testWork {
defer func() {
os.Remove("libgo2.a")
os.Remove("libgo2.h")
os.Remove("testp" + exeSuffix)
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
}()
}
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
if out, err := cmd.CombinedOutput(); err != nil {
t.Logf("%s", out)
t.Fatal(err)
}
checkLineComments(t, "libgo2.h")
checkArchive(t, "libgo2.a")
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
if runtime.Compiler == "gccgo" {
ccArgs = append(ccArgs, "-lgo")
}
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
t.Logf("%s", out)
t.Fatal(err)
}
buildSignalForwardingTest(t)
// We want to send the process a signal and see if it dies.
// Normally the signal goes to the C thread, the Go signal
@@ -610,42 +561,27 @@ func TestSignalForwardingExternal(t *testing.T) {
// fail.
const tries = 20
for i := 0; i < tries; i++ {
cmd = exec.Command(bin[0], append(bin[1:], "2")...)
stderr, err := cmd.StderrPipe()
if err != nil {
t.Fatal(err)
}
defer stderr.Close()
r := bufio.NewReader(stderr)
err = cmd.Start()
if err != nil {
t.Fatal(err)
}
// Wait for trigger to ensure that the process is started.
ok, err := r.ReadString('\n')
// Verify trigger.
if err != nil || ok != "OK\n" {
t.Fatalf("Did not receive OK signal")
}
// Give the program a chance to enter the sleep function.
time.Sleep(time.Millisecond)
cmd.Process.Signal(syscall.SIGSEGV)
err = cmd.Wait()
err := runSignalForwardingTest(t, "2")
if err == nil {
continue
}
if expectSignal(t, err, syscall.SIGSEGV) {
// If the signal is delivered to a C thread, as expected,
// the Go signal handler will disable itself and re-raise
// the signal, causing the program to die with SIGSEGV.
//
// It is also possible that the signal will be
// delivered to a Go thread, such as a GC thread.
// Currently when the Go runtime sees that a SIGSEGV was
// sent from a different program, it first tries to send
// the signal to the os/signal API. If nothing is looking
// for (or explicitly ignoring) SIGSEGV, then it crashes.
// Because the Go runtime is invoked via a c-archive,
// it treats this as GOTRACEBACK=crash, meaning that it
// dumps a stack trace for all goroutines, which it does
// by raising SIGQUIT. The effect is that we will see the
// program die with SIGQUIT in that case, not SIGSEGV.
if expectSignal(t, err, syscall.SIGSEGV, syscall.SIGQUIT) {
return
}
}
@@ -653,6 +589,23 @@ func TestSignalForwardingExternal(t *testing.T) {
t.Errorf("program succeeded unexpectedly %d times", tries)
}
func TestSignalForwardingGo(t *testing.T) {
// This test fails on darwin-amd64 because of the special
// handling of user-generated SIGSEGV signals in fixsigcode in
// runtime/signal_darwin_amd64.go.
if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" {
t.Skip("not supported on darwin-amd64")
}
checkSignalForwardingTest(t)
buildSignalForwardingTest(t)
err := runSignalForwardingTest(t, "4")
// Occasionally the signal will be delivered to a C thread,
// and the program will crash with SIGSEGV.
expectSignal(t, err, syscall.SIGQUIT, syscall.SIGSEGV)
}
// checkSignalForwardingTest calls t.Skip if the SignalForwarding test
// doesn't work on this platform.
func checkSignalForwardingTest(t *testing.T) {
@@ -667,18 +620,121 @@ func checkSignalForwardingTest(t *testing.T) {
}
}
// buildSignalForwardingTest builds the executable used by the various
// signal forwarding tests.
func buildSignalForwardingTest(t *testing.T) {
if !testWork {
t.Cleanup(func() {
os.Remove("libgo2.a")
os.Remove("libgo2.h")
os.Remove("testp" + exeSuffix)
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
})
}
t.Log("go build -buildmode=c-archive -o libgo2.a ./libgo2")
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
out, err := cmd.CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
if err != nil {
t.Fatal(err)
}
checkLineComments(t, "libgo2.h")
checkArchive(t, "libgo2.a")
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
if runtime.Compiler == "gccgo" {
ccArgs = append(ccArgs, "-lgo")
}
t.Log(ccArgs)
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
if err != nil {
t.Fatal(err)
}
}
func runSignalForwardingTest(t *testing.T, arg string) error {
t.Logf("%v %s", bin, arg)
cmd := exec.Command(bin[0], append(bin[1:], arg)...)
var out strings.Builder
cmd.Stdout = &out
stderr, err := cmd.StderrPipe()
if err != nil {
t.Fatal(err)
}
defer stderr.Close()
r := bufio.NewReader(stderr)
err = cmd.Start()
if err != nil {
t.Fatal(err)
}
// Wait for trigger to ensure that process is started.
ok, err := r.ReadString('\n')
// Verify trigger.
if err != nil || ok != "OK\n" {
t.Fatal("Did not receive OK signal")
}
var wg sync.WaitGroup
wg.Add(1)
var errsb strings.Builder
go func() {
defer wg.Done()
io.Copy(&errsb, r)
}()
// Give the program a chance to enter the function.
// If the program doesn't get there the test will still
// pass, although it doesn't quite test what we intended.
// This is fine as long as the program normally makes it.
time.Sleep(time.Millisecond)
cmd.Process.Signal(syscall.SIGSEGV)
err = cmd.Wait()
s := out.String()
if len(s) > 0 {
t.Log(s)
}
wg.Wait()
s = errsb.String()
if len(s) > 0 {
t.Log(s)
}
return err
}
// expectSignal checks that err, the exit status of a test program,
// shows a failure due to a specific signal. Returns whether we found
// the expected signal.
func expectSignal(t *testing.T, err error, sig syscall.Signal) bool {
// shows a failure due to a specific signal or two. Returns whether we
// found an expected signal.
func expectSignal(t *testing.T, err error, sig1, sig2 syscall.Signal) bool {
t.Helper()
if err == nil {
t.Error("test program succeeded unexpectedly")
} else if ee, ok := err.(*exec.ExitError); !ok {
t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
} else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
} else if !ws.Signaled() || ws.Signal() != sig {
t.Errorf("got %v; expected signal %v", ee, sig)
} else if !ws.Signaled() || (ws.Signal() != sig1 && ws.Signal() != sig2) {
if sig2 == 0 {
t.Errorf("got %q; expected signal %q", ee, sig1)
} else {
t.Errorf("got %q; expected signal %q or %q", ee, sig1, sig2)
}
} else {
return true
}
@@ -1015,14 +1071,14 @@ func TestCompileWithoutShared(t *testing.T) {
binArgs := append(cmdToRun(exe), "1")
out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
t.Logf("%v\n%s", binArgs, out)
expectSignal(t, err, syscall.SIGSEGV)
expectSignal(t, err, syscall.SIGSEGV, 0)
// SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
if runtime.GOOS != "darwin" && runtime.GOOS != "ios" {
binArgs := append(cmdToRun(exe), "3")
out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
t.Logf("%v\n%s", binArgs, out)
expectSignal(t, err, syscall.SIGPIPE)
expectSignal(t, err, syscall.SIGPIPE, 0)
}
}

View File

@@ -49,6 +49,12 @@ func RunGoroutines() {
}
}
// Block blocks the current thread while running Go code.
//export Block
func Block() {
select {}
}
var P *byte
// TestSEGV makes sure that an invalid address turns into a run-time Go panic.

View File

@@ -29,10 +29,6 @@ int main(int argc, char** argv) {
verbose = (argc > 2);
if (verbose) {
printf("calling RunGoroutines\n");
}
Noop();
switch (test) {
@@ -90,6 +86,15 @@ int main(int argc, char** argv) {
printf("did not receive SIGPIPE\n");
return 0;
}
case 4: {
fprintf(stderr, "OK\n");
fflush(stderr);
if (verbose) {
printf("calling Block\n");
}
Block();
}
default:
printf("Unknown test: %d\n", test);
return 0;

View File

@@ -143,6 +143,10 @@ const (
blockSize = 512 // Size of each block in a tar stream
nameSize = 100 // Max length of the name field in USTAR format
prefixSize = 155 // Max length of the prefix field in USTAR format
// Max length of a special file (PAX header, GNU long name or link).
// This matches the limit used by libarchive.
maxSpecialFileSize = 1 << 20
)
// blockPadding computes the number of bytes needed to pad offset up to the

View File

@@ -103,7 +103,7 @@ func (tr *Reader) next() (*Header, error) {
continue // This is a meta header affecting the next header
case TypeGNULongName, TypeGNULongLink:
format.mayOnlyBe(FormatGNU)
realname, err := io.ReadAll(tr)
realname, err := readSpecialFile(tr)
if err != nil {
return nil, err
}
@@ -293,7 +293,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) {
// parsePAX parses PAX headers.
// If an extended header (type 'x') is invalid, ErrHeader is returned
func parsePAX(r io.Reader) (map[string]string, error) {
buf, err := io.ReadAll(r)
buf, err := readSpecialFile(r)
if err != nil {
return nil, err
}
@@ -828,6 +828,16 @@ func tryReadFull(r io.Reader, b []byte) (n int, err error) {
return n, err
}
// readSpecialFile is like io.ReadAll except it returns
// ErrFieldTooLong if more than maxSpecialFileSize is read.
func readSpecialFile(r io.Reader) ([]byte, error) {
buf, err := io.ReadAll(io.LimitReader(r, maxSpecialFileSize+1))
if len(buf) > maxSpecialFileSize {
return nil, ErrFieldTooLong
}
return buf, err
}
// discard skips n bytes in r, reporting an error if unable to do so.
func discard(r io.Reader, n int64) error {
// If possible, Seek to the last byte before the end of the data section.

View File

@@ -6,6 +6,7 @@ package tar
import (
"bytes"
"compress/bzip2"
"crypto/md5"
"errors"
"fmt"
@@ -243,6 +244,9 @@ func TestReader(t *testing.T) {
}, {
file: "testdata/pax-bad-hdr-file.tar",
err: ErrHeader,
}, {
file: "testdata/pax-bad-hdr-large.tar.bz2",
err: ErrFieldTooLong,
}, {
file: "testdata/pax-bad-mtime-file.tar",
err: ErrHeader,
@@ -625,9 +629,14 @@ func TestReader(t *testing.T) {
}
defer f.Close()
var fr io.Reader = f
if strings.HasSuffix(v.file, ".bz2") {
fr = bzip2.NewReader(fr)
}
// Capture all headers and checksums.
var (
tr = NewReader(f)
tr = NewReader(fr)
hdrs []*Header
chksums []string
rdbuf = make([]byte, 8)

Binary file not shown.

View File

@@ -199,6 +199,9 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error {
flag = TypeXHeader
}
data := buf.String()
if len(data) > maxSpecialFileSize {
return ErrFieldTooLong
}
if err := tw.writeRawFile(name, data, flag, FormatPAX); err != nil || isGlobal {
return err // Global headers return here
}

View File

@@ -1004,6 +1004,33 @@ func TestIssue12594(t *testing.T) {
}
}
func TestWriteLongHeader(t *testing.T) {
for _, test := range []struct {
name string
h *Header
}{{
name: "name too long",
h: &Header{Name: strings.Repeat("a", maxSpecialFileSize)},
}, {
name: "linkname too long",
h: &Header{Linkname: strings.Repeat("a", maxSpecialFileSize)},
}, {
name: "uname too long",
h: &Header{Uname: strings.Repeat("a", maxSpecialFileSize)},
}, {
name: "gname too long",
h: &Header{Gname: strings.Repeat("a", maxSpecialFileSize)},
}, {
name: "PAX header too long",
h: &Header{PAXRecords: map[string]string{"GOLANG.x": strings.Repeat("a", maxSpecialFileSize)}},
}} {
w := NewWriter(io.Discard)
if err := w.WriteHeader(test.h); err != ErrFieldTooLong {
t.Errorf("%v: w.WriteHeader() = %v, want ErrFieldTooLong", test.name, err)
}
}
}
// testNonEmptyWriter wraps an io.Writer and ensures that
// Write is never called with an empty buffer.
type testNonEmptyWriter struct{ io.Writer }

View File

@@ -798,18 +798,18 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
// CalleeEffects appends any side effects from evaluating callee to init.
func CalleeEffects(init *ir.Nodes, callee ir.Node) {
for {
init.Append(ir.TakeInit(callee)...)
switch callee.Op() {
case ir.ONAME, ir.OCLOSURE, ir.OMETHEXPR:
return // done
case ir.OCONVNOP:
conv := callee.(*ir.ConvExpr)
init.Append(ir.TakeInit(conv)...)
callee = conv.X
case ir.OINLCALL:
ic := callee.(*ir.InlinedCallExpr)
init.Append(ir.TakeInit(ic)...)
init.Append(ic.Body.Take()...)
callee = ic.SingleResult()

View File

@@ -26,6 +26,7 @@ var Syms struct {
GCWriteBarrier *obj.LSym
Goschedguarded *obj.LSym
Growslice *obj.LSym
Memmove *obj.LSym
Msanread *obj.LSym
Msanwrite *obj.LSym
Msanmove *obj.LSym

View File

@@ -434,7 +434,7 @@ func (lv *liveness) pointerMap(liveout bitvec.BitVec, vars []*ir.Name, args, loc
if node.FrameOffset() < 0 {
lv.f.Fatalf("Node %v has frameoffset %d\n", node.Sym().Name, node.FrameOffset())
}
typebits.Set(node.Type(), node.FrameOffset(), args)
typebits.SetNoCheck(node.Type(), node.FrameOffset(), args)
break
}
fallthrough // PPARAMOUT in registers acts memory-allocates like an AUTO
@@ -1507,7 +1507,7 @@ func WriteFuncMap(fn *ir.Func, abiInfo *abi.ABIParamResultInfo) {
bv := bitvec.New(int32(nptr) * 2)
for _, p := range abiInfo.InParams() {
typebits.Set(p.Type, p.FrameOffset(abiInfo), bv)
typebits.SetNoCheck(p.Type, p.FrameOffset(abiInfo), bv)
}
nbitmap := 1
@@ -1522,7 +1522,7 @@ func WriteFuncMap(fn *ir.Func, abiInfo *abi.ABIParamResultInfo) {
if fn.Type().NumResults() > 0 {
for _, p := range abiInfo.OutParams() {
if len(p.Registers) == 0 {
typebits.Set(p.Type, p.FrameOffset(abiInfo), bv)
typebits.SetNoCheck(p.Type, p.FrameOffset(abiInfo), bv)
}
}
off = objw.BitVec(lsym, off, bv)

View File

@@ -25,6 +25,17 @@ func (s *gcSizes) Alignof(T types2.Type) int64 {
// is the same as unsafe.Alignof(x[0]), but at least 1."
return s.Alignof(t.Elem())
case *types2.Struct:
if t.NumFields() == 0 && types2.IsSyncAtomicAlign64(T) {
// Special case: sync/atomic.align64 is an
// empty struct we recognize as a signal that
// the struct it contains must be
// 64-bit-aligned.
//
// This logic is equivalent to the logic in
// cmd/compile/internal/types/size.go:calcStructOffset
return 8
}
// spec: "For a variable x of struct type: unsafe.Alignof(x)
// is the largest of the values unsafe.Alignof(x.f) for each
// field f of x, but at least 1."

View File

@@ -334,10 +334,6 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
} else { // ir.OMETHEXPR or ir.METHVALUE
// Method expression T.M where T is a generic type.
se := x.(*ir.SelectorExpr)
targs := deref(se.X.Type()).RParams()
if len(targs) == 0 {
panic("bad")
}
if x.Op() == ir.OMETHVALUE {
rcvrValue = se.X
}
@@ -348,7 +344,8 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
// of se.Selection, since that will be the type that actually has
// the method.
recv := deref(se.Selection.Type.Recv().Type)
if len(recv.RParams()) == 0 {
targs := recv.RParams()
if len(targs) == 0 {
// The embedded type that actually has the method is not
// actually generic, so no need to build a closure.
return x
@@ -1357,6 +1354,9 @@ func (g *genInst) dictPass(info *instInfo) {
}
case ir.ODOTTYPE, ir.ODOTTYPE2:
dt := m.(*ir.TypeAssertExpr)
if dt.Type().IsEmptyInterface() || (dt.Type().IsInterface() && !dt.Type().HasShape()) {
break
}
if !dt.Type().HasShape() && !(dt.X.Type().HasShape() && !dt.X.Type().IsEmptyInterface()) {
break
}
@@ -1787,6 +1787,7 @@ func (g *genInst) getSymForMethodCall(se *ir.SelectorExpr, subst *typecheck.Tsub
// instantiations have been created.
// Also handles writing method expression closures into the dictionaries.
func (g *genInst) finalizeSyms() {
Outer:
for _, d := range g.dictSymsToFinalize {
infoPrint("=== Finalizing dictionary %s\n", d.sym.Name)
@@ -1856,7 +1857,30 @@ func (g *genInst) finalizeSyms() {
}
}
if !found {
base.Fatalf("method %s on %v not found", bf.name, rcvr)
// We failed to find a method expression needed for this
// dictionary. This may happen because we tried to create a
// dictionary for an invalid instantiation.
//
// For example, in test/typeparam/issue54225.go, we attempt to
// construct a dictionary for "Node[struct{}].contentLen",
// even though "struct{}" does not implement "Value", so it
// cannot actually be used as a type argument to "Node".
//
// The real issue here is we shouldn't be attempting to create
// those dictionaries in the first place (e.g., CL 428356),
// but that fix is scarier for backporting to Go 1.19. Too
// many backport CLs to this code have fixed one issue while
// introducing another.
//
// So as a hack, instead of calling Fatalf, we simply skip
// calling objw.Global below, which prevents us from emitting
// the broken dictionary. The linker's dead code elimination
// should then naturally prune this invalid, unneeded
// dictionary. Worst case, if the dictionary somehow *is*
// needed by the final executable, we've just turned an ICE
// into a link-time missing symbol failure.
infoPrint(" ! abandoning dictionary %v; missing method expression %v.%s\n", d.sym.Name, rcvr, bf.name)
continue Outer
}
}

View File

@@ -1890,14 +1890,14 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
// the TOC to the appropriate value for that module. But if it returns
// directly to the wrapper's caller, nothing will reset it to the correct
// value for that function.
var call *ir.CallExpr
if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !generic {
call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
call.Args = ir.ParamNames(fn.Type())
call.IsDDD = fn.Type().IsVariadic()
fn.Body.Append(ir.NewTailCallStmt(base.Pos, call))
} else {
fn.SetWrapper(true) // ignore frame for panic+recover matching
var call *ir.CallExpr
if generic && dot.X != nthis {
// If there is embedding involved, then we should do the
@@ -1982,7 +1982,22 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
typecheck.Stmts(fn.Body)
if AfterGlobalEscapeAnalysis {
inline.InlineCalls(fn)
// Inlining the method may reveal closures, which require walking all function bodies
// to decide whether to capture free variables by value or by ref. So we only do inline
// if the method do not contain any closures, otherwise, the escape analysis may make
// dead variables resurrected, and causing liveness analysis confused, see issue #53702.
var canInline bool
switch x := call.X.(type) {
case *ir.Name:
canInline = len(x.Func.Closures) == 0
case *ir.SelectorExpr:
if x.Op() == ir.OMETHEXPR {
canInline = x.FuncName().Func != nil && len(x.FuncName().Func.Closures) == 0
}
}
if canInline {
inline.InlineCalls(fn)
}
escape.Batch([]*ir.Func{fn}, false)
}

View File

@@ -2092,7 +2092,13 @@
// Inline small or disjoint runtime.memmove calls with constant length.
// See the comment in op Move in genericOps.go for discussion of the type.
//
// Note that we've lost any knowledge of the type and alignment requirements
// of the source and destination. We only know the size, and that the type
// contains no pointers.
// The type of the move is not necessarily v.Args[0].Type().Elem()!
// See issue 55122 for details.
//
// Because expand calls runs after prove, constants useful to this pattern may not appear.
// Both versions need to exist; the memory and register variants.
//
@@ -2100,31 +2106,28 @@
(SelectN [0] call:(StaticCall {sym} s1:(Store _ (Const(64|32) [sz]) s2:(Store _ src s3:(Store {t} _ dst mem)))))
&& sz >= 0
&& isSameCall(sym, "runtime.memmove")
&& t.IsPtr() // avoids TUNSAFEPTR, see issue 30061
&& s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1
&& isInlinableMemmove(dst, src, int64(sz), config)
&& clobber(s1, s2, s3, call)
=> (Move {t.Elem()} [int64(sz)] dst src mem)
=> (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem)
// Match post-expansion calls, register version.
(SelectN [0] call:(StaticCall {sym} dst src (Const(64|32) [sz]) mem))
&& sz >= 0
&& call.Uses == 1 // this will exclude all calls with results
&& isSameCall(sym, "runtime.memmove")
&& dst.Type.IsPtr() // avoids TUNSAFEPTR, see issue 30061
&& isInlinableMemmove(dst, src, int64(sz), config)
&& clobber(call)
=> (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
=> (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem)
// Match pre-expansion calls.
(SelectN [0] call:(StaticLECall {sym} dst src (Const(64|32) [sz]) mem))
&& sz >= 0
&& call.Uses == 1 // this will exclude all calls with results
&& isSameCall(sym, "runtime.memmove")
&& dst.Type.IsPtr() // avoids TUNSAFEPTR, see issue 30061
&& isInlinableMemmove(dst, src, int64(sz), config)
&& clobber(call)
=> (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
=> (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem)
// De-virtualize late-expanded interface calls into late-expanded static calls.
// Note that (ITab (IMake)) doesn't get rewritten until after the first opt pass,

View File

@@ -355,7 +355,9 @@ var genericOps = []opData{
{name: "Load", argLength: 2}, // Load from arg0. arg1=memory
{name: "Dereference", argLength: 2}, // Load from arg0. arg1=memory. Helper op for arg/result passing, result is an otherwise not-SSA-able "value".
{name: "Store", argLength: 3, typ: "Mem", aux: "Typ"}, // Store arg1 to arg0. arg2=memory, aux=type. Returns memory.
// The source and destination of Move may overlap in some cases. See e.g.
// Normally we require that the source and destination of Move do not overlap.
// There is an exception when we know all the loads will happen before all
// the stores. In that case, overlap is ok. See
// memmove inlining in generic.rules. When inlineablememmovesize (in ../rewrite.go)
// returns true, we must do all loads before all stores, when lowering Move.
// The type of Move is used for the write barrier pass to insert write barriers

View File

@@ -1362,7 +1362,8 @@ func zeroUpper56Bits(x *Value, depth int) bool {
// isInlinableMemmove reports whether the given arch performs a Move of the given size
// faster than memmove. It will only return true if replacing the memmove with a Move is
// safe, either because Move is small or because the arguments are disjoint.
// safe, either because Move will do all of its loads before any of its stores, or
// because the arguments are known to be disjoint.
// This is used as a check for replacing memmove with Move ops.
func isInlinableMemmove(dst, src *Value, sz int64, c *Config) bool {
// It is always safe to convert memmove into Move when its arguments are disjoint.
@@ -1381,6 +1382,9 @@ func isInlinableMemmove(dst, src *Value, sz int64, c *Config) bool {
}
return false
}
func IsInlinableMemmove(dst, src *Value, sz int64, c *Config) bool {
return isInlinableMemmove(dst, src, sz, c)
}
// logLargeCopy logs the occurrence of a large copy.
// The best place to do this is in the rewrite rules where the size of the move is easy to find.
@@ -1394,6 +1398,14 @@ func logLargeCopy(v *Value, s int64) bool {
}
return true
}
func LogLargeCopy(funcName string, pos src.XPos, s int64) {
if s < 128 {
return
}
if logopt.Enabled() {
logopt.LogOpt(pos, "copy", "lower", funcName, fmt.Sprintf("%d bytes", s))
}
}
// hasSmallRotate reports whether the architecture has rotate instructions
// for sizes < 32-bit. This is used to decide whether to promote some rotations.

View File

@@ -21317,8 +21317,8 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool {
return true
}
// match: (SelectN [0] call:(StaticCall {sym} s1:(Store _ (Const64 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem)))))
// cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)
// result: (Move {t.Elem()} [int64(sz)] dst src mem)
// cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)
// result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem)
for {
if auxIntToInt64(v.AuxInt) != 0 {
break
@@ -21348,21 +21348,20 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool {
if s3.Op != OpStore {
break
}
t := auxToType(s3.Aux)
mem := s3.Args[2]
dst := s3.Args[1]
if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)) {
if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)) {
break
}
v.reset(OpMove)
v.AuxInt = int64ToAuxInt(int64(sz))
v.Aux = typeToAux(t.Elem())
v.Aux = typeToAux(types.Types[types.TUINT8])
v.AddArg3(dst, src, mem)
return true
}
// match: (SelectN [0] call:(StaticCall {sym} s1:(Store _ (Const32 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem)))))
// cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)
// result: (Move {t.Elem()} [int64(sz)] dst src mem)
// cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)
// result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem)
for {
if auxIntToInt64(v.AuxInt) != 0 {
break
@@ -21392,21 +21391,20 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool {
if s3.Op != OpStore {
break
}
t := auxToType(s3.Aux)
mem := s3.Args[2]
dst := s3.Args[1]
if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)) {
if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)) {
break
}
v.reset(OpMove)
v.AuxInt = int64ToAuxInt(int64(sz))
v.Aux = typeToAux(t.Elem())
v.Aux = typeToAux(types.Types[types.TUINT8])
v.AddArg3(dst, src, mem)
return true
}
// match: (SelectN [0] call:(StaticCall {sym} dst src (Const64 [sz]) mem))
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
// result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
// result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem)
for {
if auxIntToInt64(v.AuxInt) != 0 {
break
@@ -21424,18 +21422,18 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool {
break
}
sz := auxIntToInt64(call_2.AuxInt)
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
break
}
v.reset(OpMove)
v.AuxInt = int64ToAuxInt(int64(sz))
v.Aux = typeToAux(dst.Type.Elem())
v.Aux = typeToAux(types.Types[types.TUINT8])
v.AddArg3(dst, src, mem)
return true
}
// match: (SelectN [0] call:(StaticCall {sym} dst src (Const32 [sz]) mem))
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
// result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
// result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem)
for {
if auxIntToInt64(v.AuxInt) != 0 {
break
@@ -21453,18 +21451,18 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool {
break
}
sz := auxIntToInt32(call_2.AuxInt)
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
break
}
v.reset(OpMove)
v.AuxInt = int64ToAuxInt(int64(sz))
v.Aux = typeToAux(dst.Type.Elem())
v.Aux = typeToAux(types.Types[types.TUINT8])
v.AddArg3(dst, src, mem)
return true
}
// match: (SelectN [0] call:(StaticLECall {sym} dst src (Const64 [sz]) mem))
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
// result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
// result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem)
for {
if auxIntToInt64(v.AuxInt) != 0 {
break
@@ -21482,18 +21480,18 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool {
break
}
sz := auxIntToInt64(call_2.AuxInt)
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
break
}
v.reset(OpMove)
v.AuxInt = int64ToAuxInt(int64(sz))
v.Aux = typeToAux(dst.Type.Elem())
v.Aux = typeToAux(types.Types[types.TUINT8])
v.AddArg3(dst, src, mem)
return true
}
// match: (SelectN [0] call:(StaticLECall {sym} dst src (Const32 [sz]) mem))
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
// result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
// result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem)
for {
if auxIntToInt64(v.AuxInt) != 0 {
break
@@ -21511,12 +21509,12 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool {
break
}
sz := auxIntToInt32(call_2.AuxInt)
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
break
}
v.reset(OpMove)
v.AuxInt = int64ToAuxInt(int64(sz))
v.Aux = typeToAux(dst.Type.Elem())
v.Aux = typeToAux(types.Types[types.TUINT8])
v.AddArg3(dst, src, mem)
return true
}

View File

@@ -96,6 +96,7 @@ func needAlloc(n *ir.Name) bool {
func (s *ssafn) AllocFrame(f *ssa.Func) {
s.stksize = 0
s.stkptrsize = 0
s.stkalign = int64(types.RegSize)
fn := s.curfn
// Mark the PAUTO's unused.
@@ -160,6 +161,9 @@ func (s *ssafn) AllocFrame(f *ssa.Func) {
}
s.stksize += w
s.stksize = types.Rnd(s.stksize, n.Type().Alignment())
if n.Type().Alignment() > int64(types.RegSize) {
s.stkalign = n.Type().Alignment()
}
if n.Type().HasPointers() {
s.stkptrsize = s.stksize
lastHasPtr = true
@@ -169,8 +173,8 @@ func (s *ssafn) AllocFrame(f *ssa.Func) {
n.SetFrameOffset(-s.stksize)
}
s.stksize = types.Rnd(s.stksize, int64(types.RegSize))
s.stkptrsize = types.Rnd(s.stkptrsize, int64(types.RegSize))
s.stksize = types.Rnd(s.stksize, s.stkalign)
s.stkptrsize = types.Rnd(s.stkptrsize, s.stkalign)
}
const maxStackSize = 1 << 30

View File

@@ -105,6 +105,7 @@ func InitConfig() {
ir.Syms.GCWriteBarrier = typecheck.LookupRuntimeFunc("gcWriteBarrier")
ir.Syms.Goschedguarded = typecheck.LookupRuntimeFunc("goschedguarded")
ir.Syms.Growslice = typecheck.LookupRuntimeFunc("growslice")
ir.Syms.Memmove = typecheck.LookupRuntimeFunc("memmove")
ir.Syms.Msanread = typecheck.LookupRuntimeFunc("msanread")
ir.Syms.Msanwrite = typecheck.LookupRuntimeFunc("msanwrite")
ir.Syms.Msanmove = typecheck.LookupRuntimeFunc("msanmove")
@@ -1359,7 +1360,47 @@ func (s *state) zero(t *types.Type, dst *ssa.Value) {
}
func (s *state) move(t *types.Type, dst, src *ssa.Value) {
s.moveWhichMayOverlap(t, dst, src, false)
}
func (s *state) moveWhichMayOverlap(t *types.Type, dst, src *ssa.Value, mayOverlap bool) {
s.instrumentMove(t, dst, src)
if mayOverlap && t.IsArray() && t.NumElem() > 1 && !ssa.IsInlinableMemmove(dst, src, t.Size(), s.f.Config) {
// Normally, when moving Go values of type T from one location to another,
// we don't need to worry about partial overlaps. The two Ts must either be
// in disjoint (nonoverlapping) memory or in exactly the same location.
// There are 2 cases where this isn't true:
// 1) Using unsafe you can arrange partial overlaps.
// 2) Since Go 1.17, you can use a cast from a slice to a ptr-to-array.
// https://go.dev/ref/spec#Conversions_from_slice_to_array_pointer
// This feature can be used to construct partial overlaps of array types.
// var a [3]int
// p := (*[2]int)(a[:])
// q := (*[2]int)(a[1:])
// *p = *q
// We don't care about solving 1. Or at least, we haven't historically
// and no one has complained.
// For 2, we need to ensure that if there might be partial overlap,
// then we can't use OpMove; we must use memmove instead.
// (memmove handles partial overlap by copying in the correct
// direction. OpMove does not.)
//
// Note that we have to be careful here not to introduce a call when
// we're marshaling arguments to a call or unmarshaling results from a call.
// Cases where this is happening must pass mayOverlap to false.
// (Currently this only happens when unmarshaling results of a call.)
if t.HasPointers() {
s.rtcall(ir.Syms.Typedmemmove, true, nil, s.reflectType(t), dst, src)
// We would have otherwise implemented this move with straightline code,
// including a write barrier. Pretend we issue a write barrier here,
// so that the write barrier tests work. (Otherwise they'd need to know
// the details of IsInlineableMemmove.)
s.curfn.SetWBPos(s.peekPos())
} else {
s.rtcall(ir.Syms.Memmove, true, nil, dst, src, s.constInt(types.Types[types.TUINTPTR], t.Size()))
}
ssa.LogLargeCopy(s.f.Name, s.peekPos(), t.Size())
return
}
store := s.newValue3I(ssa.OpMove, types.TypeMem, t.Size(), dst, src, s.mem())
store.Aux = t
s.vars[memVar] = store
@@ -1541,6 +1582,36 @@ func (s *state) stmt(n ir.Node) {
return
}
// mayOverlap keeps track of whether the LHS and RHS might
// refer to overlapping memory.
mayOverlap := true
if n.Y == nil {
// Not a move at all, mayOverlap is not relevant.
} else if n.Def {
// A variable being defined cannot overlap anything else.
mayOverlap = false
} else if n.X.Op() == ir.ONAME && n.Y.Op() == ir.ONAME {
// Two named things never overlap.
// (Or they are identical, which we treat as nonoverlapping.)
mayOverlap = false
} else if n.Y.Op() == ir.ODEREF {
p := n.Y.(*ir.StarExpr).X
for p.Op() == ir.OCONVNOP {
p = p.(*ir.ConvExpr).X
}
if p.Op() == ir.OSPTR && p.(*ir.UnaryExpr).X.Type().IsString() {
// Pointer fields of strings point to unmodifiable memory.
// That memory can't overlap with the memory being written.
mayOverlap = false
}
} else if n.Y.Op() == ir.ORESULT || n.Y.Op() == ir.OCALLFUNC || n.Y.Op() == ir.OCALLINTER {
// When copying values out of the return area of a call, we know
// the source and destination don't overlap. Importantly, we must
// set mayOverlap so we don't introduce a call to memmove while
// we still have live data in the argument area.
mayOverlap = false
}
// Evaluate RHS.
rhs := n.Y
if rhs != nil {
@@ -1641,7 +1712,7 @@ func (s *state) stmt(n ir.Node) {
}
}
s.assign(n.X, r, deref, skip)
s.assignWhichMayOverlap(n.X, r, deref, skip, mayOverlap)
case ir.OIF:
n := n.(*ir.IfStmt)
@@ -3564,7 +3635,11 @@ const (
// If deref is true, then we do left = *right instead (and right has already been nil-checked).
// If deref is true and right == nil, just do left = 0.
// skip indicates assignments (at the top level) that can be avoided.
// mayOverlap indicates whether left&right might partially overlap in memory. Default is false.
func (s *state) assign(left ir.Node, right *ssa.Value, deref bool, skip skipMask) {
s.assignWhichMayOverlap(left, right, deref, skip, false)
}
func (s *state) assignWhichMayOverlap(left ir.Node, right *ssa.Value, deref bool, skip skipMask, mayOverlap bool) {
if left.Op() == ir.ONAME && ir.IsBlank(left) {
return
}
@@ -3665,7 +3740,7 @@ func (s *state) assign(left ir.Node, right *ssa.Value, deref bool, skip skipMask
if right == nil {
s.zero(t, addr)
} else {
s.move(t, addr, right)
s.moveWhichMayOverlap(t, addr, right, mayOverlap)
}
return
}
@@ -7262,7 +7337,8 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
func defframe(s *State, e *ssafn, f *ssa.Func) {
pp := s.pp
frame := types.Rnd(s.maxarg+e.stksize, int64(types.RegSize))
s.maxarg = types.Rnd(s.maxarg, e.stkalign)
frame := s.maxarg + e.stksize
if Arch.PadFrame != nil {
frame = Arch.PadFrame(frame)
}
@@ -7700,7 +7776,14 @@ type ssafn struct {
strings map[string]*obj.LSym // map from constant string to data symbols
stksize int64 // stack size for current frame
stkptrsize int64 // prefix of stack containing pointers
log bool // print ssa debug to the stdout
// alignment for current frame.
// NOTE: when stkalign > PtrSize, currently this only ensures the offsets of
// objects in the stack frame are aligned. The stack pointer is still aligned
// only PtrSize.
stkalign int64
log bool // print ssa debug to the stdout
}
// StringData returns a symbol which

View File

@@ -14,7 +14,16 @@ import (
// the first run and then simply copied into bv at the correct offset
// on future calls with the same type t.
func Set(t *types.Type, off int64, bv bitvec.BitVec) {
if uint8(t.Alignment()) > 0 && off&int64(uint8(t.Alignment())-1) != 0 {
set(t, off, bv, false)
}
// SetNoCheck is like Set, but do not check for alignment.
func SetNoCheck(t *types.Type, off int64, bv bitvec.BitVec) {
set(t, off, bv, true)
}
func set(t *types.Type, off int64, bv bitvec.BitVec, skip bool) {
if !skip && uint8(t.Alignment()) > 0 && off&int64(uint8(t.Alignment())-1) != 0 {
base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, uint8(t.Alignment()), off)
}
if !t.HasPointers() {
@@ -72,13 +81,13 @@ func Set(t *types.Type, off int64, bv bitvec.BitVec) {
break
}
for i := int64(0); i < t.NumElem(); i++ {
Set(elt, off, bv)
set(elt, off, bv, skip)
off += elt.Size()
}
case types.TSTRUCT:
for _, f := range t.Fields().Slice() {
Set(f.Type, off+f.Offset, bv)
set(f.Type, off+f.Offset, bv, skip)
}
default:

View File

@@ -376,10 +376,10 @@ func runtimeTypes() []*types.Type {
typs[142] = newSig(params(typs[7], typs[1], typs[5]), nil)
typs[143] = types.NewSlice(typs[7])
typs[144] = newSig(params(typs[7], typs[143]), nil)
typs[145] = newSig(params(typs[66], typs[66], typs[15]), nil)
typs[146] = newSig(params(typs[60], typs[60], typs[15]), nil)
typs[147] = newSig(params(typs[62], typs[62], typs[15]), nil)
typs[148] = newSig(params(typs[24], typs[24], typs[15]), nil)
typs[149] = newSig(params(typs[28], typs[28], typs[15]), nil)
typs[145] = newSig(params(typs[66], typs[66], typs[17]), nil)
typs[146] = newSig(params(typs[60], typs[60], typs[17]), nil)
typs[147] = newSig(params(typs[62], typs[62], typs[17]), nil)
typs[148] = newSig(params(typs[24], typs[24], typs[17]), nil)
typs[149] = newSig(params(typs[28], typs[28], typs[17]), nil)
return typs[:]
}

View File

@@ -259,16 +259,16 @@ func asanwrite(addr, size uintptr)
func checkptrAlignment(unsafe.Pointer, *byte, uintptr)
func checkptrArithmetic(unsafe.Pointer, []unsafe.Pointer)
func libfuzzerTraceCmp1(uint8, uint8, int)
func libfuzzerTraceCmp2(uint16, uint16, int)
func libfuzzerTraceCmp4(uint32, uint32, int)
func libfuzzerTraceCmp8(uint64, uint64, int)
func libfuzzerTraceConstCmp1(uint8, uint8, int)
func libfuzzerTraceConstCmp2(uint16, uint16, int)
func libfuzzerTraceConstCmp4(uint32, uint32, int)
func libfuzzerTraceConstCmp8(uint64, uint64, int)
func libfuzzerHookStrCmp(string, string, int)
func libfuzzerHookEqualFold(string, string, int)
func libfuzzerTraceCmp1(uint8, uint8, uint)
func libfuzzerTraceCmp2(uint16, uint16, uint)
func libfuzzerTraceCmp4(uint32, uint32, uint)
func libfuzzerTraceCmp8(uint64, uint64, uint)
func libfuzzerTraceConstCmp1(uint8, uint8, uint)
func libfuzzerTraceConstCmp2(uint16, uint16, uint)
func libfuzzerTraceConstCmp4(uint32, uint32, uint)
func libfuzzerTraceConstCmp8(uint64, uint64, uint)
func libfuzzerHookStrCmp(string, string, uint)
func libfuzzerHookEqualFold(string, string, uint)
// architecture variants
var x86HasPOPCNT bool

View File

@@ -1928,7 +1928,9 @@ func (w *exportWriter) expr(n ir.Node) {
w.op(n.Op())
w.pos(n.Pos())
w.expr(n.X)
w.expr(n.RType)
if w.bool(n.RType != nil) {
w.expr(n.RType)
}
if w.bool(n.ITab != nil) {
w.expr(n.ITab)
}

View File

@@ -1465,7 +1465,10 @@ func (r *importReader) node() ir.Node {
return n
case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2:
n := ir.NewDynamicTypeAssertExpr(r.pos(), op, r.expr(), r.expr())
n := ir.NewDynamicTypeAssertExpr(r.pos(), op, r.expr(), nil)
if r.bool() {
n.RType = r.expr()
}
if r.bool() {
n.ITab = r.expr()
}

View File

@@ -637,3 +637,40 @@ func TestIssue50646(t *testing.T) {
t.Errorf("comparable not assignable to any")
}
}
func TestIssue55030(t *testing.T) {
// makeSig makes the signature func(typ...)
makeSig := func(typ Type) {
par := NewVar(nopos, nil, "", typ)
params := NewTuple(par)
NewSignatureType(nil, nil, nil, params, nil, true)
}
// makeSig must not panic for the following (example) types:
// []int
makeSig(NewSlice(Typ[Int]))
// string
makeSig(Typ[String])
// P where P's core type is string
{
P := NewTypeName(nopos, nil, "P", nil) // [P string]
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
}
// P where P's core type is an (unnamed) slice
{
P := NewTypeName(nopos, nil, "P", nil) // [P []int]
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
}
// P where P's core type is bytestring (i.e., string or []byte)
{
t1 := NewTerm(true, Typ[String]) // ~string
t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
u := NewUnion([]*Term{t1, t2}) // ~string | []byte
P := NewTypeName(nopos, nil, "P", nil) // [P ~string | []byte]
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
}
}

View File

@@ -4,7 +4,10 @@
package types2
import "cmd/compile/internal/syntax"
import (
"cmd/compile/internal/syntax"
"fmt"
)
// ----------------------------------------------------------------------------
// API
@@ -28,16 +31,18 @@ type Signature struct {
// NewSignatureType creates a new function type for the given receiver,
// receiver type parameters, type parameters, parameters, and results. If
// variadic is set, params must hold at least one parameter and the last
// parameter must be of unnamed slice type. If recv is non-nil, typeParams must
// be empty. If recvTypeParams is non-empty, recv must be non-nil.
// parameter's core type must be of unnamed slice or bytestring type.
// If recv is non-nil, typeParams must be empty. If recvTypeParams is
// non-empty, recv must be non-nil.
func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature {
if variadic {
n := params.Len()
if n == 0 {
panic("variadic function must have at least one parameter")
}
if _, ok := params.At(n - 1).typ.(*Slice); !ok {
panic("variadic parameter must be of unnamed slice type")
core := coreString(params.At(n - 1).typ)
if _, ok := core.(*Slice); !ok && !isString(core) {
panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String()))
}
}
sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}

View File

@@ -53,7 +53,7 @@ func (s *StdSizes) Alignof(T Type) int64 {
// is the same as unsafe.Alignof(x[0]), but at least 1."
return s.Alignof(t.elem)
case *Struct:
if len(t.fields) == 0 && isSyncAtomicAlign64(T) {
if len(t.fields) == 0 && IsSyncAtomicAlign64(T) {
// Special case: sync/atomic.align64 is an
// empty struct we recognize as a signal that
// the struct it contains must be
@@ -104,7 +104,7 @@ func (s *StdSizes) Alignof(T Type) int64 {
return a
}
func isSyncAtomicAlign64(T Type) bool {
func IsSyncAtomicAlign64(T Type) bool {
named, ok := T.(*Named)
if !ok {
return false

View File

@@ -243,6 +243,7 @@ func fixedlit(ctxt initContext, kind initKind, n *ir.CompLitExpr, var_ ir.Node,
// confuses about variables lifetime. So making sure those expressions
// are ordered correctly here. See issue #52673.
orderBlock(&sinit, map[string][]*ir.Name{})
walkStmtList(sinit)
}
init.Append(sinit...)
continue

View File

@@ -938,7 +938,8 @@ func packagefile(pkg string) string {
}
// unixOS is the set of GOOS values matched by the "unix" build tag.
// This is the same list as in go/build/syslist.go.
// This is the same list as in go/build/syslist.go and
// cmd/go/internal/imports/build.go.
var unixOS = map[string]bool{
"aix": true,
"android": true,

View File

@@ -3,7 +3,7 @@ module cmd
go 1.19
require (
github.com/google/pprof v0.0.0-20220517023622-154dc81eb7b0
github.com/google/pprof v0.0.0-20220729232143-a41b82acbcb1
golang.org/x/arch v0.0.0-20220412001346-fc48f9fe4c15
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29

View File

@@ -1,5 +1,5 @@
github.com/google/pprof v0.0.0-20220517023622-154dc81eb7b0 h1:XgEFTOJTsN3Li0Txfhn2UzsysGJfXIDe7wE07uY7ZfI=
github.com/google/pprof v0.0.0-20220517023622-154dc81eb7b0/go.mod h1:gSuNB+gJaOiQKLEZ+q+PK9Mq3SOzhRcw2GsGS/FhYDk=
github.com/google/pprof v0.0.0-20220729232143-a41b82acbcb1 h1:8pyqKJvrJqUYaKS851Ule26pwWvey6IDMiczaBLDKLQ=
github.com/google/pprof v0.0.0-20220729232143-a41b82acbcb1/go.mod h1:gSuNB+gJaOiQKLEZ+q+PK9Mq3SOzhRcw2GsGS/FhYDk=
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2 h1:rcanfLhLDA8nozr/K289V1zcntHr3V+SHlXwzz1ZI2g=
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
golang.org/x/arch v0.0.0-20220412001346-fc48f9fe4c15 h1:GVfVkciLYxn5mY5EncwAe0SXUn9Rm81rRkZ0TTmn/cU=

View File

@@ -174,8 +174,8 @@ func ExtraEnvVars() []cfg.EnvVar {
// ExtraEnvVarsCostly returns environment variables that should not leak into child processes
// but are costly to evaluate.
func ExtraEnvVarsCostly() []cfg.EnvVar {
var b work.Builder
b.Init()
b := work.NewBuilder("")
cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{})
if err != nil {
// Should not happen - b.CFlags was given an empty package.

View File

@@ -20,6 +20,7 @@ package imports
import (
"bytes"
"cmd/go/internal/cfg"
"errors"
"fmt"
"go/build/constraint"
@@ -201,17 +202,22 @@ func matchTag(name string, tags map[string]bool, prefer bool) bool {
return prefer
}
have := tags[name]
if name == "linux" {
have = have || tags["android"]
if tags[name] {
return true
}
if name == "solaris" {
have = have || tags["illumos"]
switch name {
case "linux":
return tags["android"]
case "solaris":
return tags["illumos"]
case "darwin":
return tags["ios"]
case "unix":
return unixOS[cfg.BuildContext.GOOS]
default:
return false
}
if name == "darwin" {
have = have || tags["ios"]
}
return have
}
// eval is like
@@ -322,6 +328,24 @@ var KnownOS = map[string]bool{
"zos": true,
}
// unixOS is the set of GOOS values matched by the "unix" build tag.
// This is not used for filename matching.
// This is the same list as in go/build/syslist.go and cmd/dist/build.go.
var unixOS = map[string]bool{
"aix": true,
"android": true,
"darwin": true,
"dragonfly": true,
"freebsd": true,
"hurd": true,
"illumos": true,
"ios": true,
"linux": true,
"netbsd": true,
"openbsd": true,
"solaris": true,
}
var KnownArch = map[string]bool{
"386": true,
"amd64": true,

View File

@@ -36,6 +36,9 @@ func loadTags() map[string]bool {
for _, tag := range cfg.BuildContext.BuildTags {
tags[tag] = true
}
for _, tag := range cfg.BuildContext.ToolTags {
tags[tag] = true
}
for _, tag := range cfg.BuildContext.ReleaseTags {
tags[tag] = true
}

View File

@@ -689,8 +689,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
// Do we need to run a build to gather information?
needStale := (listJson && listJsonFields.needAny("Stale", "StaleReason")) || strings.Contains(*listFmt, ".Stale")
if needStale || *listExport || *listCompiled {
var b work.Builder
b.Init()
b := work.NewBuilder("")
b.IsCmdList = true
b.NeedExport = *listExport
b.NeedCompiledGoFiles = *listCompiled

View File

@@ -37,7 +37,9 @@ const (
// A Repo represents a code hosting source.
// Typical implementations include local version control repositories,
// remote version control servers, and code hosting sites.
// A Repo must be safe for simultaneous use by multiple goroutines.
//
// A Repo must be safe for simultaneous use by multiple goroutines,
// and callers must not modify returned values, which may be cached and shared.
type Repo interface {
// CheckReuse checks whether the old origin information
// remains up to date. If so, whatever cached object it was

View File

@@ -348,12 +348,21 @@ func (r *gitRepo) Latest() (*RevInfo, error) {
if refs["HEAD"] == "" {
return nil, ErrNoCommits
}
info, err := r.Stat(refs["HEAD"])
statInfo, err := r.Stat(refs["HEAD"])
if err != nil {
return nil, err
}
// Stat may return cached info, so make a copy to modify here.
info := new(RevInfo)
*info = *statInfo
info.Origin = new(Origin)
if statInfo.Origin != nil {
*info.Origin = *statInfo.Origin
}
info.Origin.Ref = "HEAD"
info.Origin.Hash = refs["HEAD"]
return info, nil
}
@@ -560,7 +569,7 @@ func (r *gitRepo) fetchRefsLocked() error {
return nil
}
// statLocal returns a RevInfo describing rev in the local git repository.
// statLocal returns a new RevInfo describing rev in the local git repository.
// It uses version as info.Version.
func (r *gitRepo) statLocal(version, rev string) (*RevInfo, error) {
out, err := Run(r.dir, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", rev, "--")

View File

@@ -182,23 +182,27 @@ func mergeOrigin(m1, m2 *codehost.Origin) *codehost.Origin {
if !m2.Checkable() {
return m2
}
merged := new(codehost.Origin)
*merged = *m1 // Clone to avoid overwriting fields in cached results.
if m2.TagSum != "" {
if m1.TagSum != "" && (m1.TagSum != m2.TagSum || m1.TagPrefix != m2.TagPrefix) {
m1.ClearCheckable()
return m1
merged.ClearCheckable()
return merged
}
m1.TagSum = m2.TagSum
m1.TagPrefix = m2.TagPrefix
merged.TagSum = m2.TagSum
merged.TagPrefix = m2.TagPrefix
}
if m2.Hash != "" {
if m1.Hash != "" && (m1.Hash != m2.Hash || m1.Ref != m2.Ref) {
m1.ClearCheckable()
return m1
merged.ClearCheckable()
return merged
}
m1.Hash = m2.Hash
m1.Ref = m2.Ref
merged.Hash = m2.Hash
merged.Ref = m2.Ref
}
return m1
return merged
}
// addVersions fills in m.Versions with the list of known versions.

View File

@@ -27,7 +27,7 @@ var importTests = []struct {
},
{
path: "golang.org/x/net",
err: `module golang.org/x/net@.* found \(v0.0.0-.*\), but does not contain package golang.org/x/net`,
err: `module golang.org/x/net@.* found \(v[01]\.\d+\.\d+\), but does not contain package golang.org/x/net`,
},
{
path: "golang.org/x/text",

View File

@@ -220,6 +220,17 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed
return revErr, err
}
mergeRevOrigin := func(rev *modfetch.RevInfo, origin *codehost.Origin) *modfetch.RevInfo {
merged := mergeOrigin(rev.Origin, origin)
if merged == rev.Origin {
return rev
}
clone := new(modfetch.RevInfo)
*clone = *rev
clone.Origin = merged
return clone
}
lookup := func(v string) (*modfetch.RevInfo, error) {
rev, err := repo.Stat(v)
// Stat can return a non-nil rev and a non-nil err,
@@ -227,7 +238,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed
if rev == nil && err != nil {
return revErr, err
}
rev.Origin = mergeOrigin(rev.Origin, versions.Origin)
rev = mergeRevOrigin(rev, versions.Origin)
if err != nil {
return rev, err
}
@@ -256,12 +267,12 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed
if err := allowed(ctx, module.Version{Path: path, Version: current}); errors.Is(err, ErrDisallowed) {
return revErr, err
}
info, err := repo.Stat(current)
if info == nil && err != nil {
rev, err = repo.Stat(current)
if rev == nil && err != nil {
return revErr, err
}
info.Origin = mergeOrigin(info.Origin, versions.Origin)
return info, err
rev = mergeRevOrigin(rev, versions.Origin)
return rev, err
}
}

View File

@@ -91,8 +91,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
}
work.BuildInit()
var b work.Builder
b.Init()
b := work.NewBuilder("")
b.Print = printStderr
i := 0

View File

@@ -744,8 +744,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
}
}
var b work.Builder
b.Init()
b := work.NewBuilder("")
if cfg.BuildI {
fmt.Fprint(os.Stderr, "go: -i flag is deprecated\n")
@@ -800,7 +799,16 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
if !testC || a.Failed {
return
}
b.Init()
// TODO(bcmills): I have no idea why the Builder must be reset here, but
// without this reset dance, TestGoTestDashIDashOWritesBinary fails with
// lots of "vet config not found" errors. This was added in CL 5699088,
// which had almost no public discussion, a very short commit description,
// and left no comment in the code to explain what is going on here. 🤯
//
// Maybe this has the effect of removing actions that were registered by the
// call to CompileAction above?
b = work.NewBuilder("")
}
var builds, runs, prints []*work.Action
@@ -916,7 +924,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
ensureImport(p, "sync/atomic")
}
buildTest, runTest, printTest, err := builderTest(&b, ctx, pkgOpts, p, allImports[p])
buildTest, runTest, printTest, err := builderTest(b, ctx, pkgOpts, p, allImports[p])
if err != nil {
str := err.Error()
str = strings.TrimPrefix(str, "\n")

View File

@@ -94,8 +94,7 @@ func runVet(ctx context.Context, cmd *base.Command, args []string) {
base.Fatalf("no packages to vet")
}
var b work.Builder
b.Init()
b := work.NewBuilder("")
root := &work.Action{Mode: "go vet"}
for _, p := range pkgs {

View File

@@ -240,7 +240,13 @@ const (
ModeVetOnly = 1 << 8
)
func (b *Builder) Init() {
// NewBuilder returns a new Builder ready for use.
//
// If workDir is the empty string, NewBuilder creates a WorkDir if needed
// and arranges for it to be removed in case of an unclean exit.
func NewBuilder(workDir string) *Builder {
b := new(Builder)
b.Print = func(a ...any) (int, error) {
return fmt.Fprint(os.Stderr, a...)
}
@@ -249,7 +255,9 @@ func (b *Builder) Init() {
b.toolIDCache = make(map[string]string)
b.buildIDCache = make(map[string]string)
if cfg.BuildN {
if workDir != "" {
b.WorkDir = workDir
} else if cfg.BuildN {
b.WorkDir = "$WORK"
} else {
tmp, err := os.MkdirTemp(cfg.Getenv("GOTMPDIR"), "go-build")
@@ -306,6 +314,8 @@ func (b *Builder) Init() {
base.Exit()
}
}
return b
}
func CheckGOOSARCHPair(goos, goarch string) error {

View File

@@ -403,8 +403,7 @@ var RuntimeVersion = runtime.Version()
func runBuild(ctx context.Context, cmd *base.Command, args []string) {
modload.InitWorkfile()
BuildInit()
var b Builder
b.Init()
b := NewBuilder("")
pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{LoadVCS: true}, args)
load.CheckPackageErrors(pkgs)
@@ -728,8 +727,8 @@ func InstallPackages(ctx context.Context, patterns []string, pkgs []*load.Packag
}
base.ExitIfErrors()
var b Builder
b.Init()
b := NewBuilder("")
depMode := ModeBuild
if cfg.BuildI {
depMode = ModeInstall

View File

@@ -556,10 +556,8 @@ func (ts *testScript) cmdCc(want simpleStatus, args []string) {
ts.fatalf("usage: cc args... [&]")
}
var b work.Builder
b.Init()
b := work.NewBuilder(ts.workdir)
ts.cmdExec(want, append(b.GccCmd(".", ""), args...))
robustio.RemoveAll(b.WorkDir)
}
// cd changes to a different directory.

View File

@@ -0,0 +1,32 @@
# Regression test for https://go.dev/issue/54712: the "unix" build constraint
# was not applied consistently during package loading.
go list -x -f '{{if .Module}}{{.ImportPath}}{{end}}' -deps .
stdout 'example.com/version'
-- go.mod --
module example
go 1.19
require example.com/version v1.1.0
-- go.sum --
example.com/version v1.1.0 h1:VdPnGmIF1NJrntStkxGrF3L/OfhaL567VzCjncGUgtM=
example.com/version v1.1.0/go.mod h1:S7K9BnT4o5wT4PCczXPfWVzpjD4ud4e7AJMQJEgiu2Q=
-- main_notunix.go --
//go:build !(aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris)
package main
import _ "example.com/version"
func main() {}
-- main_unix.go --
//go:build unix
package main
import _ "example.com/version"
func main() {}

View File

@@ -0,0 +1,29 @@
# Tests Issue #54468
[short] skip 'links a test binary'
[!race] skip
go mod tidy
go test -c -o=$devnull -race .
! stderr 'cannot find package'
-- go.mod --
module testrace
go 1.18
require rsc.io/sampler v1.0.0
-- race_test.go --
//go:build race
package testrace
import (
"testing"
_ "rsc.io/sampler"
)
func TestRaceTag(t *testing.T) {
}

View File

@@ -1842,3 +1842,82 @@ func main() {
}
}
}
func TestIssue54320(t *testing.T) {
// Check that when trampolines are used, the DWARF LPT is correctly
// emitted in the final binary
testenv.MustHaveGoBuild(t)
if runtime.GOOS == "plan9" {
t.Skip("skipping on plan9; no DWARF symbol table in executables")
}
t.Parallel()
const prog = `
package main
import "fmt"
func main() {
fmt.Printf("Hello world\n");
}
`
dir := t.TempDir()
f := gobuild(t, dir, prog, "-ldflags=-debugtramp=2")
defer f.Close()
d, err := f.DWARF()
if err != nil {
t.Fatalf("error reading DWARF: %v", err)
}
rdr := d.Reader()
found := false
var entry *dwarf.Entry
for entry, err = rdr.Next(); entry != nil; entry, err = rdr.Next() {
if err != nil {
t.Fatalf("error reading DWARF: %v", err)
}
if entry.Tag != dwarf.TagCompileUnit {
continue
}
name, _ := entry.Val(dwarf.AttrName).(string)
if name == "main" {
found = true
break
}
rdr.SkipChildren()
}
if !found {
t.Fatalf("could not find main compile unit")
}
lr, err := d.LineReader(entry)
if err != nil {
t.Fatalf("error obtaining linereader: %v", err)
}
var le dwarf.LineEntry
found = false
for {
if err := lr.Next(&le); err != nil {
if err == io.EOF {
break
}
t.Fatalf("error reading linentry: %v", err)
}
// check LE contains an entry to test.go
if le.File == nil {
continue
}
file := filepath.Base(le.File.Name)
if file == "test.go" {
found = true
break
}
}
if !found {
t.Errorf("no LPT entries for test.go")
}
}

View File

@@ -1423,7 +1423,6 @@ func (ctxt *Link) hostlink() {
if ctxt.HeadType == objabi.Hdarwin {
if machoPlatform == PLATFORM_MACOS && ctxt.IsAMD64() {
argv = append(argv, "-Wl,-no_pie")
argv = append(argv, "-Wl,-pagezero_size,4000000")
}
}
if *flagRace && ctxt.HeadType == objabi.Hwindows {
@@ -1775,6 +1774,13 @@ func (ctxt *Link) hostlink() {
if len(out) > 0 {
// always print external output even if the command is successful, so that we don't
// swallow linker warnings (see https://golang.org/issue/17935).
if ctxt.IsDarwin() && ctxt.IsAMD64() {
const noPieWarning = "ld: warning: -no_pie is deprecated when targeting new OS versions\n"
if i := bytes.Index(out, []byte(noPieWarning)); i >= 0 {
// swallow -no_pie deprecation warning, issue 54482
out = append(out[:i], out[i+len(noPieWarning):]...)
}
}
ctxt.Logf("%s", out)
}

View File

@@ -1610,13 +1610,8 @@ func (l *Loader) GetFuncDwarfAuxSyms(fnSymIdx Sym) (auxDwarfInfo, auxDwarfLoc, a
if l.SymType(fnSymIdx) != sym.STEXT {
log.Fatalf("error: non-function sym %d/%s t=%s passed to GetFuncDwarfAuxSyms", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String())
}
if l.IsExternal(fnSymIdx) {
// Current expectation is that any external function will
// not have auxsyms.
return
}
r, li := l.toLocal(fnSymIdx)
auxs := r.Auxs(li)
r, auxs := l.auxs(fnSymIdx)
for i := range auxs {
a := &auxs[i]
switch a.Type() {

View File

@@ -79,7 +79,7 @@ type configMenuEntry struct {
}
// configMenu returns a list of items to add to a menu in the web UI.
func configMenu(fname string, url url.URL) []configMenuEntry {
func configMenu(fname string, u url.URL) []configMenuEntry {
// Start with system configs.
configs := []namedConfig{{Name: "Default", config: defaultConfig()}}
if settings, err := readSettings(fname); err == nil {
@@ -91,13 +91,15 @@ func configMenu(fname string, url url.URL) []configMenuEntry {
result := make([]configMenuEntry, len(configs))
lastMatch := -1
for i, cfg := range configs {
dst, changed := cfg.config.makeURL(url)
dst, changed := cfg.config.makeURL(u)
if !changed {
lastMatch = i
}
// Use a relative URL to work in presence of stripping/redirects in webui.go.
rel := &url.URL{RawQuery: dst.RawQuery, ForceQuery: true}
result[i] = configMenuEntry{
Name: cfg.Name,
URL: dst.String(),
URL: rel.String(),
UserConfig: (i != 0),
}
}

View File

@@ -385,6 +385,9 @@ func multilinePrintableName(info *NodeInfo) string {
infoCopy := *info
infoCopy.Name = escapeForDot(ShortenFunctionName(infoCopy.Name))
infoCopy.Name = strings.Replace(infoCopy.Name, "::", `\n`, -1)
// Go type parameters are reported as "[...]" by Go pprof profiles.
// Keep this ellipsis rather than replacing with newlines below.
infoCopy.Name = strings.Replace(infoCopy.Name, "[...]", "[…]", -1)
infoCopy.Name = strings.Replace(infoCopy.Name, ".", `\n`, -1)
if infoCopy.File != "" {
infoCopy.File = filepath.Base(infoCopy.File)

View File

@@ -205,49 +205,64 @@ func Demangle(prof *profile.Profile, force bool, demanglerMode string) {
}
}
var options []demangle.Option
options := demanglerModeToOptions(demanglerMode)
for _, fn := range prof.Function {
demangleSingleFunction(fn, options)
}
}
func demanglerModeToOptions(demanglerMode string) []demangle.Option {
switch demanglerMode {
case "": // demangled, simplified: no parameters, no templates, no return type
options = []demangle.Option{demangle.NoParams, demangle.NoTemplateParams}
return []demangle.Option{demangle.NoParams, demangle.NoTemplateParams}
case "templates": // demangled, simplified: no parameters, no return type
options = []demangle.Option{demangle.NoParams}
return []demangle.Option{demangle.NoParams}
case "full":
options = []demangle.Option{demangle.NoClones}
return []demangle.Option{demangle.NoClones}
case "none": // no demangling
return
return []demangle.Option{}
}
panic(fmt.Sprintf("unknown demanglerMode %s", demanglerMode))
}
func demangleSingleFunction(fn *profile.Function, options []demangle.Option) {
if fn.Name != "" && fn.SystemName != fn.Name {
return // Already demangled.
}
// Copy the options because they may be updated by the call.
o := make([]demangle.Option, len(options))
for _, fn := range prof.Function {
if fn.Name != "" && fn.SystemName != fn.Name {
continue // Already demangled.
}
copy(o, options)
if demangled := demangle.Filter(fn.SystemName, o...); demangled != fn.SystemName {
fn.Name = demangled
continue
}
// Could not demangle. Apply heuristics in case the name is
// already demangled.
name := fn.SystemName
if looksLikeDemangledCPlusPlus(name) {
if demanglerMode == "" || demanglerMode == "templates" {
copy(o, options)
if demangled := demangle.Filter(fn.SystemName, o...); demangled != fn.SystemName {
fn.Name = demangled
return
}
// Could not demangle. Apply heuristics in case the name is
// already demangled.
name := fn.SystemName
if looksLikeDemangledCPlusPlus(name) {
for _, o := range options {
switch o {
case demangle.NoParams:
name = removeMatching(name, '(', ')')
}
if demanglerMode == "" {
case demangle.NoTemplateParams:
name = removeMatching(name, '<', '>')
}
}
fn.Name = name
}
fn.Name = name
}
// looksLikeDemangledCPlusPlus is a heuristic to decide if a name is
// the result of demangling C++. If so, further heuristics will be
// applied to simplify the name.
func looksLikeDemangledCPlusPlus(demangled string) bool {
if strings.Contains(demangled, ".<") { // Skip java names of the form "class.<init>"
// Skip java names of the form "class.<init>".
if strings.Contains(demangled, ".<") {
return false
}
// Skip Go names of the form "foo.(*Bar[...]).Method".
if strings.Contains(demangled, "]).") {
return false
}
return strings.ContainsAny(demangled, "<>[]") || strings.Contains(demangled, "::")

View File

@@ -1,4 +1,4 @@
# github.com/google/pprof v0.0.0-20220517023622-154dc81eb7b0
# github.com/google/pprof v0.0.0-20220729232143-a41b82acbcb1
## explicit; go 1.17
github.com/google/pprof/driver
github.com/google/pprof/internal/binutils

View File

@@ -240,7 +240,7 @@ func (hs *serverHandshakeState) processClientHello() error {
hs.ecdheOk = supportsECDHE(c.config, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints)
if hs.ecdheOk {
if hs.ecdheOk && len(hs.clientHello.supportedPoints) > 0 {
// Although omitting the ec_point_formats extension is permitted, some
// old OpenSSL version will refuse to handshake if not present.
//
@@ -321,6 +321,13 @@ func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8
break
}
}
// Per RFC 8422, Section 5.1.2, if the Supported Point Formats extension is
// missing, uncompressed points are supported. If supportedPoints is empty,
// the extension must be missing, as an empty extension body is rejected by
// the parser. See https://go.dev/issue/49126.
if len(supportedPoints) == 0 {
supportsPointFormat = true
}
return supportsCurve && supportsPointFormat
}

View File

@@ -281,7 +281,7 @@ func TestTLS12OnlyCipherSuites(t *testing.T) {
func TestTLSPointFormats(t *testing.T) {
// Test that a Server returns the ec_point_format extension when ECC is
// negotiated, and not returned on RSA handshake.
// negotiated, and not on a RSA handshake or if ec_point_format is missing.
tests := []struct {
name string
cipherSuites []uint16
@@ -289,8 +289,11 @@ func TestTLSPointFormats(t *testing.T) {
supportedPoints []uint8
wantSupportedPoints bool
}{
{"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{compressionNone}, true},
{"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{pointFormatUncompressed}, true},
{"ECC without ec_point_format", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, nil, false},
{"ECC with extra values", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{13, 37, pointFormatUncompressed, 42}, true},
{"RSA", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, nil, false},
{"RSA with ec_point_format", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, []uint8{pointFormatUncompressed}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -330,18 +333,8 @@ func TestTLSPointFormats(t *testing.T) {
t.Fatalf("didn't get ServerHello message in reply. Got %v\n", reply)
}
if tt.wantSupportedPoints {
if len(serverHello.supportedPoints) < 1 {
t.Fatal("missing ec_point_format extension from server")
}
found := false
for _, p := range serverHello.supportedPoints {
if p == pointFormatUncompressed {
found = true
break
}
}
if !found {
t.Fatal("missing uncompressed format in ec_point_format extension from server")
if !bytes.Equal(serverHello.supportedPoints, []uint8{pointFormatUncompressed}) {
t.Fatal("incorrect ec_point_format extension from server")
}
} else {
if len(serverHello.supportedPoints) != 0 {

View File

@@ -54,6 +54,9 @@ func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
// marshalECPrivateKey marshals an EC private key into ASN.1, DER format and
// sets the curve ID to the given OID, or omits it if OID is nil.
func marshalECPrivateKeyWithOID(key *ecdsa.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) {
if !key.Curve.IsOnCurve(key.X, key.Y) {
return nil, errors.New("invalid elliptic key public key")
}
privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
return asn1.Marshal(ecPrivateKey{
Version: 1,

View File

@@ -84,11 +84,14 @@ func marshalPublicKey(pub any) (publicKeyBytes []byte, publicKeyAlgorithm pkix.A
// RFC 3279, Section 2.3.1.
publicKeyAlgorithm.Parameters = asn1.NullRawValue
case *ecdsa.PublicKey:
publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
oid, ok := oidFromNamedCurve(pub.Curve)
if !ok {
return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve")
}
if !pub.Curve.IsOnCurve(pub.X, pub.Y) {
return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: invalid elliptic curve public key")
}
publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
var paramBytes []byte
paramBytes, err = asn1.Marshal(oid)

View File

@@ -68,6 +68,20 @@ func TestPKCS1MismatchPublicKeyFormat(t *testing.T) {
}
}
func TestMarshalInvalidPublicKey(t *testing.T) {
_, err := MarshalPKIXPublicKey(&ecdsa.PublicKey{})
if err == nil {
t.Errorf("expected error, got MarshalPKIXPublicKey success")
}
_, err = MarshalPKIXPublicKey(&ecdsa.PublicKey{
Curve: elliptic.P256(),
X: big.NewInt(1), Y: big.NewInt(2),
})
if err == nil {
t.Errorf("expected error, got MarshalPKIXPublicKey success")
}
}
func testParsePKIXPublicKey(t *testing.T, pemBytes string) (pub any) {
block, _ := pem.Decode([]byte(pemBytes))
pub, err := ParsePKIXPublicKey(block.Bytes)

View File

@@ -4,7 +4,7 @@ go 1.19
require (
golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8
golang.org/x/net v0.0.0-20220517181318-183a9ca12b87
golang.org/x/net v0.0.0-20220907013720-d52c520e3766
)
require (

View File

@@ -1,7 +1,7 @@
golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8 h1:y+mHpWoQJNAHt26Nhh6JP7hvM71IRZureyvZhoVALIs=
golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20220517181318-183a9ca12b87 h1:cCR+9mKLOGyX4Zx+uBZDXEDAQsvKQ/XbW4vreG5v1jU=
golang.org/x/net v0.0.0-20220517181318-183a9ca12b87/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220907013720-d52c520e3766 h1:D02YdIT3M6OQkZXTQiO761u/SmR3DDDiDXLN2oZIUac=
golang.org/x/net v0.0.0-20220907013720-d52c520e3766/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA=
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 h1:h+pU/hCb7sEApigI6eII3/Emx5ZHaFWS+nulUp0Az/k=

View File

@@ -33,7 +33,8 @@ var knownOS = map[string]bool{
// unixOS is the set of GOOS values matched by the "unix" build tag.
// This is not used for filename matching.
// This list also appears in cmd/dist/build.go.
// This list also appears in cmd/dist/build.go and
// cmd/go/internal/imports/build.go.
var unixOS = map[string]bool{
"aix": true,
"android": true,

View File

@@ -664,3 +664,40 @@ func TestIssue50646(t *testing.T) {
t.Errorf("comparable not assignable to any")
}
}
func TestIssue55030(t *testing.T) {
// makeSig makes the signature func(typ...)
makeSig := func(typ Type) {
par := NewVar(token.NoPos, nil, "", typ)
params := NewTuple(par)
NewSignatureType(nil, nil, nil, params, nil, true)
}
// makeSig must not panic for the following (example) types:
// []int
makeSig(NewSlice(Typ[Int]))
// string
makeSig(Typ[String])
// P where P's core type is string
{
P := NewTypeName(token.NoPos, nil, "P", nil) // [P string]
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
}
// P where P's core type is an (unnamed) slice
{
P := NewTypeName(token.NoPos, nil, "P", nil) // [P []int]
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
}
// P where P's core type is bytestring (i.e., string or []byte)
{
t1 := NewTerm(true, Typ[String]) // ~string
t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
u := NewUnion([]*Term{t1, t2}) // ~string | []byte
P := NewTypeName(token.NoPos, nil, "P", nil) // [P ~string | []byte]
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
}
}

View File

@@ -5,6 +5,7 @@
package types
import (
"fmt"
"go/ast"
"go/token"
)
@@ -41,16 +42,18 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
// NewSignatureType creates a new function type for the given receiver,
// receiver type parameters, type parameters, parameters, and results. If
// variadic is set, params must hold at least one parameter and the last
// parameter must be of unnamed slice type. If recv is non-nil, typeParams must
// be empty. If recvTypeParams is non-empty, recv must be non-nil.
// parameter's core type must be of unnamed slice or bytestring type.
// If recv is non-nil, typeParams must be empty. If recvTypeParams is
// non-empty, recv must be non-nil.
func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature {
if variadic {
n := params.Len()
if n == 0 {
panic("variadic function must have at least one parameter")
}
if _, ok := params.At(n - 1).typ.(*Slice); !ok {
panic("variadic parameter must be of unnamed slice type")
core := coreString(params.At(n - 1).typ)
if _, ok := core.(*Slice); !ok && !isString(core) {
panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String()))
}
}
sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}

View File

@@ -21,15 +21,15 @@ import _ "unsafe" // for go:linkname
//go:linkname libfuzzerHookStrCmp runtime.libfuzzerHookStrCmp
//go:linkname libfuzzerHookEqualFold runtime.libfuzzerHookEqualFold
func libfuzzerTraceCmp1(arg0, arg1 uint8, fakePC int) {}
func libfuzzerTraceCmp2(arg0, arg1 uint16, fakePC int) {}
func libfuzzerTraceCmp4(arg0, arg1 uint32, fakePC int) {}
func libfuzzerTraceCmp8(arg0, arg1 uint64, fakePC int) {}
func libfuzzerTraceCmp1(arg0, arg1 uint8, fakePC uint) {}
func libfuzzerTraceCmp2(arg0, arg1 uint16, fakePC uint) {}
func libfuzzerTraceCmp4(arg0, arg1 uint32, fakePC uint) {}
func libfuzzerTraceCmp8(arg0, arg1 uint64, fakePC uint) {}
func libfuzzerTraceConstCmp1(arg0, arg1 uint8, fakePC int) {}
func libfuzzerTraceConstCmp2(arg0, arg1 uint16, fakePC int) {}
func libfuzzerTraceConstCmp4(arg0, arg1 uint32, fakePC int) {}
func libfuzzerTraceConstCmp8(arg0, arg1 uint64, fakePC int) {}
func libfuzzerTraceConstCmp1(arg0, arg1 uint8, fakePC uint) {}
func libfuzzerTraceConstCmp2(arg0, arg1 uint16, fakePC uint) {}
func libfuzzerTraceConstCmp4(arg0, arg1 uint32, fakePC uint) {}
func libfuzzerTraceConstCmp8(arg0, arg1 uint64, fakePC uint) {}
func libfuzzerHookStrCmp(arg0, arg1 string, fakePC int) {}
func libfuzzerHookEqualFold(arg0, arg1 string, fakePC int) {}
func libfuzzerHookStrCmp(arg0, arg1 string, fakePC uint) {}
func libfuzzerHookEqualFold(arg0, arg1 string, fakePC uint) {}

View File

@@ -5058,6 +5058,9 @@ func (sc *http2serverConn) startGracefulShutdownInternal() {
func (sc *http2serverConn) goAway(code http2ErrCode) {
sc.serveG.check()
if sc.inGoAway {
if sc.goAwayCode == http2ErrCodeNo {
sc.goAwayCode = code
}
return
}
sc.inGoAway = true

View File

@@ -261,6 +261,9 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
}
p.Director(outreq)
if outreq.Form != nil {
outreq.URL.RawQuery = cleanQueryParams(outreq.URL.RawQuery)
}
outreq.Close = false
reqUpType := upgradeType(outreq.Header)
@@ -639,3 +642,36 @@ func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
_, err := io.Copy(c.backend, c.user)
errc <- err
}
func cleanQueryParams(s string) string {
reencode := func(s string) string {
v, _ := url.ParseQuery(s)
return v.Encode()
}
for i := 0; i < len(s); {
switch s[i] {
case ';':
return reencode(s)
case '%':
if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
return reencode(s)
}
i += 3
default:
i++
}
}
return s
}
func ishex(c byte) bool {
switch {
case '0' <= c && c <= '9':
return true
case 'a' <= c && c <= 'f':
return true
case 'A' <= c && c <= 'F':
return true
}
return false
}

View File

@@ -1537,3 +1537,77 @@ func TestJoinURLPath(t *testing.T) {
}
}
}
const (
testWantsCleanQuery = true
testWantsRawQuery = false
)
func TestReverseProxyQueryParameterSmugglingDirectorDoesNotParseForm(t *testing.T) {
testReverseProxyQueryParameterSmuggling(t, testWantsRawQuery, func(u *url.URL) *ReverseProxy {
proxyHandler := NewSingleHostReverseProxy(u)
oldDirector := proxyHandler.Director
proxyHandler.Director = func(r *http.Request) {
oldDirector(r)
}
return proxyHandler
})
}
func TestReverseProxyQueryParameterSmugglingDirectorParsesForm(t *testing.T) {
testReverseProxyQueryParameterSmuggling(t, testWantsCleanQuery, func(u *url.URL) *ReverseProxy {
proxyHandler := NewSingleHostReverseProxy(u)
oldDirector := proxyHandler.Director
proxyHandler.Director = func(r *http.Request) {
// Parsing the form causes ReverseProxy to remove unparsable
// query parameters before forwarding.
r.FormValue("a")
oldDirector(r)
}
return proxyHandler
})
}
func testReverseProxyQueryParameterSmuggling(t *testing.T, wantCleanQuery bool, newProxy func(*url.URL) *ReverseProxy) {
const content = "response_content"
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(r.URL.RawQuery))
}))
defer backend.Close()
backendURL, err := url.Parse(backend.URL)
if err != nil {
t.Fatal(err)
}
proxyHandler := newProxy(backendURL)
frontend := httptest.NewServer(proxyHandler)
defer frontend.Close()
// Don't spam output with logs of queries containing semicolons.
backend.Config.ErrorLog = log.New(io.Discard, "", 0)
frontend.Config.ErrorLog = log.New(io.Discard, "", 0)
for _, test := range []struct {
rawQuery string
cleanQuery string
}{{
rawQuery: "a=1&a=2;b=3",
cleanQuery: "a=1",
}, {
rawQuery: "a=1&a=%zz&b=3",
cleanQuery: "a=1&b=3",
}} {
res, err := frontend.Client().Get(frontend.URL + "?" + test.rawQuery)
if err != nil {
t.Fatalf("Get: %v", err)
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
wantQuery := test.rawQuery
if wantCleanQuery {
wantQuery = test.cleanQuery
}
if got, want := string(body), wantQuery; got != want {
t.Errorf("proxy forwarded raw query %q as %q, want %q", test.rawQuery, got, want)
}
}
}

View File

@@ -1191,17 +1191,23 @@ func (u *URL) UnmarshalBinary(text []byte) error {
// any existing path and the resulting path cleaned of any ./ or ../ elements.
// Any sequences of multiple / characters will be reduced to a single /.
func (u *URL) JoinPath(elem ...string) *URL {
url := *u
if len(elem) > 0 {
elem = append([]string{u.EscapedPath()}, elem...)
p := path.Join(elem...)
// path.Join will remove any trailing slashes.
// Preserve at least one.
if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
p += "/"
}
url.setPath(p)
elem = append([]string{u.EscapedPath()}, elem...)
var p string
if !strings.HasPrefix(elem[0], "/") {
// Return a relative path if u is relative,
// but ensure that it contains no ../ elements.
elem[0] = "/" + elem[0]
p = path.Join(elem...)[1:]
} else {
p = path.Join(elem...)
}
// path.Join will remove any trailing slashes.
// Preserve at least one.
if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
p += "/"
}
url := *u
url.setPath(p)
return &url
}

View File

@@ -2080,6 +2080,26 @@ func TestJoinPath(t *testing.T) {
elem: []string{"../../../go"},
out: "https://go.googlesource.com/go",
},
{
base: "https://go.googlesource.com/",
elem: []string{"../go"},
out: "https://go.googlesource.com/go",
},
{
base: "https://go.googlesource.com",
elem: []string{"../go"},
out: "https://go.googlesource.com/go",
},
{
base: "https://go.googlesource.com",
elem: []string{"../go", "../../go", "../../../go"},
out: "https://go.googlesource.com/go",
},
{
base: "https://go.googlesource.com/../go",
elem: nil,
out: "https://go.googlesource.com/go",
},
{
base: "https://go.googlesource.com/",
elem: []string{"./go"},
@@ -2112,7 +2132,7 @@ func TestJoinPath(t *testing.T) {
{
base: "https://go.googlesource.com",
elem: nil,
out: "https://go.googlesource.com",
out: "https://go.googlesource.com/",
},
{
base: "https://go.googlesource.com/",
@@ -2129,11 +2149,46 @@ func TestJoinPath(t *testing.T) {
elem: []string{"c%2fd"},
out: "https://go.googlesource.com/a%2fb/c%2fd",
},
{
base: "https://go.googlesource.com/a/b",
elem: []string{"/go"},
out: "https://go.googlesource.com/a/b/go",
},
{
base: "/",
elem: nil,
out: "/",
},
{
base: "a",
elem: nil,
out: "a",
},
{
base: "a",
elem: []string{"b"},
out: "a/b",
},
{
base: "a",
elem: []string{"../b"},
out: "b",
},
{
base: "a",
elem: []string{"../../b"},
out: "b",
},
{
base: "",
elem: []string{"a"},
out: "a",
},
{
base: "",
elem: []string{"../a"},
out: "a",
},
}
for _, tt := range tests {
wantErr := "nil"

View File

@@ -11,9 +11,10 @@ import (
func TestDedupEnv(t *testing.T) {
tests := []struct {
noCase bool
in []string
want []string
noCase bool
in []string
want []string
wantErr bool
}{
{
noCase: true,
@@ -41,11 +42,17 @@ func TestDedupEnv(t *testing.T) {
in: []string{"dodgy", "entries"},
want: []string{"dodgy", "entries"},
},
{
// Filter out entries containing NULs.
in: []string{"A=a\x00b", "B=b", "C\x00C=c"},
want: []string{"B=b"},
wantErr: true,
},
}
for _, tt := range tests {
got := dedupEnvCase(tt.noCase, tt.in)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Dedup(%v, %q) = %q; want %q", tt.noCase, tt.in, got, tt.want)
got, err := dedupEnvCase(tt.noCase, tt.in)
if !reflect.DeepEqual(got, tt.want) || (err != nil) != tt.wantErr {
t.Errorf("Dedup(%v, %q) = %q, %v; want %q, error:%v", tt.noCase, tt.in, got, err, tt.want, tt.wantErr)
}
}
}

View File

@@ -912,7 +912,11 @@ func (c *Cmd) environ() ([]string, error) {
}
}
return addCriticalEnv(dedupEnv(env)), err
env, dedupErr := dedupEnv(env)
if err == nil {
err = dedupErr
}
return addCriticalEnv(env), err
}
// Environ returns a copy of the environment in which the command would be run
@@ -926,20 +930,27 @@ func (c *Cmd) Environ() []string {
// dedupEnv returns a copy of env with any duplicates removed, in favor of
// later values.
// Items not of the normal environment "key=value" form are preserved unchanged.
func dedupEnv(env []string) []string {
// Items containing NUL characters are removed, and an error is returned along with
// the remaining values.
func dedupEnv(env []string) ([]string, error) {
return dedupEnvCase(runtime.GOOS == "windows", env)
}
// dedupEnvCase is dedupEnv with a case option for testing.
// If caseInsensitive is true, the case of keys is ignored.
func dedupEnvCase(caseInsensitive bool, env []string) []string {
func dedupEnvCase(caseInsensitive bool, env []string) ([]string, error) {
// Construct the output in reverse order, to preserve the
// last occurrence of each key.
var err error
out := make([]string, 0, len(env))
saw := make(map[string]bool, len(env))
for n := len(env); n > 0; n-- {
kv := env[n-1]
if strings.IndexByte(kv, 0) != -1 {
err = errors.New("exec: environment variable contains NUL")
continue
}
i := strings.Index(kv, "=")
if i == 0 {
// We observe in practice keys with a single leading "=" on Windows.
@@ -974,7 +985,7 @@ func dedupEnvCase(caseInsensitive bool, env []string) []string {
out[i], out[j] = out[j], out[i]
}
return out
return out, err
}
// addCriticalEnv adds any critical environment variables that are required

View File

@@ -1053,6 +1053,15 @@ func TestDedupEnvEcho(t *testing.T) {
}
}
func TestEnvNULCharacter(t *testing.T) {
cmd := helperCommand(t, "echoenv", "FOO", "BAR")
cmd.Env = append(cmd.Environ(), "FOO=foo\x00BAR=bar")
out, err := cmd.CombinedOutput()
if err == nil {
t.Errorf("output = %q; want error", string(out))
}
}
func TestString(t *testing.T) {
echoPath, err := exec.LookPath("echo")
if err != nil {

View File

@@ -91,15 +91,49 @@ const (
// until we've allocated at least maxHeight Regexp structures.
const maxHeight = 1000
// maxSize is the maximum size of a compiled regexp in Insts.
// It too is somewhat arbitrarily chosen, but the idea is to be large enough
// to allow significant regexps while at the same time small enough that
// the compiled form will not take up too much memory.
// 128 MB is enough for a 3.3 million Inst structures, which roughly
// corresponds to a 3.3 MB regexp.
const (
maxSize = 128 << 20 / instSize
instSize = 5 * 8 // byte, 2 uint32, slice is 5 64-bit words
)
// maxRunes is the maximum number of runes allowed in a regexp tree
// counting the runes in all the nodes.
// Ignoring character classes p.numRunes is always less than the length of the regexp.
// Character classes can make it much larger: each \pL adds 1292 runes.
// 128 MB is enough for 32M runes, which is over 26k \pL instances.
// Note that repetitions do not make copies of the rune slices,
// so \pL{1000} is only one rune slice, not 1000.
// We could keep a cache of character classes we've seen,
// so that all the \pL we see use the same rune list,
// but that doesn't remove the problem entirely:
// consider something like [\pL01234][\pL01235][\pL01236]...[\pL^&*()].
// And because the Rune slice is exposed directly in the Regexp,
// there is not an opportunity to change the representation to allow
// partial sharing between different character classes.
// So the limit is the best we can do.
const (
maxRunes = 128 << 20 / runeSize
runeSize = 4 // rune is int32
)
type parser struct {
flags Flags // parse mode flags
stack []*Regexp // stack of parsed expressions
free *Regexp
numCap int // number of capturing groups seen
wholeRegexp string
tmpClass []rune // temporary char class work space
numRegexp int // number of regexps allocated
height map[*Regexp]int // regexp height for height limit check
tmpClass []rune // temporary char class work space
numRegexp int // number of regexps allocated
numRunes int // number of runes in char classes
repeats int64 // product of all repetitions seen
height map[*Regexp]int // regexp height, for height limit check
size map[*Regexp]int64 // regexp compiled size, for size limit check
}
func (p *parser) newRegexp(op Op) *Regexp {
@@ -123,6 +157,104 @@ func (p *parser) reuse(re *Regexp) {
p.free = re
}
func (p *parser) checkLimits(re *Regexp) {
if p.numRunes > maxRunes {
panic(ErrInternalError)
}
p.checkSize(re)
p.checkHeight(re)
}
func (p *parser) checkSize(re *Regexp) {
if p.size == nil {
// We haven't started tracking size yet.
// Do a relatively cheap check to see if we need to start.
// Maintain the product of all the repeats we've seen
// and don't track if the total number of regexp nodes
// we've seen times the repeat product is in budget.
if p.repeats == 0 {
p.repeats = 1
}
if re.Op == OpRepeat {
n := re.Max
if n == -1 {
n = re.Min
}
if n <= 0 {
n = 1
}
if int64(n) > maxSize/p.repeats {
p.repeats = maxSize
} else {
p.repeats *= int64(n)
}
}
if int64(p.numRegexp) < maxSize/p.repeats {
return
}
// We need to start tracking size.
// Make the map and belatedly populate it
// with info about everything we've constructed so far.
p.size = make(map[*Regexp]int64)
for _, re := range p.stack {
p.checkSize(re)
}
}
if p.calcSize(re, true) > maxSize {
panic(ErrInternalError)
}
}
func (p *parser) calcSize(re *Regexp, force bool) int64 {
if !force {
if size, ok := p.size[re]; ok {
return size
}
}
var size int64
switch re.Op {
case OpLiteral:
size = int64(len(re.Rune))
case OpCapture, OpStar:
// star can be 1+ or 2+; assume 2 pessimistically
size = 2 + p.calcSize(re.Sub[0], false)
case OpPlus, OpQuest:
size = 1 + p.calcSize(re.Sub[0], false)
case OpConcat:
for _, sub := range re.Sub {
size += p.calcSize(sub, false)
}
case OpAlternate:
for _, sub := range re.Sub {
size += p.calcSize(sub, false)
}
if len(re.Sub) > 1 {
size += int64(len(re.Sub)) - 1
}
case OpRepeat:
sub := p.calcSize(re.Sub[0], false)
if re.Max == -1 {
if re.Min == 0 {
size = 2 + sub // x*
} else {
size = 1 + int64(re.Min)*sub // xxx+
}
break
}
// x{2,5} = xx(x(x(x)?)?)?
size = int64(re.Max)*sub + int64(re.Max-re.Min)
}
if size < 1 {
size = 1
}
p.size[re] = size
return size
}
func (p *parser) checkHeight(re *Regexp) {
if p.numRegexp < maxHeight {
return
@@ -159,6 +291,7 @@ func (p *parser) calcHeight(re *Regexp, force bool) int {
// push pushes the regexp re onto the parse stack and returns the regexp.
func (p *parser) push(re *Regexp) *Regexp {
p.numRunes += len(re.Rune)
if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] {
// Single rune.
if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) {
@@ -190,7 +323,7 @@ func (p *parser) push(re *Regexp) *Regexp {
}
p.stack = append(p.stack, re)
p.checkHeight(re)
p.checkLimits(re)
return re
}
@@ -300,7 +433,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (
re.Sub = re.Sub0[:1]
re.Sub[0] = sub
p.stack[n-1] = re
p.checkHeight(re)
p.checkLimits(re)
if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
@@ -508,6 +641,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp {
for j := start; j < i; j++ {
sub[j] = p.removeLeadingString(sub[j], len(str))
p.checkLimits(sub[j])
}
suffix := p.collapse(sub[start:i], OpAlternate) // recurse
@@ -565,6 +699,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp {
for j := start; j < i; j++ {
reuse := j != start // prefix came from sub[start]
sub[j] = p.removeLeadingRegexp(sub[j], reuse)
p.checkLimits(sub[j])
}
suffix := p.collapse(sub[start:i], OpAlternate) // recurse
@@ -762,6 +897,8 @@ func parse(s string, flags Flags) (_ *Regexp, err error) {
panic(r)
case nil:
// ok
case ErrInternalError: // too big
err = &Error{Code: ErrInternalError, Expr: s}
case ErrNestingDepth:
err = &Error{Code: ErrNestingDepth, Expr: s}
}

View File

@@ -484,12 +484,15 @@ var invalidRegexps = []string{
`(?P<>a)`,
`[a-Z]`,
`(?i)[a-Z]`,
`a{100000}`,
`a{100000,}`,
"((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
strings.Repeat("(", 1000) + strings.Repeat(")", 1000),
strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000),
`\Q\E*`,
`a{100000}`, // too much repetition
`a{100000,}`, // too much repetition
"((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", // too much repetition
strings.Repeat("(", 1000) + strings.Repeat(")", 1000), // too deep
strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000), // too deep
"(" + strings.Repeat("(xx?)", 1000) + "){1000}", // too long
strings.Repeat("(xx?){1000}", 1000), // too long
strings.Repeat(`\pL`, 27000), // too many runes
}
var onlyPerl = []string{

View File

@@ -387,6 +387,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
RET
TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
// Force SPWRITE. This function doesn't actually write SP,
// but it is called with a special calling convention where
// the caller doesn't save LR on stack but passes it as a
// register (R3), and the unwinder currently doesn't understand.
// Make it SPWRITE to stop unwinding. (See issue 54332)
MOVW R13, R13
MOVW $0, R7
B runtime·morestack(SB)

View File

@@ -320,6 +320,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
UNDEF
TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
// Force SPWRITE. This function doesn't actually write SP,
// but it is called with a special calling convention where
// the caller doesn't save LR on stack but passes it as a
// register (R3), and the unwinder currently doesn't understand.
// Make it SPWRITE to stop unwinding. (See issue 54332)
MOVD RSP, RSP
MOVW $0, R26
B runtime·morestack(SB)

View File

@@ -258,6 +258,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
UNDEF
TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
// Force SPWRITE. This function doesn't actually write SP,
// but it is called with a special calling convention where
// the caller doesn't save LR on stack but passes it as a
// register (R3), and the unwinder currently doesn't understand.
// Make it SPWRITE to stop unwinding. (See issue 54332)
MOVV R29, R29
MOVV R0, REGCTXT
JMP runtime·morestack(SB)

View File

@@ -257,6 +257,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
UNDEF
TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
// Force SPWRITE. This function doesn't actually write SP,
// but it is called with a special calling convention where
// the caller doesn't save LR on stack but passes it as a
// register (R3), and the unwinder currently doesn't understand.
// Make it SPWRITE to stop unwinding. (See issue 54332)
MOVW R29, R29
MOVW R0, REGCTXT
JMP runtime·morestack(SB)

View File

@@ -334,6 +334,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
UNDEF
TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
// Force SPWRITE. This function doesn't actually write SP,
// but it is called with a special calling convention where
// the caller doesn't save LR on stack but passes it as a
// register (R5), and the unwinder currently doesn't understand.
// Make it SPWRITE to stop unwinding. (See issue 54332)
MOVD R1, R1
MOVD R0, R11
BR runtime·morestack(SB)

View File

@@ -158,8 +158,8 @@ TEXT runtime·getcallerpc(SB),NOSPLIT|NOFRAME,$0-8
*/
// Called during function prolog when more stack is needed.
// Caller has already loaded:
// R1: framesize, R2: argsize, R3: LR
// Called with return address (i.e. caller's PC) in X5 (aka T0),
// and the LR register contains the caller's LR.
//
// The traceback routines see morestack on a g0 as being
// the top of a stack (for example, morestack calling newstack
@@ -209,6 +209,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
// func morestack_noctxt()
TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
// Force SPWRITE. This function doesn't actually write SP,
// but it is called with a special calling convention where
// the caller doesn't save LR on stack but passes it as a
// register, and the unwinder currently doesn't understand.
// Make it SPWRITE to stop unwinding. (See issue 54332)
MOV X2, X2
MOV ZERO, CTXT
JMP runtime·morestack(SB)

View File

@@ -346,6 +346,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
UNDEF
TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
// Force SPWRITE. This function doesn't actually write SP,
// but it is called with a special calling convention where
// the caller doesn't save LR on stack but passes it as a
// register (R5), and the unwinder currently doesn't understand.
// Make it SPWRITE to stop unwinding. (See issue 54332)
MOVD R15, R15
MOVD $0, R12
BR runtime·morestack(SB)

View File

@@ -23,7 +23,9 @@ package cgo
#cgo solaris LDFLAGS: -lxnet
#cgo solaris LDFLAGS: -lsocket
#cgo CFLAGS: -Wall -Werror
// We use -fno-stack-protector because internal linking won't find
// the support functions. See issues #52919 and #54313.
#cgo CFLAGS: -Wall -Werror -fno-stack-protector
#cgo solaris CPPFLAGS: -D_POSIX_PTHREAD_SEMANTICS

View File

@@ -20,49 +20,49 @@ const retSledSize = 512
// This may result in these functions having callers that are nosplit. That is why they must be nosplit.
//
//go:nosplit
func libfuzzerTraceCmp1(arg0, arg1 uint8, fakePC int) {
func libfuzzerTraceCmp1(arg0, arg1 uint8, fakePC uint) {
fakePC = fakePC % retSledSize
libfuzzerCallTraceIntCmp(&__sanitizer_cov_trace_cmp1, uintptr(arg0), uintptr(arg1), uintptr(fakePC))
}
//go:nosplit
func libfuzzerTraceCmp2(arg0, arg1 uint16, fakePC int) {
func libfuzzerTraceCmp2(arg0, arg1 uint16, fakePC uint) {
fakePC = fakePC % retSledSize
libfuzzerCallTraceIntCmp(&__sanitizer_cov_trace_cmp2, uintptr(arg0), uintptr(arg1), uintptr(fakePC))
}
//go:nosplit
func libfuzzerTraceCmp4(arg0, arg1 uint32, fakePC int) {
func libfuzzerTraceCmp4(arg0, arg1 uint32, fakePC uint) {
fakePC = fakePC % retSledSize
libfuzzerCallTraceIntCmp(&__sanitizer_cov_trace_cmp4, uintptr(arg0), uintptr(arg1), uintptr(fakePC))
}
//go:nosplit
func libfuzzerTraceCmp8(arg0, arg1 uint64, fakePC int) {
func libfuzzerTraceCmp8(arg0, arg1 uint64, fakePC uint) {
fakePC = fakePC % retSledSize
libfuzzerCallTraceIntCmp(&__sanitizer_cov_trace_cmp8, uintptr(arg0), uintptr(arg1), uintptr(fakePC))
}
//go:nosplit
func libfuzzerTraceConstCmp1(arg0, arg1 uint8, fakePC int) {
func libfuzzerTraceConstCmp1(arg0, arg1 uint8, fakePC uint) {
fakePC = fakePC % retSledSize
libfuzzerCallTraceIntCmp(&__sanitizer_cov_trace_const_cmp1, uintptr(arg0), uintptr(arg1), uintptr(fakePC))
}
//go:nosplit
func libfuzzerTraceConstCmp2(arg0, arg1 uint16, fakePC int) {
func libfuzzerTraceConstCmp2(arg0, arg1 uint16, fakePC uint) {
fakePC = fakePC % retSledSize
libfuzzerCallTraceIntCmp(&__sanitizer_cov_trace_const_cmp2, uintptr(arg0), uintptr(arg1), uintptr(fakePC))
}
//go:nosplit
func libfuzzerTraceConstCmp4(arg0, arg1 uint32, fakePC int) {
func libfuzzerTraceConstCmp4(arg0, arg1 uint32, fakePC uint) {
fakePC = fakePC % retSledSize
libfuzzerCallTraceIntCmp(&__sanitizer_cov_trace_const_cmp4, uintptr(arg0), uintptr(arg1), uintptr(fakePC))
}
//go:nosplit
func libfuzzerTraceConstCmp8(arg0, arg1 uint64, fakePC int) {
func libfuzzerTraceConstCmp8(arg0, arg1 uint64, fakePC uint) {
fakePC = fakePC % retSledSize
libfuzzerCallTraceIntCmp(&__sanitizer_cov_trace_const_cmp8, uintptr(arg0), uintptr(arg1), uintptr(fakePC))
}

View File

@@ -7,6 +7,7 @@ package runtime
import (
"internal/abi"
"internal/goarch"
"runtime/internal/atomic"
"unsafe"
)
@@ -182,7 +183,7 @@ func newosproc(mp *m) {
}
}
func exitThread(wait *uint32) {
func exitThread(wait *atomic.Uint32) {
// We should never reach exitThread on Solaris because we let
// libc clean up threads.
throw("exitThread")

View File

@@ -8,6 +8,7 @@ package runtime
import (
"internal/abi"
"runtime/internal/atomic"
"unsafe"
)
@@ -233,7 +234,7 @@ func newosproc(mp *m) {
}
func exitThread(wait *uint32) {
func exitThread(wait *atomic.Uint32) {
// We should never reach exitThread on AIX because we let
// libc clean up threads.
throw("exitThread")

View File

@@ -7,6 +7,7 @@
package runtime
import (
"runtime/internal/atomic"
"unsafe"
)
@@ -35,7 +36,7 @@ func usleep_no_g(usec uint32) {
usleep(usec)
}
func exitThread(wait *uint32)
func exitThread(wait *atomic.Uint32)
type mOS struct{}

View File

@@ -7,6 +7,7 @@
package runtime
import (
"runtime/internal/atomic"
"unsafe"
)
@@ -49,11 +50,11 @@ func open(name *byte, mode, perm int32) int32
// return value is only set on linux to be used in osinit()
func madvise(addr unsafe.Pointer, n uintptr, flags int32) int32
// exitThread terminates the current thread, writing *wait = 0 when
// exitThread terminates the current thread, writing *wait = freeMStack when
// the stack is safe to reclaim.
//
//go:noescape
func exitThread(wait *uint32)
func exitThread(wait *atomic.Uint32)
//go:noescape
func obsdsigprocmask(how int32, new sigset) sigset

View File

@@ -461,7 +461,7 @@ func newosproc(mp *m) {
}
}
func exitThread(wait *uint32) {
func exitThread(wait *atomic.Uint32) {
// We should never reach exitThread on Plan 9 because we let
// the OS clean up threads.
throw("exitThread")

View File

@@ -941,7 +941,7 @@ func newosproc0(mp *m, stk unsafe.Pointer) {
throw("bad newosproc0")
}
func exitThread(wait *uint32) {
func exitThread(wait *atomic.Uint32) {
// We should never reach exitThread on Windows because we let
// the OS clean up threads.
throw("exitThread")

View File

@@ -1516,19 +1516,18 @@ func mexit(osStack bool) {
}
throw("m not found in allm")
found:
if !osStack {
// Delay reaping m until it's done with the stack.
//
// If this is using an OS stack, the OS will free it
// so there's no need for reaping.
atomic.Store(&m.freeWait, 1)
// Put m on the free list, though it will not be reaped until
// freeWait is 0. Note that the free list must not be linked
// through alllink because some functions walk allm without
// locking, so may be using alllink.
m.freelink = sched.freem
sched.freem = m
}
// Delay reaping m until it's done with the stack.
//
// Put mp on the free list, though it will not be reaped while freeWait
// is freeMWait. mp is no longer reachable via allm, so even if it is
// on an OS stack, we must keep a reference to mp alive so that the GC
// doesn't free mp while we are still using it.
//
// Note that the free list must not be linked through alllink because
// some functions walk allm without locking, so may be using alllink.
m.freeWait.Store(freeMWait)
m.freelink = sched.freem
sched.freem = m
unlock(&sched.lock)
atomic.Xadd64(&ncgocall, int64(m.ncgocall))
@@ -1558,6 +1557,9 @@ found:
mdestroy(m)
if osStack {
// No more uses of mp, so it is safe to drop the reference.
m.freeWait.Store(freeMRef)
// Return from mstart and let the system thread
// library free the g0 stack and terminate the thread.
return
@@ -1729,19 +1731,25 @@ func allocm(_p_ *p, fn func(), id int64) *m {
lock(&sched.lock)
var newList *m
for freem := sched.freem; freem != nil; {
if freem.freeWait != 0 {
wait := freem.freeWait.Load()
if wait == freeMWait {
next := freem.freelink
freem.freelink = newList
newList = freem
freem = next
continue
}
// stackfree must be on the system stack, but allocm is
// reachable off the system stack transitively from
// startm.
systemstack(func() {
stackfree(freem.g0.stack)
})
// Free the stack if needed. For freeMRef, there is
// nothing to do except drop freem from the sched.freem
// list.
if wait == freeMStack {
// stackfree must be on the system stack, but allocm is
// reachable off the system stack transitively from
// startm.
systemstack(func() {
stackfree(freem.g0.stack)
})
}
freem = freem.freelink
}
sched.freem = newList

View File

@@ -22,6 +22,7 @@ TEXT _main<>(SB),NOSPLIT,$-8
// There is no TLS base pointer.
//
// TODO(austin): Support ABI v1 dynamic linking entry point
XOR R0, R0 // Note, newer kernels may not always set R0 to 0.
MOVD $runtime·rt0_go(SB), R12
MOVD R12, CTR
MOVBZ runtime·iscgo(SB), R5

View File

@@ -516,6 +516,13 @@ const (
tlsSize = tlsSlots * goarch.PtrSize
)
// Values for m.freeWait.
const (
freeMStack = 0 // M done, free stack and reference.
freeMRef = 1 // M done, free reference.
freeMWait = 2 // M still in use.
)
type m struct {
g0 *g // goroutine with scheduling stack
morebuf gobuf // gobuf arg to morestack
@@ -546,7 +553,7 @@ type m struct {
newSigstack bool // minit on C thread called sigaltstack
printlock int8
incgo bool // m is executing a cgo call
freeWait uint32 // if == 0, safe to free g0 and delete m (atomic)
freeWait atomic.Uint32 // Whether it is safe to free g0 and delete m (one of freeMRef, freeMStack, freeMWait)
fastrand uint64
needextram bool
traceback uint8

View File

@@ -84,6 +84,10 @@ func (c *sigctxt) fixsigcode(sig uint32) {
// in real life, people will probably search for it and find this code.
// There are no Google hits for b01dfacedebac1e or 0xb01dfacedebac1e
// as I type this comment.
//
// Note: if this code is removed, please consider
// enabling TestSignalForwardingGo for darwin-amd64 in
// misc/cgo/testcarchive/carchive_test.go.
if c.sigcode() == _SI_USER {
c.set_sigcode(_SI_USER + 1)
c.set_sigaddr(0xb01dfacedebac1e)

View File

@@ -6,7 +6,10 @@
package runtime
import "unsafe"
import (
"runtime/internal/atomic"
"unsafe"
)
// read calls the read system call.
// It returns a non-negative number of bytes written or a negative errno value.
@@ -34,8 +37,8 @@ func open(name *byte, mode, perm int32) int32
// return value is only set on linux to be used in osinit()
func madvise(addr unsafe.Pointer, n uintptr, flags int32) int32
// exitThread terminates the current thread, writing *wait = 0 when
// exitThread terminates the current thread, writing *wait = freeMStack when
// the stack is safe to reclaim.
//
//go:noescape
func exitThread(wait *uint32)
func exitThread(wait *atomic.Uint32)

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