Compare commits

...

56 Commits

Author SHA1 Message Date
Chris Broadfoot
753452fac6 [release-branch.go1.7] go1.7.5
Change-Id: I09b5f6f3c79ec691f6d2fd28551dc06d79105c42
Reviewed-on: https://go-review.googlesource.com/35834
Run-TryBot: Chris Broadfoot <cbro@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2017-01-26 17:38:29 +00:00
Chris Broadfoot
6ceba5d5e8 [release-branch.go1.7] doc: document go1.7.5
Change-Id: Ic8d4e971edebba9412f2e7c3d3c29f296c4977ff
Reviewed-on: https://go-review.googlesource.com/35833
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/35835
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2017-01-26 17:36:58 +00:00
Brad Fitzpatrick
5c2b5ee3c8 [release-branch.go1.7] crypto/x509: speed up and deflake non-cgo Darwin root cert discovery
Backporting Go 1.8's fix to #18203
Fixes #18688

---

Piping into security verify-cert only worked on macOS Sierra, and was
flaky for unknown reasons. Users reported that the number of trusted
root certs stopped randomly jumping around once they switched to using
verify-cert against files on disk instead of /dev/stdin.

But even using "security verify-cert" on 150-200 certs took too
long. It took 3.5 seconds on my machine. More than 4 goroutines
hitting verify-cert didn't help much, and soon started to hurt
instead.

New strategy, from comments in the code:

// 1. Run "security trust-settings-export" and "security
//    trust-settings-export -d" to discover the set of certs with some
//    user-tweaked trusy policy. We're too lazy to parse the XML (at
//    least at this stage of Go 1.8) to understand what the trust
//    policy actually is. We just learn that there is _some_ policy.
//
// 2. Run "security find-certificate" to dump the list of system root
//    CAs in PEM format.
//
// 3. For each dumped cert, conditionally verify it with "security
//    verify-cert" if that cert was in the set discovered in Step 1.
//    Without the Step 1 optimization, running "security verify-cert"
//    150-200 times takes 3.5 seconds. With the optimization, the
//    whole process takes about 180 milliseconds with 1 untrusted root
//    CA. (Compared to 110ms in the cgo path)

Change-Id: I79737d9f2cb9b020ba297a326d4d31d68c7e9fee
Reviewed-on: https://go-review.googlesource.com/35634
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2017-01-25 17:21:33 +00:00
Austin Clements
efdb1813a0 [release-branch.go1.7] runtime: fix getArgInfo for deferred reflection calls
Fixes #18333 (backport)

getArgInfo for reflect.makeFuncStub and reflect.methodValueCall is
necessarily special. These have dynamically determined argument maps
that are stored in their context (that is, their *funcval). These
functions are written to store this context at 0(SP) when called, and
getArgInfo retrieves it from there.

This technique works if getArgInfo is passed an active call frame for
one of these functions. However, getArgInfo is also used in
tracebackdefers, where the "call" is not a true call with an active
stack frame, but a deferred call. In this situation, getArgInfo
currently crashes because tracebackdefers passes a frame with sp set
to 0. However, the entire approach used by getArgInfo is flawed in
this situation because the wrapper has not actually executed, and
hence hasn't saved this metadata to any stack frame.

In the defer case, we know the *funcval from the _defer itself, so we
can fix this by teaching getArgInfo to use the *funcval context
directly when its available, and otherwise get it from the active call
frame.

While we're here, this commit simplifies getArgInfo a bit by making it
play more nicely with the type system. Rather than decoding the
*reflect.methodValue that is the wrapper's context as a *[2]uintptr,
just write out a copy of the reflect.methodValue type in the runtime.

Fixes #16331. Fixes #17471.

Change-Id: I81db4d985179b4a81c68c490cceeccbfc675456a
Reviewed-on: https://go-review.googlesource.com/31138
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/35638
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-01-25 17:18:12 +00:00
Austin Clements
c4552c1c61 [release-branch.go1.7] runtime: force workers out before checking mark roots
Fixes #18700 (backport)

Currently we check that all roots are marked as soon as gcMarkDone
decides to transition from mark 1 to mark 2. However, issue #16083
indicates that there may be a race where we try to complete mark 1
while a worker is still scanning a stack, causing the root mark check
to fail.

We don't yet understand this race, but as a simple mitigation, move
the root check to after gcMarkDone performs a ragged barrier, which
will force any remaining workers to finish their current job.

Updates #16083. This may "fix" it, but it would be better to
understand and fix the underlying race.

Change-Id: I1af9ce67bd87ade7bc2a067295d79c28cd11abd2
Reviewed-on: https://go-review.googlesource.com/35678
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2017-01-25 17:18:04 +00:00
Russ Cox
faafe0e30c [release-branch.go1.7] runtime: fix corruption crash/race between select and stack growth
Fixes #18708 (backport)

To implement the blocking of a select, a goroutine builds a list of
offers to communicate (pseudo-g's, aka sudog), one for each case,
queues them on the corresponding channels, and waits for another
goroutine to complete one of those cases and wake it up. Obviously it
is not OK for two other goroutines to complete multiple cases and both
wake the goroutine blocked in select. To make sure that only one
branch of the select is chosen, all the sudogs contain a pointer to a
shared (single) 'done uint32', which is atomically cas'ed by any
interested goroutines. The goroutine that wins the cas race gets to
wake up the select. A complication is that 'done uint32' is stored on
the stack of the goroutine running the select, and that stack can move
during the select due to stack growth or stack shrinking.

The relevant ordering to block and unblock in select is:

	1. Lock all channels.
	2. Create list of sudogs and queue sudogs on all channels.
	3. Switch to system stack, mark goroutine as asleep,
	   unlock all channels.
	4. Sleep until woken.
	5. Wake up on goroutine stack.
	6. Lock all channels.
	7. Dequeue sudogs from all channels.
	8. Free list of sudogs.
	9. Unlock all channels.

There are two kinds of stack moves: stack growth and stack shrinking.
Stack growth happens while the original goroutine is running.
Stack shrinking happens asynchronously, during garbage collection.

While a channel listing a sudog is locked by select in this process,
no other goroutine can attempt to complete communication on that
channel, because that other goroutine doesn't hold the lock and can't
find the sudog. If the stack moves while all the channel locks are
held or when the sudogs are not yet or no longer queued in the
channels, no problem, because no goroutine can get to the sudogs and
therefore to selectdone. We only need to worry about the stack (and
'done uint32') moving with the sudogs queued in unlocked channels.

Stack shrinking can happen any time the goroutine is stopped.
That code already acquires all the channel locks before doing the
stack move, so it avoids this problem.

Stack growth can happen essentially any time the original goroutine is
running on its own stack (not the system stack). In the first half of
the select, all the channels are locked before any sudogs are queued,
and the channels are not unlocked until the goroutine has stopped
executing on its own stack and is asleep, so that part is OK. In the
second half of the select, the goroutine wakes up on its own goroutine
stack and immediately locks all channels. But the actual call to lock
might grow the stack, before acquiring any locks. In that case, the
stack is moving with the sudogs queued in unlocked channels. Not good.
One goroutine has already won a cas on the old stack (that goroutine
woke up the selecting goroutine, moving it out of step 4), and the
fact that done = 1 now should prevent any other goroutines from
completing any other select cases. During the stack move, however,
sudog.selectdone is moved from pointing to the old done variable on
the old stack to a new memory location on the new stack. Another
goroutine might observe the moved pointer before the new memory
location has been initialized. If the new memory word happens to be
zero, that goroutine might win a cas on the new location, thinking it
can now complete the select (again). It will then complete a second
communication (reading from or writing to the goroutine stack
incorrectly) and then attempt to wake up the selecting goroutine,
which is already awake.

The scribbling over the goroutine stack unexpectedly is already bad,
but likely to go unnoticed, at least immediately. As for the second
wakeup, there are a variety of ways it might play out.

* The goroutine might not be asleep.
That will produce a runtime crash (throw) like in #17007:

	runtime: gp: gp=0xc0422dcb60, goid=2299, gp->atomicstatus=8
	runtime:  g:  g=0xa5cfe0, goid=0,  g->atomicstatus=0
	fatal error: bad g->status in ready

Here, atomicstatus=8 is copystack; the second, incorrect wakeup is
observing that the selecting goroutine is in state "Gcopystack"
instead of "Gwaiting".

* The goroutine might be sleeping in a send on a nil chan.
If it wakes up, it will crash with 'fatal error: unreachable'.

* The goroutine might be sleeping in a send on a non-nil chan.
If it wakes up, it will crash with 'fatal error: chansend:
spurious wakeup'.

* The goroutine might be sleeping in a receive on a nil chan.
If it wakes up, it will crash with 'fatal error: unreachable'.

* The goroutine might be sleeping in a receive on a non-nil chan.
If it wakes up, it will silently (incorrectly!) continue as if it
received a zero value from a closed channel, leaving a sudog queued on
the channel pointing at that zero vaue on the goroutine's stack; that
space will be reused as the goroutine executes, and when some other
goroutine finally completes the receive, it will do a stray write into
the goroutine's stack memory, which may cause problems. Then it will
attempt the real wakeup of the goroutine, leading recursively to any
of the cases in this list.

* The goroutine might have been running a select in a finalizer
(I hope not!) and might now be sleeping waiting for more things to
finalize. If it wakes up, as long as it goes back to sleep quickly
(before the real GC code tries to wake it), the spurious wakeup does
no harm (but the stack was still scribbled on).

* The goroutine might be sleeping in gcParkAssist.
If it wakes up, that will let the goroutine continue executing a bit
earlier than we would have liked. Eventually the GC will attempt the
real wakeup of the goroutine, leading recursively to any of the cases
in this list.

* The goroutine cannot be sleeping in bgsweep, because the background
sweepers never use select.

* The goroutine might be sleeping in netpollblock.
If it wakes up, it will crash with 'fatal error: netpollblock:
corrupted state'.

* The goroutine might be sleeping in main as another thread crashes.
If it wakes up, it will exit(0) instead of letting the other thread
crash with a non-zero exit status.

* The goroutine cannot be sleeping in forcegchelper,
because forcegchelper never uses select.

* The goroutine might be sleeping in an empty select - select {}.
If it wakes up, it will return to the next line in the program!

* The goroutine might be sleeping in a non-empty select (again).
In this case, it will wake up spuriously, with gp.param == nil (no
reason for wakeup), but that was fortuitously overloaded for handling
wakeup due to a closing channel and the way it is handled is to rerun
the select, which (accidentally) handles the spurious wakeup
correctly:

	if cas == nil {
		// This can happen if we were woken up by a close().
		// TODO: figure that out explicitly so we don't need this loop.
		goto loop
	}

Before looping, it will dequeue all the sudogs on all the channels
involved, so that no other goroutine will attempt to wake it.
Since the goroutine was blocked in select before, being blocked in
select again when the spurious wakeup arrives may be quite likely.
In this case, the spurious wakeup does no harm (but the stack was
still scribbled on).

* The goroutine might be sleeping in semacquire (mutex slow path).
If it wakes up, that is taken as a signal to try for the semaphore
again, not a signal that the semaphore is now held, but the next
iteration around the loop will queue the sudog a second time, causing
a cycle in the wakeup list for the given address. If that sudog is the
only one in the list, when it is eventually dequeued, it will
(due to the precise way the code is written) leave the sudog on the
queue inactive with the sudog broken. But the sudog will also be in
the free list, and that will eventually cause confusion.

* The goroutine might be sleeping in notifyListWait, for sync.Cond.
If it wakes up, (*Cond).Wait returns. The docs say "Unlike in other
systems, Wait cannot return unless awoken by Broadcast or Signal,"
so the spurious wakeup is incorrect behavior, but most callers do not
depend on that fact. Eventually the condition will happen, attempting
the real wakeup of the goroutine and leading recursively to any of the
cases in this list.

* The goroutine might be sleeping in timeSleep aka time.Sleep.
If it wakes up, it will continue running, leaving a timer ticking.
When that time bomb goes off, it will try to ready the goroutine
again, leading to any one of the cases in this list.

* The goroutine cannot be sleeping in timerproc,
because timerproc never uses select.

* The goroutine might be sleeping in ReadTrace.
If it wakes up, it will print 'runtime: spurious wakeup of trace
reader' and return nil. All future calls to ReadTrace will print
'runtime: ReadTrace called from multiple goroutines simultaneously'.
Eventually, when trace data is available, a true wakeup will be
attempted, leading to any one of the cases in this list.

None of these fatal errors appear in any of the trybot or dashboard
logs. The 'bad g->status in ready' that happens if the goroutine is
running (the most likely scenario anyway) has happened once on the
dashboard and eight times in trybot logs. Of the eight, five were
atomicstatus=8 during net/http tests, so almost certainly this bug.
The other three were atomicstatus=2, all near code in select,
but in a draft CL by Dmitry that was rewriting select and may or may
not have had its own bugs.

This bug has existed since Go 1.4. Until then the select code was
implemented in C, 'done uint32' was a C stack variable 'uint32 done',
and C stacks never moved. I believe it has become more common recently
because of Brad's work to run more and more tests in net/http in
parallel, which lengthens race windows.

The fix is to run step 6 on the system stack,
avoiding possibility of stack growth.

Fixes #17007 and possibly other mysterious failures.

Change-Id: I9d6575a51ac96ae9d67ec24da670426a4a45a317
Reviewed-on: https://go-review.googlesource.com/34835
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-on: https://go-review.googlesource.com/35637
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-01-25 17:17:42 +00:00
David Chase
93468efeb7 [release-branch.go1.7] cmd/compile: rewrite literal.method to ensure full initialization
CALLPART of STRUCTLIT did not check for incomplete initialization
of struct; modify PTRLIT treatment to force zeroing.

Test for structlit, believe this might have also failed for
arraylit.

Fixes #18410.

Change-Id: I511abf8ef850e300996d40568944665714efe1fc
Reviewed-on: https://go-review.googlesource.com/34622
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/35636
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
2017-01-25 17:17:21 +00:00
Alberto Donizetti
f5dd484480 [release-branch.go1.7] time: update test for tzdata-2016g
Backport of the fix to #17276 for Go 1.7.

Change-Id: Ifc1a8e2a81d4e543dbef04566985618884a8c0e0
Reviewed-on: https://go-review.googlesource.com/35635
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Reviewed-by: Alberto Donizetti <alb.donizetti@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-01-25 17:17:16 +00:00
Austin Clements
70e980631c [release-branch.go1.7] runtime: improve diagnostics for "scan missed a g"
Updates #18700 (backport)

Currently there are no diagnostics for mark root check during marking.
Fix this by printing out the same diagnostics we print during mark
termination.

Also, drop the allglock before throwing. Holding that across a throw
causes a self-deadlock with tracebackothers.

For #16083.

Change-Id: Ib605f3ae0c17e70704b31d8378274cfaa2307dc2
Reviewed-on: https://go-review.googlesource.com/35677
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2017-01-25 17:16:44 +00:00
Brad Fitzpatrick
230a376b5a [release-branch.go1.7] doc: remove Reddit as an official space where Code of Conduct applies
Fixes #18289

Change-Id: I047e98cc36b861ef15292170aeaff8bc29243cab
Reviewed-on: https://go-review.googlesource.com/34281
Reviewed-by: Russ Cox <rsc@golang.org>
(cherry picked from commit 265e547658)
Reviewed-on: https://go-review.googlesource.com/34282
2016-12-12 19:57:48 +00:00
Chris Broadfoot
6b36535cf3 [release-branch.go1.7] go1.7.4
Change-Id: I76d2c823eb98c16bb923caad2d0b0e0809a5ee37
Reviewed-on: https://go-review.googlesource.com/33798
Run-TryBot: Chris Broadfoot <cbro@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-12-01 22:13:49 +00:00
Chris Broadfoot
0ad8bf4122 [release-branch.go1.7] doc: document go1.7.4 and go1.6.4
Change-Id: I0728afe6a1d1e0aee4701e51a5548fa9fd637b66
Reviewed-on: https://go-review.googlesource.com/33795
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/33796
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-12-01 20:45:54 +00:00
Quentin Smith
26741a15f7 [release-branch.go1.7] crypto/x509: read Darwin trust settings for root CAs
Darwin separately stores bits indicating whether a root certificate
should be trusted; this changes Go to read and use those when
initializing SystemCertPool.

Unfortunately, the trust API is very slow. To avoid a delay of up to
0.5s in initializing the system cert pool, we assume that
the trust settings found in kSecTrustSettingsDomainSystem will always
indicate trust. (That is, all root certs Apple distributes are trusted.)
This is not guaranteed by the API but is true in practice.

In the non-cgo codepath, we do not have that benefit, so we must check
the trust status of every certificate. This causes about 0.5s of delay
in initializing the SystemCertPool.

On OS X 10.11 and older, the "security" command requires a certificate
to be provided in a file and not on stdin, so the non-cgo codepath
creates temporary files for each certificate, further slowing initialization.

Updates #18141.

Change-Id: If681c514047afe5e1a68de6c9d40ceabbce54755
Reviewed-on: https://go-review.googlesource.com/33721
Run-TryBot: Quentin Smith <quentin@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-on: https://go-review.googlesource.com/33727
2016-12-01 20:25:14 +00:00
Michael Fraenkel
fab76f07f5 [release-branch.go1.7] net/http: multipart ReadForm close file after copy
Always close the file regardless of whether the copy succeeds or fails.
Pass along the close error if the copy succeeds

Updates #16296
Fixes #17965

Change-Id: Ib394655b91d25750f029f17b3846d985f673fb50
Reviewed-on: https://go-review.googlesource.com/30410
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/33639
Reviewed-by: Chris Broadfoot <cbro@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-12-01 19:33:25 +00:00
Brad Fitzpatrick
4f7363cd72 [release-branch.go1.7] doc: reference go1.4-bootstrap-20161024.tar.gz
Updates #16352

Change-Id: I214c87579ef21ced8d0ba94aa170dd7780afec4b
Reviewed-on: https://go-review.googlesource.com/32312
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-on: https://go-review.googlesource.com/32914
2016-11-08 18:24:20 +00:00
Shenghou Ma
6759eff8eb [release-branch.go1.7] doc/devel/release.html: document go1.6.3 doesn't actually support macOS Sierra
Updates #17824.

Change-Id: I73cf89c21b418158c7014c3271cd1103a17a5c86
Reviewed-on: https://go-review.googlesource.com/32882
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/32885
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Minux Ma <minux@golang.org>
2016-11-08 16:11:19 +00:00
Brad Fitzpatrick
75f4f703eb [release-branch.go1.7] doc: remove mention of Go 1.6.3 working on Sierra
We thought it would at the time, but then Beta 4 changed the ABI
again, so it wasn't true in practice.

Fixes #17643

Change-Id: I36b747bd69a56adc7291fa30d6bffdf67ab8741b
Reviewed-on: https://go-review.googlesource.com/32238
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-on: https://go-review.googlesource.com/32270
2016-10-28 15:20:28 +00:00
Chris Broadfoot
2f6557233c [release-branch.go1.7] go1.7.3
Change-Id: I906070c84c0f40c4dd8af8b5894895127834ee00
Reviewed-on: https://go-review.googlesource.com/31438
Run-TryBot: Chris Broadfoot <cbro@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-10-19 17:04:39 +00:00
Chris Broadfoot
4de7b10483 [release-branch.go1.7] doc: document go1.7.3 and add note to go1.7.2 that it should not be used
Change-Id: I3dd1513e927733ce5c63928da772cb81760ba869
Reviewed-on: https://go-review.googlesource.com/31442
Reviewed-by: Andrew Gerrand <adg@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-10-19 17:04:17 +00:00
Chris Broadfoot
3b6f4b04ba [release-branch.go1.7] net/http: update bundled http2
Updates bundled http2 for x/net/http2 git rev d4c55e66 for:

[release-branch.go1.7] http2: never Read from Request.Body in Transport
to determine ContentLength
https://golang.org/cl/31361

Updates #17480
Updates #17071

Change-Id: I2231adaed3cb5b368927a9654dcf7e69a8b664b6
Reviewed-on: https://go-review.googlesource.com/31432
Run-TryBot: Chris Broadfoot <cbro@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-10-19 00:01:52 +00:00
Brad Fitzpatrick
740dfbadbd [release-branch.go1.7] net/http: update test to check Content-Length 0 Body more reliably
The way to send an explicitly-zero Content-Length is to set a nil Body.

Fix this test to do that, rather than relying on type sniffing.

Updates #17480
Updates #17071

Change-Id: I6a38e20f17013c88ec4ea69d73c507e4ed886947
Reviewed-on: https://go-review.googlesource.com/31434
TryBot-Result: Gobot Gobot <gobot@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Chris Broadfoot <cbro@golang.org>
Reviewed-on: https://go-review.googlesource.com/31437
Run-TryBot: Chris Broadfoot <cbro@golang.org>
2016-10-18 23:50:01 +00:00
Chris Broadfoot
edecc650ec [release-branch.go1.7] go1.7.2
Change-Id: I546e8b1aa4facdbf13bb80d386bf4839a3aff9d1
Reviewed-on: https://go-review.googlesource.com/31314
Run-TryBot: Chris Broadfoot <cbro@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-10-17 21:08:12 +00:00
Chris Broadfoot
2e150a0aa7 [release-branch.go1.7] doc: document go1.7.2
Change-Id: I34b3650ee9512879ff7528336813a7850c46ea90
Reviewed-on: https://go-review.googlesource.com/31311
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/31313
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-10-17 20:41:45 +00:00
Michael Munday
f0377a2851 [release-branch.go1.7] crypto/{aes,cipher}: fix panic in CBC on s390x when src length is 0
Adds a test to check that block cipher modes accept a zero-length
input.

Fixes #17435.

Change-Id: Ie093c4cdff756b5c2dcb79342e167b3de5622389
Reviewed-on: https://go-review.googlesource.com/31070
Run-TryBot: Michael Munday <munday@ca.ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/31291
Reviewed-by: Michael Munday <munday@ca.ibm.com>
Run-TryBot: Chris Broadfoot <cbro@golang.org>
2016-10-17 20:25:13 +00:00
David Chase
2287d95e9b [release-branch.go1.7] cmd/compile: escape analysis needs to run "flood" to fixed point
In some cases the members of the root set from which flood
runs themselves escape, without their referents being also
tagged as escaping.  Fix this by reflooding from those roots
whose escape increases, and also enhance the "leak" test to
include reachability from a heap-escaped root.

Fixes #17318.

Change-Id: Ied1e75cee17ede8ca72a8b9302ce8201641ec593
Reviewed-on: https://go-review.googlesource.com/30693
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-on: https://go-review.googlesource.com/31290
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2016-10-17 20:25:07 +00:00
Mike Appleby
a2f37b7fe1 [release-branch.go1.7] runtime: sleep on CLOCK_MONOTONIC in futexsleep1 on freebsd
In FreeBSD 10.0, the _umtx_op syscall was changed to allow sleeping on
any supported clock, but the default clock was switched from a monotonic
clock to CLOCK_REALTIME.

Prior to 10.0, the __umtx_op_wait* functions ignored the fourth argument
to _umtx_op (uaddr1), expected the fifth argument (uaddr2) to be a
struct timespec pointer, and used a monotonic clock (nanouptime(9)) for
timeout calculations.

Since 10.0, if callers want a clock other than CLOCK_REALTIME, they must
call _umtx_op with uaddr1 set to a value greater than sizeof(struct
timespec), and with uaddr2 as pointer to a struct _umtx_time, rather
than a timespec. Callers can set the _clockid field of the struct
_umtx_time to request the clock they want.

The relevant FreeBSD commit:
    https://svnweb.freebsd.org/base?view=revision&revision=232144

Fixes #17168

Change-Id: I3dd7b32b683622b8d7b4a6a8f9eb56401bed6bdf
Reviewed-on: https://go-review.googlesource.com/30154
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/31269
2016-10-17 20:25:00 +00:00
Adam Langley
ca0b97e80a [release-branch.go1.7] crypto/tls: fix deadlock when racing to complete handshake.
After renegotiation support was added (af125a5193) it's possible for a
Write to block on a Read when racing to complete the handshake:
   1. The Write determines that a handshake is needed and tries to
      take the neccesary locks in the correct order.
   2. The Read also determines that a handshake is needed and wins
      the race to take the locks.
   3. The Read goroutine completes the handshake and wins a race
      to unlock and relock c.in, which it'll hold when waiting for
      more network data.

If the application-level protocol requires the Write to complete before
data can be read then the system as a whole will deadlock.

Unfortunately it doesn't appear possible to reverse the locking order of
c.in and handshakeMutex because we might read a renegotiation request at
any point and need to be able to do a handshake without unlocking.

So this change adds a sync.Cond that indicates that a goroutine has
committed to doing a handshake. Other interested goroutines can wait on
that Cond when needed.

The test for this isn't great. I was able to reproduce the deadlock with
it only when building with -race. (Because -race happened to alter the
timing just enough.)

Fixes #17101.

Change-Id: I4e8757f7b82a84e46c9963a977d089f0fb675495
Reviewed-on: https://go-review.googlesource.com/29164
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-on: https://go-review.googlesource.com/31268
2016-10-17 20:24:52 +00:00
Michael Munday
230c3918a8 [release-branch.go1.7] runtime: fix SIGILL in checkvectorfacility on s390x
STFLE does not necessarily write to all the double-words that are
requested. It is therefore necessary to clear the target memory
before calling STFLE in order to ensure that the facility list does
not contain false positives.

Fixes #17032.

Change-Id: I7bec9ade7103e747b72f08562fe57e6f091bd89f
Reviewed-on: https://go-review.googlesource.com/28850
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/31267
Reviewed-by: Michael Munday <munday@ca.ibm.com>
2016-10-17 20:24:42 +00:00
Brad Fitzpatrick
b67902fee7 [release-branch.go1.7] net/http: update bundled http2
Updates bundled http2 for x/net/http2 git rev 8d4d01f0 for:

[release-branch.go1.7] http2: don't sniff first Request.Body byte in Transport until we have a conn
https://golang.org/cl/29074

Fixes #17071

Change-Id: I37fef5c2c0fdf499545f9af08abd5f9edb2da4c0
Reviewed-on: https://go-review.googlesource.com/29111
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-09-15 22:24:39 +00:00
Michal Bohuslávek
5a589904a3 [release-branch.go1.7] doc: fix typo in the release notes
Change-Id: I003795d8dc2176532ee133740bf35e23a3aa3878
Reviewed-on: https://go-review.googlesource.com/28811
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/28774
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-09-08 16:43:05 +00:00
Chris Broadfoot
f75aafdf56 [release-branch.go1.7] go1.7.1
Change-Id: Id877244fba01ae84255ad2d1f6334d096d5d6f71
Reviewed-on: https://go-review.googlesource.com/28694
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-07 19:11:54 +00:00
Chris Broadfoot
b261730e56 [release-branch.go1.7] doc: document go1.7.1
Change-Id: I6bdbf0cafa0f70bdb7c435e45885f5d8f9e05dad
Reviewed-on: https://go-review.googlesource.com/28693
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/28692
2016-09-07 19:10:12 +00:00
Austin Clements
40712a9625 [release-branch.go1.7] runtime: fix check for vacuous page boundary rounding again
The previous fix for this, commit 336dad2a, had everything right in
the commit message, but reversed the test in the code. Fix the test in
the code.

This reversal effectively disabled the scavenger on large page systems
*except* in the rare cases where this code was originally wrong, which
is why it didn't obviously show up in testing.

Fixes #16644. Again. :(

Change-Id: I27cce4aea13de217197db4b628f17860f27ce83e
Reviewed-on: https://go-review.googlesource.com/27402
Run-TryBot: Austin Clements <austin@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/28631
Run-TryBot: Chris Broadfoot <cbro@golang.org>
2016-09-07 18:48:36 +00:00
Keith Randall
24f46bd34f [release-branch.go1.7] cmd/compile: compare size in dead store elimination
This CL is a manual backpatch of CL 27320 into the 1.7.1 release branch.

The manual backpatch is required because OpZero changed from having a
size as its AuxInt to having a size+align as its AuxInt (that was to support
the ARM SSA backend).  Otherwise the CLs should be identical.

Please review carefully!

Change-Id: I569b759c06d1971c9c62dc5dd589abc7ef7c844a
Reviewed-on: https://go-review.googlesource.com/28670
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-09-07 18:48:24 +00:00
Brad Fitzpatrick
c24b5d43a6 [release-branch.go1.7] syscall: use MNT_NOWAIT in TestGetfsstat
Fixes test failure when VMWare's shared folder filesystem is present.

MNT_NOWAIT is what the mount(8) command does.

Fixes #16937

Change-Id: Id436185f544b7069db46c8716d6a0bf580b31da0
Reviewed-on: https://go-review.googlesource.com/28550
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-on: https://go-review.googlesource.com/28650
Run-TryBot: Chris Broadfoot <cbro@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-07 18:15:52 +00:00
Brad Fitzpatrick
dc3612e0d1 [release-branch.go1.7] net/http: fix unwanted HTTP/2 conn Transport crash after IdleConnTimeout
Go 1.7 crashed after Transport.IdleConnTimeout if an HTTP/2 connection
was established but but its caller no longer wanted it. (Assuming the
connection cache was enabled, which it is by default)

Fixes #16208

Change-Id: I9628757f7669e344f416927c77f00ed3864839e3
Reviewed-on: https://go-review.googlesource.com/27450
Reviewed-by: Andrew Gerrand <adg@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/28637
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-07 17:49:20 +00:00
Brad Fitzpatrick
6f12826a86 [release-branch.go1.7] net/http: make Transport.CancelRequest doc recommend Request.WithContext
The old deprecation docs were referencing another deprecated field.

Fixes #16752

Change-Id: I44a690048e00ddc790a80214ecb7f5bb0a5b7b34
Reviewed-on: https://go-review.googlesource.com/27510
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Reviewed-on: https://go-review.googlesource.com/28638
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-07 17:47:55 +00:00
Hiroshi Ioka
3129c67db7 [release-branch.go1.7] path/filepath: handle ".." in normalizing a path on Windows
Current code assumes there are not ".." in the Clean(path).
That's not true. Clean doesn't handle leading "..", so we need to stop
normalization if we see "..".

Fixes #16793

Change-Id: I0a7901bedac17f1210b134d593ebd9f5e8483775
Reviewed-on: https://go-review.googlesource.com/27410
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/28641
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-07 17:47:27 +00:00
Matthew Dempsky
bb8706890b [release-branch.go1.7] net: restore per-query timeout logic
The handling of "options timeout:n" is supposed to be per individual
DNS server exchange, not per Lookup call.

Fixes #16865.

Change-Id: I2304579b9169c1515292f142cb372af9d37ff7c1
Reviewed-on: https://go-review.googlesource.com/28057
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/28640
2016-09-07 17:47:00 +00:00
Egon Elbre
287be1e42d [release-branch.go1.7] website: recreate 16px and 32px favicon
Recreated original favicon with svg. Note, the rasterizations are hand
tweaked for crispness and straight export will not give the same results.

Fixes #6938

Change-Id: I9bf7b59028711361c29365b145932d90af419b69
Reviewed-on: https://go-review.googlesource.com/26850
Reviewed-by: Chris Broadfoot <cbro@golang.org>
Reviewed-on: https://go-review.googlesource.com/28639
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-07 17:46:59 +00:00
Tom Wilkie
308bdd0256 [release-branch.go1.7] net: don't avoid resolving .local addresses
.local addresses are used by things like Kubernetes and Weave DNS; Go
should not avoid resolving them.

This is a partial revert of https://golang.org/cl/21328 which was too
strict of an interpretation of RFC 6762.

Fixes #16739

Change-Id: I349415b4eab5d61240dd18217bd95dc7d2105cd5
Reviewed-on: https://go-review.googlesource.com/27250
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/28632
2016-09-07 17:46:47 +00:00
David Crawshaw
9b4e323e88 [release-branch.go1.7] reflect: clear tflag on new types
Fixes #16722

Change-Id: I50a0e69d3e79d13bc1860cd983267c3db087a4b8
Reviewed-on: https://go-review.googlesource.com/27119
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/28630
2016-09-07 17:46:45 +00:00
Michael Munday
a5add8c726 [release-branch.go1.7] hash/crc32: fix optimized s390x implementation
The code wasn't checking to see if the data was still >= 64 bytes
long after aligning it.

Aligning the data is an optimization and we don't actually need
to do it. In fact for smaller sizes it slows things down due to
the overhead of calling the generic function. Therefore for now
I have simply removed the alignment stage. I have also added a
check into the assembly to deliberately trigger a segmentation
fault if the data is too short.

Fixes #16779.

Change-Id: Ic01636d775efc5ec97689f050991cee04ce8fe73
Reviewed-on: https://go-review.googlesource.com/27409
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/28635
2016-09-07 17:46:02 +00:00
Brad Fitzpatrick
e464c08bef [release-branch.go1.7] io: fix infinite loop bug in MultiReader
If an io.Reader returned (non-zero, EOF), MultiReader would yield
bytes forever.

This bug has existed before Go 1 (!!), introduced in the original
MultiReader implementation in https://golang.org/cl/1764043 and also
survived basically the only update to this code since then
(https://golang.org/cl/17873, git rev ccdca832c), which was added in
Go 1.7.

This just bit me when writing a test for some unrelated code.

Fixes #16795

Change-Id: I36e6a701269793935d19a47ac12f67b07179fbff
Reviewed-on: https://go-review.googlesource.com/27397
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Reviewed-on: https://go-review.googlesource.com/28633
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-07 17:45:58 +00:00
Joe Tsai
c0f5de1ad2 [release-branch.go1.7] compress/flate: make huffmanBitWriter errors persistent
For persistent error handling, the methods of huffmanBitWriter have to be
consistent about how they check errors. It must either consistently
check error *before* every operation OR immediately *after* every
operation. Since most of the current logic uses the previous approach,
we apply the same style of error checking to writeBits and all calls
to Write such that they only operate if w.err is already nil going
into them.

The error handling approach is brittle and easily broken by future commits to
the code. In the near future, we should switch the logic to use panic at the
lowest levels and a recover at the edge of the public API to ensure
that errors are always persistent.

Fixes #16749

Change-Id: Ie1d83e4ed8842f6911a31e23311cd3cbf38abe8c
Reviewed-on: https://go-review.googlesource.com/27200
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/28634
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-07 17:45:45 +00:00
Brad Fitzpatrick
1861ac159e [release-branch.go1.7] net/http: update bundled http2 for Transport double STREAM_ENDED error
Updates bundled http2 to x/net/http2 git rev 7394c11 for:

http2: fix protocol violation regression when writing certain request bodies
https://golang.org/cl/27406

Fixes #16788

Change-Id: I0efcd36e2b4b34a1df79f763d35bf7a3a1858506
Reviewed-on: https://go-review.googlesource.com/27451
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
Reviewed-on: https://go-review.googlesource.com/28636
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-07 17:45:41 +00:00
Brad Fitzpatrick
759c2c48ea [release-branch.go1.7] doc/go1.7.html: fix name of tls.Config.NextProtos
Updates #16737

Change-Id: Ia51fc9b06df43b7c6f7136e90b40362263c20081
Reviewed-on: https://go-review.googlesource.com/27126
Reviewed-by: Chris Broadfoot <cbro@golang.org>
Reviewed-on: https://go-review.googlesource.com/27234
2016-08-17 17:35:08 +00:00
Chris Broadfoot
09fa0b8e95 [release-branch.go1.7] doc: add 1.7 to golang.org/project
Change-Id: Ib17f6643efd49e2bca188c4faa505f79832d18b1
Reviewed-on: https://go-review.googlesource.com/27110
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/27112
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-08-16 01:17:11 +00:00
Chris Broadfoot
0d81858868 go1.7
Change-Id: Id86f2615772ce087c2ac1a9039ffc27c33298773
Reviewed-on: https://go-review.googlesource.com/27075
Run-TryBot: Chris Broadfoot <cbro@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-08-15 22:43:38 +00:00
Chris Broadfoot
681a667ced [release-branch.go1.7] doc: document go1.7
Change-Id: Ieae5831b35768a625bf735a38f3d938f23f0b77b
Reviewed-on: https://go-review.googlesource.com/27057
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/27070
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-08-15 20:16:48 +00:00
Chris Broadfoot
806a84d3f1 [release-branch.go1.7] doc: update version tag in source install instructions
Change-Id: Id83e0371b7232b01be83640ef1e47f9026cf2a23
Reviewed-on: https://go-review.googlesource.com/27055
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/27056
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-08-15 19:52:58 +00:00
Chris Broadfoot
87d4bd1997 [release-branch.go1.6] doc/go1.7.html: remove DRAFT
Fixes #15820.

Change-Id: Ia5d5237754e77774a3a6049765eea163911f41c9
Reviewed-on: https://go-review.googlesource.com/25592
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/27054
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-08-15 18:53:48 +00:00
Chris Broadfoot
1e933ed7c0 go1.7rc6
Change-Id: Ie76b5af0ecc4c64c523110b44483c06e7031237c
Reviewed-on: https://go-review.googlesource.com/25582
Reviewed-by: Chris Broadfoot <cbro@golang.org>
2016-08-08 18:42:30 +00:00
Chris Broadfoot
78d024a588 all: merge master into release-branch.go1.7
7a62274 net/http: make Transport use new connection if over HTTP/2 concurrency limit
219ca60 doc: fix required OS X version inconsistency for binary downloads
26015b9 runtime: make stack 16-byte aligned for external code in _rt0_amd64_linux_lib
9fde86b runtime, syscall: fix kernel gettimeofday ABI change on iOS 10
3a03e87 os: check for waitid returning ENOSYS
1031675 net/http: update bundled http2 for flow control window adjustment fix
da070be syscall: fix Gettimeofday on macOS Sierra
f135c32 runtime: initialize hash algs before typemap

Change-Id: Ie176f3db1e253d75ae8e56b16d3fd9900b37dde3
2016-08-08 11:30:51 -07:00
Chris Broadfoot
09fc3cc5df go1.7rc5
Change-Id: I5571a5fa679065060950c554f7b28e42268b3e74
Reviewed-on: https://go-review.googlesource.com/25417
Run-TryBot: Chris Broadfoot <cbro@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-08-02 23:34:48 +00:00
Chris Broadfoot
17a48e0a00 all: merge master into release-branch.go1.7
Change-Id: I77d1665af543dc71f30b2afa48eac411de11afc7
2016-08-02 14:44:26 -07:00
59 changed files with 1695 additions and 219 deletions

1
VERSION Normal file
View File

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

View File

@@ -67,7 +67,6 @@ official forums operated by the Go project (“Go spaces”):
<li>The <a href="https://groups.google.com/group/golang-nuts">golang-nuts</a> and
<a href="https://groups.google.com/group/golang-dev">golang-dev</a> mailing lists.
<li>The #go-nuts IRC channel on Freenode.
<li>The <a href="https://reddit.com/r/golang">/r/golang subreddit</a>.
</ul>
<p>

View File

@@ -34,6 +34,7 @@ We encourage all Go users to subscribe to
<p>A <a href="/doc/devel/release.html">summary</a> of the changes between Go releases. Notes for the major releases:</p>
<ul>
<li><a href="/doc/go1.7">Go 1.7</a> <small>(August 2016)</small></li>
<li><a href="/doc/go1.6">Go 1.6</a> <small>(February 2016)</small></li>
<li><a href="/doc/go1.5">Go 1.5</a> <small>(August 2015)</small></li>
<li><a href="/doc/go1.4">Go 1.4</a> <small>(December 2014)</small></li>

View File

@@ -30,6 +30,52 @@ to fix critical security problems in both Go 1.4 and Go 1.5 as they arise.
See the <a href="/security">security policy</a> for more details.
</p>
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
<p>
Go 1.7 is a major release of Go.
Read the <a href="/doc/go1.7">Go 1.7 Release Notes</a> for more information.
</p>
<h3 id="go1.7.minor">Minor revisions</h3>
<p>
go1.7.1 (released 2016/09/07) includes fixes to the compiler, runtime,
documentation, and the <code>compress/flate</code>, <code>hash/crc32</code>,
<code>io</code>, <code>net</code>, <code>net/http</code>,
<code>path/filepath</code>, <code>reflect</code>, and <code>syscall</code>
packages.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.1">Go
1.7.1 milestone</a> on our issue tracker for details.
</p>
<p>
go1.7.2 should not be used. It was tagged but not fully released.
The release was deferred due to a last minute bug report.
Use go1.7.3 instead, and refer to the summary of changes below.
</p>
<p>
go1.7.3 (released 2016/10/19) includes fixes to the compiler, runtime,
and the <code>crypto/cipher</code>, <code>crypto/tls</code>,
<code>net/http</code>, and <code>strings</code> packages.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.3">Go
1.7.3 milestone</a> on our issue tracker for details.
</p>
<p>
go1.7.4 (released 2016/12/01) includes two security fixes.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.4">Go
1.7.4 milestone</a> on our issue tracker for details.
</p>
<p>
go1.7.5 (released 2017/01/26) includes fixes to the compiler, runtime,
and the <code>crypto/x509</code> and <code>time</code> packages.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.5">Go
1.7.5 milestone</a> on our issue tracker for details.
</p>
<h2 id="go1.6">go1.6 (released 2016/02/17)</h2>
<p>
@@ -56,11 +102,18 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.2">Go
<p>
go1.6.3 (released 2016/07/17) includes security fixes to the
<code>net/http/cgi</code> package and <code>net/http</code> package when used in
a CGI environment. This release also adds support for macOS Sierra.
a CGI environment.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.3">Go
1.6.3 milestone</a> on our issue tracker for details.
</p>
<p>
go1.6.4 (released 2016/12/01) includes two security fixes.
It contains the same fixes as Go 1.7.4 and was released at the same time.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.4">Go
1.7.4 milestone</a> on our issue tracker for details.
</p>
<h2 id="go1.5">go1.5 (released 2015/08/19)</h2>
<p>

View File

@@ -1,5 +1,5 @@
<!--{
"Title": "Go 1.7 Release Notes DRAFT",
"Title": "Go 1.7 Release Notes",
"Path": "/doc/go1.7",
"Template": true
}-->
@@ -25,15 +25,6 @@ Do not send CLs removing the interior tags from such phrases.
ul li { margin: 0.5em 0; }
</style>
<p>
<!-- TODO: REMOVE THIS COMMENT -->
<!-- TODO: Also remove "DRAFT" in the "Title" at the top of this file. -->
<i>NOTE: This is a DRAFT of the Go 1.7 release notes, prepared for the Go 1.7 beta.
Go 1.7 has NOT yet been released.
By our regular schedule, it is expected some time in August 2016.
</i>
</p>
<h2 id="introduction">Introduction to Go 1.7</h2>
<p>
@@ -76,8 +67,7 @@ This change has no effect on the correctness of existing programs.
<p>
Go 1.7 adds support for macOS 10.12 Sierra.
This support was backported to Go 1.6.3.
Binaries built with versions of Go before 1.6.3 will not work
Binaries built with versions of Go before 1.7 will not work
correctly on Sierra.
</p>
@@ -919,7 +909,7 @@ For example, the address on which a request received is
<p>
The server's <a href="/pkg/net/http/#Server.Serve"><code>Serve</code></a> method
now only enables HTTP/2 support if the <code>Server.TLSConfig</code> field is <code>nil</code>
or includes <code>"h2"</code> in its <code>TLSConfig.NextProto</code>.
or includes <code>"h2"</code> in its <code>TLSConfig.NextProtos</code>.
</p>
<p>

238
doc/gopher/favicon.svg Normal file
View File

@@ -0,0 +1,238 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
height="32"
viewBox="0 0 32 32.000001"
id="svg4416"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="favicon.svg"
inkscape:export-filename="../../favicon.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4418" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.839192"
inkscape:cx="17.966652"
inkscape:cy="9.2991824"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:snap-bbox-edge-midpoints="false"
inkscape:bbox-nodes="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1018"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid5148" />
</sodipodi:namedview>
<metadata
id="metadata4421">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="icon"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1020.3622)">
<ellipse
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#384e54;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="ellipse4216"
cx="-907.35657"
cy="479.90009"
rx="3.5793996"
ry="3.8207953"
transform="matrix(-0.49169095,-0.87076978,-0.87076978,0.49169095,0,0)"
inkscape:transform-center-x="0.67794294"
inkscape:transform-center-y="-2.3634048" />
<ellipse
inkscape:transform-center-y="-2.3633882"
inkscape:transform-center-x="-0.67793718"
transform="matrix(0.49169095,-0.87076978,0.87076978,0.49169095,0,0)"
ry="3.8207953"
rx="3.5793996"
cy="507.8461"
cx="-891.57654"
id="ellipse4463"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#384e54;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#384e54;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 16.091693,1021.3642 c -1.105749,0.01 -2.210341,0.049 -3.31609,0.09 C 6.8422558,1021.6738 2,1026.3942 2,1032.3622 c 0,2.9786 0,13 0,20 l 28,0 c 0,-8 0,-16 0,-20 0,-5.9683 -4.667345,-10.4912 -10.59023,-10.908 -1.10575,-0.078 -2.212328,-0.099 -3.318077,-0.09 z"
id="path4465"
sodipodi:nodetypes="ccsccscc" />
<path
inkscape:transform-center-y="-1.3604657"
inkscape:transform-center-x="-0.98424303"
sodipodi:nodetypes="sssssss"
inkscape:connector-curvature="0"
id="path4469"
d="m 4.6078867,1025.0462 c 0.459564,0.2595 1.818262,1.2013 1.980983,1.648 0.183401,0.5035 0.159385,1.0657 -0.114614,1.551 -0.346627,0.6138 -1.005341,0.9487 -1.696421,0.9365 -0.339886,-0.01 -1.720283,-0.6372 -2.042561,-0.8192 -0.97754,-0.5519 -1.350795,-1.7418 -0.833686,-2.6576 0.517109,-0.9158 1.728749,-1.2107 2.706299,-0.6587 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#76e1fe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.32850246;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4473"
width="3.0866659"
height="3.5313663"
x="14.406213"
y="1035.6842"
ry="0.62426329" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#76e1fe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 16,1023.3622 c -9,0 -12,3.7153 -12,9 l 0,20 24,0 c -0.04889,-7.3562 0,-18 0,-20 0,-5.2848 -3,-9 -12,-9 z"
id="path4471"
sodipodi:nodetypes="zsccsz" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#76e1fe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 27.074073,1025.0462 c -0.45957,0.2595 -1.818257,1.2013 -1.980979,1.648 -0.183401,0.5035 -0.159384,1.0657 0.114614,1.551 0.346627,0.6138 1.005335,0.9487 1.696415,0.9365 0.33988,-0.01 1.72029,-0.6372 2.04256,-0.8192 0.97754,-0.5519 1.35079,-1.7418 0.83369,-2.6576 -0.51711,-0.9158 -1.72876,-1.2107 -2.7063,-0.6587 z"
id="path4481"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssss"
inkscape:transform-center-x="0.98424094"
inkscape:transform-center-y="-1.3604657" />
<circle
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="circle4477"
cx="21.175734"
cy="1030.3542"
r="4.6537542"
inkscape:export-filename=".\rect4485.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<circle
r="4.8316345"
cy="1030.3542"
cx="10.339486"
id="circle4483"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
inkscape:export-filename=".\rect4485.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename=".\rect4485.png"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.32941176;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4246"
width="3.6673687"
height="4.1063409"
x="14.115863"
y="1035.9174"
ry="0.72590536" />
<rect
ry="0.72590536"
y="1035.2253"
x="14.115863"
height="4.1063409"
width="3.6673687"
id="rect4485"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#fffcfb;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
inkscape:export-filename=".\rect4485.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.32941176;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 19.999735,1036.5289 c 0,0.838 -0.871228,1.2682 -2.144766,1.1659 -0.02366,0 -0.04795,-0.6004 -0.254147,-0.5832 -0.503669,0.042 -1.095902,-0.02 -1.685964,-0.02 -0.612939,0 -1.206342,0.1826 -1.68549,0.017 -0.110233,-0.038 -0.178298,0.5838 -0.261532,0.5816 -1.243685,-0.033 -2.078803,-0.3383 -2.078803,-1.1618 0,-1.2118 1.815635,-2.1941 4.055351,-2.1941 2.239704,0 4.055351,0.9823 4.055351,2.1941 z"
id="path4487"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssss"
inkscape:export-filename=".\rect4485.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<path
sodipodi:nodetypes="sssssssss"
inkscape:connector-curvature="0"
id="path4489"
d="m 19.977414,1035.7004 c 0,0.5685 -0.433659,0.8554 -1.138091,1.0001 -0.291933,0.06 -0.630371,0.096 -1.003719,0.1166 -0.56405,0.032 -1.207782,0.031 -1.89122,0.031 -0.672834,0 -1.307182,0 -1.864904,-0.029 -0.306268,-0.017 -0.589429,-0.043 -0.843164,-0.084 -0.813833,-0.1318 -1.324962,-0.417 -1.324962,-1.0344 0,-1.1601 1.805642,-2.1006 4.03303,-2.1006 2.227377,0 4.03303,0.9405 4.03303,2.1006 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c38c74;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
inkscape:export-filename=".\rect4485.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<ellipse
cy="1033.8501"
cx="15.944382"
id="ellipse4491"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#23201f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
rx="2.0801733"
ry="1.343747"
inkscape:export-filename=".\rect4485.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<circle
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#171311;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="circle4493"
cx="12.414201"
cy="1030.3542"
r="1.9630634"
inkscape:export-filename=".\rect4485.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<circle
r="1.9630634"
cy="1030.3542"
cx="23.110121"
id="circle4495"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#171311;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
inkscape:export-filename=".\rect4485.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path4497"
d="m 5.0055377,1027.2727 c -1.170435,-1.0835 -2.026973,-0.7721 -2.044172,-0.7463"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#384e54;stroke-width:0.39730874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="display:inline;fill:none;fill-rule:evenodd;stroke:#384e54;stroke-width:0.39730874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.3852457,1026.9152 c -1.158557,0.036 -1.346704,0.6303 -1.33881,0.6523"
id="path4499"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="display:inline;fill:none;fill-rule:evenodd;stroke:#384e54;stroke-width:0.39730874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 26.630533,1027.1724 c 1.17043,-1.0835 2.02697,-0.7721 2.04417,-0.7463"
id="path4501"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path4503"
d="m 27.321773,1026.673 c 1.15856,0.036 1.3467,0.6302 1.3388,0.6522"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#384e54;stroke-width:0.39730874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -119,27 +119,39 @@ Go does not support CentOS 6 on these systems.
<p>
The Go tool chain is written in Go. To build it, you need a Go compiler installed.
The scripts that do the initial build of the tools look for an existing Go tool
chain in <code>$HOME/go1.4</code>.
(This path may be overridden by setting the <code>GOROOT_BOOTSTRAP</code>
environment variable.)
chain in <code>$GOROOT_BOOTSTRAP</code>.
If unset, the default value of <code>GOROOT_BOOTSTRAP</code>
is <code>$HOME/go1.4</code>.
</p>
<p>
Build the tools with Go version 1.4 or a point release (1.4.1, 1.4.2 etc.).
Go 1.4 binaries can be found at <a href="/dl/">the downloads page</a>.
There are many options for the bootstrap tool chain.
After obtaining one, set <code>GOROOT_BOOTSTRAP</code> to the
directory containing the unpacked tree.
For example, <code>$GOROOT_BOOTSTRAP/bin/go</code> should be
the <code>go</code> command binary for the bootstrap tool chain.
</p>
<p>
Download the zip or tarball of Go 1.4 for your platform and extract it to
<code>$HOME/go1.4</code> (or your nominated <code>GOROOT_BOOTSTRAP</code>
location).
To use a binary release as a bootstrap tool chain, see
<a href="/dl/">the downloads page</a> or use any other
packaged Go distribution.
</p>
<p>
If you want to install Go 1.5 on a system that is not supported by Go 1.4 (such
as <code>linux/ppc64</code> and <code>linux/mips64le</code>) you can either use
<a href="/src/bootstrap.bash">bootstrap.bash</a> on a system that can bootstrap Go
1.5 normally, or bootstrap with gccgo 5.
To build a bootstrap tool chain from source, use
either the git branch <code>release-branch.go1.4</code> or
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20161024.tar.gz">go1.4-bootstrap-20161024.tar.gz</a>,
which contains the Go 1.4 source code plus accumulated fixes
to keep the tools running on newer operating systems.
(Go 1.4 was the last distribution in which the tool chain was written in C.)
</p>
<p>
To cross-compile a bootstrap tool chain from source, which is
necessary on systems Go 1.4 did not target (for
example, <code>linux/ppc64le</code>), install Go on a different system
and run <a href="/src/bootstrap.bash">bootstrap.bash</a>.
</p>
<p>
@@ -158,8 +170,9 @@ and used as <code>GOROOT_BOOTSTRAP</code> to bootstrap a local build.
</p>
<p>
To use gccgo, you need to arrange for <code>$GOROOT_BOOTSTRAP/bin/go</code> to be
the go tool that comes as part of gccgo 5. For example on Ubuntu Vivid:
To use gccgo as the bootstrap toolchain, you need to arrange
for <code>$GOROOT_BOOTSTRAP/bin/go</code> to be the go tool that comes
as part of gccgo 5. For example on Ubuntu Vivid:
</p>
<pre>
@@ -203,7 +216,7 @@ To build without <code>cgo</code>, set the environment variable
Change to the directory that will be its parent
and make sure the <code>go</code> directory does not exist.
Then clone the repository and check out the latest release tag
(<code class="versionTag">go1.6</code>, for example):</p>
(<code class="versionTag">go1.7.2</code>, for example):</p>
<pre>
$ git clone https://go.googlesource.com/go
@@ -391,7 +404,7 @@ New releases are announced on the
<a href="//groups.google.com/group/golang-announce">golang-announce</a>
mailing list.
Each announcement mentions the latest release tag, for instance,
<code class="versionTag">go1.6</code>.
<code class="versionTag">go1.7.2</code>.
</p>
<p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -472,9 +472,29 @@ func escAnalyze(all []*Node, recursive bool) {
// visit the upstream of each dst, mark address nodes with
// addrescapes, mark parameters unsafe
escapes := make([]uint16, len(e.dsts))
for i, n := range e.dsts {
escapes[i] = n.Esc
}
for _, n := range e.dsts {
escflood(e, n)
}
for {
done := true
for i, n := range e.dsts {
if n.Esc != escapes[i] {
done = false
if Debug['m'] > 2 {
Warnl(n.Lineno, "Reflooding %v %S", e.curfnSym(n), n)
}
escapes[i] = n.Esc
escflood(e, n)
}
}
if done {
break
}
}
// for all top level functions, tag the typenodes corresponding to the param nodes
for _, n := range all {
@@ -1796,6 +1816,7 @@ func escwalkBody(e *EscState, level Level, dst *Node, src *Node, step *EscStep,
}
leaks = level.int() <= 0 && level.guaranteedDereference() <= 0 && dstE.Escloopdepth < modSrcLoopdepth
leaks = leaks || level.int() <= 0 && dst.Esc&EscMask == EscHeap
osrcesc = src.Esc
switch src.Op {

View File

@@ -1042,6 +1042,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
var r *Node
if n.Right != nil {
// n.Right is stack temporary used as backing store.
init.Append(Nod(OAS, n.Right, nil)) // zero backing store, just in case (#18410)
r = Nod(OADDR, n.Right, nil)
r = typecheck(r, Erv)
} else {

View File

@@ -14,8 +14,7 @@ func dse(f *Func) {
defer f.retSparseSet(loadUse)
storeUse := f.newSparseSet(f.NumValues())
defer f.retSparseSet(storeUse)
shadowed := f.newSparseSet(f.NumValues())
defer f.retSparseSet(shadowed)
shadowed := newSparseMap(f.NumValues()) // TODO: cache
for _, b := range f.Blocks {
// Find all the stores in this block. Categorize their uses:
// loadUse contains stores which are used by a subsequent load.
@@ -81,17 +80,18 @@ func dse(f *Func) {
shadowed.clear()
}
if v.Op == OpStore || v.Op == OpZero {
if shadowed.contains(v.Args[0].ID) {
sz := v.AuxInt
if shadowedSize := int64(shadowed.get(v.Args[0].ID)); shadowedSize != -1 && shadowedSize >= sz {
// Modify store into a copy
if v.Op == OpStore {
// store addr value mem
v.SetArgs1(v.Args[2])
} else {
// zero addr mem
sz := v.Args[0].Type.ElemType().Size()
if v.AuxInt != sz {
typesz := v.Args[0].Type.ElemType().Size()
if sz != typesz {
f.Fatalf("mismatched zero/store sizes: %d and %d [%s]",
v.AuxInt, sz, v.LongString())
sz, typesz, v.LongString())
}
v.SetArgs1(v.Args[1])
}
@@ -99,7 +99,10 @@ func dse(f *Func) {
v.AuxInt = 0
v.Op = OpCopy
} else {
shadowed.add(v.Args[0].ID)
if sz > 0x7fffffff { // work around sparseMap's int32 value type
sz = 0x7fffffff
}
shadowed.set(v.Args[0].ID, int32(sz))
}
}
// walk to previous store

View File

@@ -8,7 +8,7 @@ import "testing"
func TestDeadStore(t *testing.T) {
c := testConfig(t)
elemType := &TypeImpl{Size_: 8, Name: "testtype"}
elemType := &TypeImpl{Size_: 1, Name: "testtype"}
ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr", Elem_: elemType} // dummy for testing
fun := Fun(c, "entry",
Bloc("entry",
@@ -18,7 +18,7 @@ func TestDeadStore(t *testing.T) {
Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
Valu("addr2", OpAddr, ptrType, 0, nil, "sb"),
Valu("addr3", OpAddr, ptrType, 0, nil, "sb"),
Valu("zero1", OpZero, TypeMem, 8, nil, "addr3", "start"),
Valu("zero1", OpZero, TypeMem, 1, nil, "addr3", "start"),
Valu("store1", OpStore, TypeMem, 1, nil, "addr1", "v", "zero1"),
Valu("store2", OpStore, TypeMem, 1, nil, "addr2", "v", "store1"),
Valu("store3", OpStore, TypeMem, 1, nil, "addr1", "v", "store2"),
@@ -95,3 +95,32 @@ func TestDeadStoreTypes(t *testing.T) {
t.Errorf("store %s incorrectly removed", v)
}
}
func TestDeadStoreUnsafe(t *testing.T) {
// Make sure a narrow store can't shadow a wider one. The test above
// covers the case of two different types, but unsafe pointer casting
// can get to a point where the size is changed but type unchanged.
c := testConfig(t)
ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing
fun := Fun(c, "entry",
Bloc("entry",
Valu("start", OpInitMem, TypeMem, 0, nil),
Valu("sb", OpSB, TypeInvalid, 0, nil),
Valu("v", OpConstBool, TypeBool, 1, nil),
Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
Valu("store1", OpStore, TypeMem, 8, nil, "addr1", "v", "start"), // store 8 bytes
Valu("store2", OpStore, TypeMem, 1, nil, "addr1", "v", "store1"), // store 1 byte
Goto("exit")),
Bloc("exit",
Exit("store2")))
CheckFunc(fun.f)
cse(fun.f)
dse(fun.f)
CheckFunc(fun.f)
v := fun.values["store1"]
if v.Op == OpCopy {
t.Errorf("store %s incorrectly removed", v)
}
}

View File

@@ -724,7 +724,7 @@ func (w *Writer) Close() error {
// the result of NewWriter or NewWriterDict called with dst
// and w's level and dictionary.
func (w *Writer) Reset(dst io.Writer) {
if dw, ok := w.d.w.w.(*dictWriter); ok {
if dw, ok := w.d.w.writer.(*dictWriter); ok {
// w was created with NewWriterDict
dw.w = dst
w.d.reset(dw)

View File

@@ -6,6 +6,7 @@ package flate
import (
"bytes"
"errors"
"fmt"
"internal/testenv"
"io"
@@ -631,3 +632,52 @@ func TestBestSpeed(t *testing.T) {
}
}
}
var errIO = errors.New("IO error")
// failWriter fails with errIO exactly at the nth call to Write.
type failWriter struct{ n int }
func (w *failWriter) Write(b []byte) (int, error) {
w.n--
if w.n == -1 {
return 0, errIO
}
return len(b), nil
}
func TestWriterPersistentError(t *testing.T) {
d, err := ioutil.ReadFile("../testdata/Mark.Twain-Tom.Sawyer.txt")
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
d = d[:10000] // Keep this test short
zw, err := NewWriter(nil, DefaultCompression)
if err != nil {
t.Fatalf("NewWriter: %v", err)
}
// Sweep over the threshold at which an error is returned.
// The variable i makes it such that the ith call to failWriter.Write will
// return errIO. Since failWriter errors are not persistent, we must ensure
// that flate.Writer errors are persistent.
for i := 0; i < 1000; i++ {
fw := &failWriter{i}
zw.Reset(fw)
_, werr := zw.Write(d)
cerr := zw.Close()
if werr != errIO && werr != nil {
t.Errorf("test %d, mismatching Write error: got %v, want %v", i, werr, errIO)
}
if cerr != errIO && fw.n < 0 {
t.Errorf("test %d, mismatching Close error: got %v, want %v", i, cerr, errIO)
}
if fw.n >= 0 {
// At this point, the failure threshold was sufficiently high enough
// that we wrote the whole stream without any errors.
return
}
}
}

View File

@@ -77,7 +77,11 @@ var offsetBase = []uint32{
var codegenOrder = []uint32{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
type huffmanBitWriter struct {
w io.Writer
// writer is the underlying writer.
// Do not use it directly; use the write method, which ensures
// that Write errors are sticky.
writer io.Writer
// Data waiting to be written is bytes[0:nbytes]
// and then the low nbits of bits.
bits uint64
@@ -96,7 +100,7 @@ type huffmanBitWriter struct {
func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
return &huffmanBitWriter{
w: w,
writer: w,
literalFreq: make([]int32, maxNumLit),
offsetFreq: make([]int32, offsetCodeCount),
codegen: make([]uint8, maxNumLit+offsetCodeCount+1),
@@ -107,7 +111,7 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
}
func (w *huffmanBitWriter) reset(writer io.Writer) {
w.w = writer
w.writer = writer
w.bits, w.nbits, w.nbytes, w.err = 0, 0, 0, nil
w.bytes = [bufferSize]byte{}
}
@@ -129,11 +133,21 @@ func (w *huffmanBitWriter) flush() {
n++
}
w.bits = 0
_, w.err = w.w.Write(w.bytes[:n])
w.write(w.bytes[:n])
w.nbytes = 0
}
func (w *huffmanBitWriter) write(b []byte) {
if w.err != nil {
return
}
_, w.err = w.writer.Write(b)
}
func (w *huffmanBitWriter) writeBits(b int32, nb uint) {
if w.err != nil {
return
}
w.bits |= uint64(b) << w.nbits
w.nbits += nb
if w.nbits >= 48 {
@@ -150,7 +164,7 @@ func (w *huffmanBitWriter) writeBits(b int32, nb uint) {
bytes[5] = byte(bits >> 40)
n += 6
if n >= bufferFlushSize {
_, w.err = w.w.Write(w.bytes[:n])
w.write(w.bytes[:n])
n = 0
}
w.nbytes = n
@@ -173,13 +187,10 @@ func (w *huffmanBitWriter) writeBytes(bytes []byte) {
n++
}
if n != 0 {
_, w.err = w.w.Write(w.bytes[:n])
if w.err != nil {
return
}
w.write(w.bytes[:n])
}
w.nbytes = 0
_, w.err = w.w.Write(bytes)
w.write(bytes)
}
// RFC 1951 3.2.7 specifies a special run-length encoding for specifying
@@ -341,7 +352,7 @@ func (w *huffmanBitWriter) writeCode(c hcode) {
bytes[5] = byte(bits >> 40)
n += 6
if n >= bufferFlushSize {
_, w.err = w.w.Write(w.bytes[:n])
w.write(w.bytes[:n])
n = 0
}
w.nbytes = n
@@ -572,6 +583,9 @@ func (w *huffmanBitWriter) indexTokens(tokens []token) (numLiterals, numOffsets
// writeTokens writes a slice of tokens to the output.
// codes for literal and offset encoding must be supplied.
func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode) {
if w.err != nil {
return
}
for _, t := range tokens {
if t < matchType {
w.writeCode(leCodes[t.literal()])
@@ -676,9 +690,9 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte) {
if n < bufferFlushSize {
continue
}
_, w.err = w.w.Write(w.bytes[:n])
w.write(w.bytes[:n])
if w.err != nil {
return
return // Return early in the event of write failures
}
n = 0
}

View File

@@ -48,7 +48,9 @@ func (x *cbc) CryptBlocks(dst, src []byte) {
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src))
if len(src) > 0 {
cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src))
}
}
func (x *cbc) SetIV(iv []byte) {

View File

@@ -5,8 +5,10 @@
package cipher_test
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"testing"
)
@@ -34,3 +36,55 @@ func mustPanic(t *testing.T, msg string, f func()) {
}()
f()
}
func TestEmptyPlaintext(t *testing.T) {
var key [16]byte
a, err := aes.NewCipher(key[:16])
if err != nil {
t.Fatal(err)
}
d, err := des.NewCipher(key[:8])
if err != nil {
t.Fatal(err)
}
s := 16
pt := make([]byte, s)
ct := make([]byte, s)
for i := 0; i < 16; i++ {
pt[i], ct[i] = byte(i), byte(i)
}
assertEqual := func(name string, got, want []byte) {
if !bytes.Equal(got, want) {
t.Fatalf("%s: got %v, want %v", name, got, want)
}
}
for _, b := range []cipher.Block{a, d} {
iv := make([]byte, b.BlockSize())
cbce := cipher.NewCBCEncrypter(b, iv)
cbce.CryptBlocks(ct, pt[:0])
assertEqual("CBC encrypt", ct, pt)
cbcd := cipher.NewCBCDecrypter(b, iv)
cbcd.CryptBlocks(ct, pt[:0])
assertEqual("CBC decrypt", ct, pt)
cfbe := cipher.NewCFBEncrypter(b, iv)
cfbe.XORKeyStream(ct, pt[:0])
assertEqual("CFB encrypt", ct, pt)
cfbd := cipher.NewCFBDecrypter(b, iv)
cfbd.XORKeyStream(ct, pt[:0])
assertEqual("CFB decrypt", ct, pt)
ctr := cipher.NewCTR(b, iv)
ctr.XORKeyStream(ct, pt[:0])
assertEqual("CTR", ct, pt)
ofb := cipher.NewOFB(b, iv)
ofb.XORKeyStream(ct, pt[:0])
assertEqual("OFB", ct, pt)
}
}

View File

@@ -29,10 +29,14 @@ type Conn struct {
// constant after handshake; protected by handshakeMutex
handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex
handshakeErr error // error resulting from handshake
vers uint16 // TLS version
haveVers bool // version has been negotiated
config *Config // configuration passed to constructor
// handshakeCond, if not nil, indicates that a goroutine is committed
// to running the handshake for this Conn. Other goroutines that need
// to wait for the handshake can wait on this, under handshakeMutex.
handshakeCond *sync.Cond
handshakeErr error // error resulting from handshake
vers uint16 // TLS version
haveVers bool // version has been negotiated
config *Config // configuration passed to constructor
// handshakeComplete is true if the connection is currently transfering
// application data (i.e. is not currently processing a handshake).
handshakeComplete bool
@@ -1206,26 +1210,50 @@ func (c *Conn) Handshake() error {
// need to check whether a handshake is pending (such as Write) to
// block.
//
// Thus we take c.handshakeMutex first and, if we find that a handshake
// is needed, then we unlock, acquire c.in and c.handshakeMutex in the
// correct order, and check again.
// Thus we first take c.handshakeMutex to check whether a handshake is
// needed.
//
// If so then, previously, this code would unlock handshakeMutex and
// then lock c.in and handshakeMutex in the correct order to run the
// handshake. The problem was that it was possible for a Read to
// complete the handshake once handshakeMutex was unlocked and then
// keep c.in while waiting for network data. Thus a concurrent
// operation could be blocked on c.in.
//
// Thus handshakeCond is used to signal that a goroutine is committed
// to running the handshake and other goroutines can wait on it if they
// need. handshakeCond is protected by handshakeMutex.
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
for i := 0; i < 2; i++ {
if i == 1 {
c.handshakeMutex.Unlock()
c.in.Lock()
defer c.in.Unlock()
c.handshakeMutex.Lock()
}
for {
if err := c.handshakeErr; err != nil {
return err
}
if c.handshakeComplete {
return nil
}
if c.handshakeCond == nil {
break
}
c.handshakeCond.Wait()
}
// Set handshakeCond to indicate that this goroutine is committing to
// running the handshake.
c.handshakeCond = sync.NewCond(&c.handshakeMutex)
c.handshakeMutex.Unlock()
c.in.Lock()
defer c.in.Unlock()
c.handshakeMutex.Lock()
// The handshake cannot have completed when handshakeMutex was unlocked
// because this goroutine set handshakeCond.
if c.handshakeErr != nil || c.handshakeComplete {
panic("handshake should not have been able to complete after handshakeCond was set")
}
if c.isClient {
@@ -1236,6 +1264,16 @@ func (c *Conn) Handshake() error {
if c.handshakeErr == nil {
c.handshakes++
}
if c.handshakeErr == nil && !c.handshakeComplete {
panic("handshake should have had a result.")
}
// Wake any other goroutines that are waiting for this handshake to
// complete.
c.handshakeCond.Broadcast()
c.handshakeCond = nil
return c.handshakeErr
}

View File

@@ -1045,3 +1045,57 @@ func TestBuffering(t *testing.T) {
t.Errorf("expected server handshake to complete with only two writes, but saw %d", n)
}
}
func TestHandshakeRace(t *testing.T) {
// This test races a Read and Write to try and complete a handshake in
// order to provide some evidence that there are no races or deadlocks
// in the handshake locking.
for i := 0; i < 32; i++ {
c, s := net.Pipe()
go func() {
server := Server(s, testConfig)
if err := server.Handshake(); err != nil {
panic(err)
}
var request [1]byte
if n, err := server.Read(request[:]); err != nil || n != 1 {
panic(err)
}
server.Write(request[:])
server.Close()
}()
startWrite := make(chan struct{})
startRead := make(chan struct{})
readDone := make(chan struct{})
client := Client(c, testConfig)
go func() {
<-startWrite
var request [1]byte
client.Write(request[:])
}()
go func() {
<-startRead
var reply [1]byte
if n, err := client.Read(reply[:]); err != nil || n != 1 {
panic(err)
}
c.Close()
readDone <- struct{}{}
}()
if i&1 == 1 {
startWrite <- struct{}{}
startRead <- struct{}{}
} else {
startRead <- struct{}{}
startWrite <- struct{}{}
}
<-readDone
}
}

View File

@@ -64,6 +64,21 @@ func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCer
return
}
func (s *CertPool) contains(cert *Certificate) bool {
if s == nil {
return false
}
candidates := s.byName[string(cert.RawSubject)]
for _, c := range candidates {
if s.certs[c].Equal(cert) {
return true
}
}
return false
}
// AddCert adds a certificate to a pool.
func (s *CertPool) AddCert(cert *Certificate) {
if cert == nil {

View File

@@ -73,10 +73,11 @@ int useOldCode() {
//
// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
// certificates of the system. On failure, the function returns -1.
// Additionally, it fills untrustedPemRoots with certs that must be removed from pemRoots.
//
// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
// we've consumed its content.
int FetchPEMRoots(CFDataRef *pemRoots) {
// Note: The CFDataRef returned in pemRoots and untrustedPemRoots must
// be released (using CFRelease) after we've consumed its content.
int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
if (useOldCode()) {
return FetchPEMRoots_MountainLion(pemRoots);
}
@@ -93,23 +94,69 @@ int FetchPEMRoots(CFDataRef *pemRoots) {
return -1;
}
// kSecTrustSettingsResult is defined as CFSTR("kSecTrustSettingsResult"),
// but the Go linker's internal linking mode can't handle CFSTR relocations.
// Create our own dynamic string instead and release it below.
CFStringRef policy = CFStringCreateWithCString(NULL, "kSecTrustSettingsResult", kCFStringEncodingUTF8);
CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
CFMutableDataRef combinedUntrustedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
for (int i = 0; i < numDomains; i++) {
CFArrayRef certs = NULL;
// Only get certificates from domain that are trusted
OSStatus err = SecTrustSettingsCopyCertificates(domains[i], &certs);
if (err != noErr) {
continue;
}
int numCerts = CFArrayGetCount(certs);
CFIndex numCerts = CFArrayGetCount(certs);
for (int j = 0; j < numCerts; j++) {
CFDataRef data = NULL;
CFErrorRef errRef = NULL;
CFArrayRef trustSettings = NULL;
SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, j);
if (cert == NULL) {
continue;
}
// We only want trusted certs.
int untrusted = 0;
if (i != 0) {
// Certs found in the system domain are always trusted. If the user
// configures "Never Trust" on such a cert, it will also be found in the
// admin or user domain, causing it to be added to untrustedPemRoots. The
// Go code will then clean this up.
// Trust may be stored in any of the domains. According to Apple's
// SecTrustServer.c, "user trust settings overrule admin trust settings",
// so take the last trust settings array we find.
// Skip the system domain since it is always trusted.
for (int k = 1; k < numDomains; k++) {
CFArrayRef domainTrustSettings = NULL;
err = SecTrustSettingsCopyTrustSettings(cert, domains[k], &domainTrustSettings);
if (err == errSecSuccess && domainTrustSettings != NULL) {
if (trustSettings) {
CFRelease(trustSettings);
}
trustSettings = domainTrustSettings;
}
}
if (trustSettings == NULL) {
// "this certificate must be verified to a known trusted certificate"; aka not a root.
continue;
}
for (CFIndex k = 0; k < CFArrayGetCount(trustSettings); k++) {
CFNumberRef cfNum;
CFDictionaryRef tSetting = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, k);
if (CFDictionaryGetValueIfPresent(tSetting, policy, (const void**)&cfNum)){
SInt32 result = 0;
CFNumberGetValue(cfNum, kCFNumberSInt32Type, &result);
// TODO: The rest of the dictionary specifies conditions for evaluation.
if (result == kSecTrustSettingsResultDeny) {
untrusted = 1;
}
}
}
CFRelease(trustSettings);
}
// We only want to add Root CAs, so make sure Subject and Issuer Name match
CFDataRef subjectName = SecCertificateCopyNormalizedSubjectContent(cert, &errRef);
if (errRef != NULL) {
@@ -138,13 +185,16 @@ int FetchPEMRoots(CFDataRef *pemRoots) {
}
if (data != NULL) {
CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
CFMutableDataRef appendTo = untrusted ? combinedUntrustedData : combinedData;
CFDataAppendBytes(appendTo, CFDataGetBytePtr(data), CFDataGetLength(data));
CFRelease(data);
}
}
CFRelease(certs);
}
CFRelease(policy);
*pemRoots = combinedData;
*untrustedPemRoots = combinedUntrustedData;
return 0;
}
*/
@@ -158,7 +208,8 @@ func loadSystemRoots() (*CertPool, error) {
roots := NewCertPool()
var data C.CFDataRef = nil
err := C.FetchPEMRoots(&data)
var untrustedData C.CFDataRef = nil
err := C.FetchPEMRoots(&data, &untrustedData)
if err == -1 {
// TODO: better error message
return nil, errors.New("crypto/x509: failed to load darwin system roots with cgo")
@@ -167,5 +218,19 @@ func loadSystemRoots() (*CertPool, error) {
defer C.CFRelease(C.CFTypeRef(data))
buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
roots.AppendCertsFromPEM(buf)
return roots, nil
if untrustedData == nil {
return roots, nil
}
defer C.CFRelease(C.CFTypeRef(untrustedData))
buf = C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(untrustedData)), C.int(C.CFDataGetLength(untrustedData)))
untrustedRoots := NewCertPool()
untrustedRoots.AppendCertsFromPEM(buf)
trustedRoots := NewCertPool()
for _, c := range roots.certs {
if !untrustedRoots.contains(c) {
trustedRoots.AddCert(c)
}
}
return trustedRoots, nil
}

View File

@@ -6,20 +6,239 @@
package x509
import "os/exec"
import (
"bufio"
"bytes"
"crypto/sha1"
"encoding/pem"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
)
var debugExecDarwinRoots = strings.Contains(os.Getenv("GODEBUG"), "x509roots=1")
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
return nil, nil
}
// This code is only used when compiling without cgo.
// It is here, instead of root_nocgo_darwin.go, so that tests can check it
// even if the tests are run with cgo enabled.
// The linker will not include these unused functions in binaries built with cgo enabled.
// execSecurityRoots finds the macOS list of trusted root certificates
// using only command-line tools. This is our fallback path when cgo isn't available.
//
// The strategy is as follows:
//
// 1. Run "security trust-settings-export" and "security
// trust-settings-export -d" to discover the set of certs with some
// user-tweaked trust policy. We're too lazy to parse the XML (at
// least at this stage of Go 1.8) to understand what the trust
// policy actually is. We just learn that there is _some_ policy.
//
// 2. Run "security find-certificate" to dump the list of system root
// CAs in PEM format.
//
// 3. For each dumped cert, conditionally verify it with "security
// verify-cert" if that cert was in the set discovered in Step 1.
// Without the Step 1 optimization, running "security verify-cert"
// 150-200 times takes 3.5 seconds. With the optimization, the
// whole process takes about 180 milliseconds with 1 untrusted root
// CA. (Compared to 110ms in the cgo path)
func execSecurityRoots() (*CertPool, error) {
hasPolicy, err := getCertsWithTrustPolicy()
if err != nil {
return nil, err
}
if debugExecDarwinRoots {
println(fmt.Sprintf("crypto/x509: %d certs have a trust policy", len(hasPolicy)))
}
cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain")
data, err := cmd.Output()
if err != nil {
return nil, err
}
roots := NewCertPool()
roots.AppendCertsFromPEM(data)
var (
mu sync.Mutex
roots = NewCertPool()
numVerified int // number of execs of 'security verify-cert', for debug stats
)
blockCh := make(chan *pem.Block)
var wg sync.WaitGroup
// Using 4 goroutines to pipe into verify-cert seems to be
// about the best we can do. The verify-cert binary seems to
// just RPC to another server with coarse locking anyway, so
// running 16 at a time for instance doesn't help at all. Due
// to the "if hasPolicy" check below, though, we will rarely
// (or never) call verify-cert on stock macOS systems, though.
// The hope is that we only call verify-cert when the user has
// tweaked their trust poliy. These 4 goroutines are only
// defensive in the pathological case of many trust edits.
for i := 0; i < 4; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for block := range blockCh {
cert, err := ParseCertificate(block.Bytes)
if err != nil {
continue
}
sha1CapHex := fmt.Sprintf("%X", sha1.Sum(block.Bytes))
valid := true
verifyChecks := 0
if hasPolicy[sha1CapHex] {
verifyChecks++
if !verifyCertWithSystem(block, cert) {
valid = false
}
}
mu.Lock()
numVerified += verifyChecks
if valid {
roots.AddCert(cert)
}
mu.Unlock()
}
}()
}
for len(data) > 0 {
var block *pem.Block
block, data = pem.Decode(data)
if block == nil {
break
}
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
continue
}
blockCh <- block
}
close(blockCh)
wg.Wait()
if debugExecDarwinRoots {
mu.Lock()
defer mu.Unlock()
println(fmt.Sprintf("crypto/x509: ran security verify-cert %d times", numVerified))
}
return roots, nil
}
func verifyCertWithSystem(block *pem.Block, cert *Certificate) bool {
data := pem.EncodeToMemory(block)
f, err := ioutil.TempFile("", "cert")
if err != nil {
fmt.Fprintf(os.Stderr, "can't create temporary file for cert: %v", err)
return false
}
defer os.Remove(f.Name())
if _, err := f.Write(data); err != nil {
fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
return false
}
if err := f.Close(); err != nil {
fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
return false
}
cmd := exec.Command("/usr/bin/security", "verify-cert", "-c", f.Name(), "-l", "-L")
var stderr bytes.Buffer
if debugExecDarwinRoots {
cmd.Stderr = &stderr
}
if err := cmd.Run(); err != nil {
if debugExecDarwinRoots {
println(fmt.Sprintf("crypto/x509: verify-cert rejected %s: %q", cert.Subject.CommonName, bytes.TrimSpace(stderr.Bytes())))
}
return false
}
if debugExecDarwinRoots {
println(fmt.Sprintf("crypto/x509: verify-cert approved %s", cert.Subject.CommonName))
}
return true
}
// getCertsWithTrustPolicy returns the set of certs that have a
// possibly-altered trust policy. The keys of the map are capitalized
// sha1 hex of the raw cert.
// They are the certs that should be checked against `security
// verify-cert` to see whether the user altered the default trust
// settings. This code is only used for cgo-disabled builds.
func getCertsWithTrustPolicy() (map[string]bool, error) {
set := map[string]bool{}
td, err := ioutil.TempDir("", "x509trustpolicy")
if err != nil {
return nil, err
}
defer os.RemoveAll(td)
run := func(file string, args ...string) error {
file = filepath.Join(td, file)
args = append(args, file)
cmd := exec.Command("/usr/bin/security", args...)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
// If there are no trust settings, the
// `security trust-settings-export` command
// fails with:
// exit status 1, SecTrustSettingsCreateExternalRepresentation: No Trust Settings were found.
// Rather than match on English substrings that are probably localized
// on macOS, just treat interpret any failure as meaning that there are
// no trust settings.
if debugExecDarwinRoots {
println(fmt.Sprintf("crypto/x509: exec %q: %v, %s", cmd.Args, err, stderr.Bytes()))
}
return nil
}
f, err := os.Open(file)
if err != nil {
return err
}
defer f.Close()
// Gather all the runs of 40 capitalized hex characters.
br := bufio.NewReader(f)
var hexBuf bytes.Buffer
for {
b, err := br.ReadByte()
isHex := ('A' <= b && b <= 'F') || ('0' <= b && b <= '9')
if isHex {
hexBuf.WriteByte(b)
} else {
if hexBuf.Len() == 40 {
set[hexBuf.String()] = true
}
hexBuf.Reset()
}
if err == io.EOF {
break
}
if err != nil {
return err
}
}
return nil
}
if err := run("user", "trust-settings-export"); err != nil {
return nil, fmt.Errorf("dump-trust-settings (user): %v", err)
}
if err := run("admin", "trust-settings-export", "-d"); err != nil {
return nil, fmt.Errorf("dump-trust-settings (admin): %v", err)
}
return set, nil
}

View File

@@ -7,6 +7,7 @@ package x509
import (
"runtime"
"testing"
"time"
)
func TestSystemRoots(t *testing.T) {
@@ -15,13 +16,21 @@ func TestSystemRoots(t *testing.T) {
t.Skipf("skipping on %s/%s, no system root", runtime.GOOS, runtime.GOARCH)
}
sysRoots := systemRootsPool() // actual system roots
t0 := time.Now()
sysRoots := systemRootsPool() // actual system roots
sysRootsDuration := time.Since(t0)
t1 := time.Now()
execRoots, err := execSecurityRoots() // non-cgo roots
execSysRootsDuration := time.Since(t1)
if err != nil {
t.Fatalf("failed to read system roots: %v", err)
}
t.Logf(" cgo sys roots: %v", sysRootsDuration)
t.Logf("non-cgo sys roots: %v", execSysRootsDuration)
for _, tt := range []*CertPool{sysRoots, execRoots} {
if tt == nil {
t.Fatal("no system roots")
@@ -29,6 +38,7 @@ func TestSystemRoots(t *testing.T) {
// On Mavericks, there are 212 bundled certs; require only
// 150 here, since this is just a sanity check, and the
// exact number will vary over time.
t.Logf("got %d roots", len(tt.certs))
if want, have := 150, len(tt.certs); have < want {
t.Fatalf("want at least %d system roots, have %d", want, have)
}

View File

@@ -4,14 +4,9 @@
package crc32
import (
"unsafe"
)
const (
vxMinLen = 64
vxAlignment = 16
vxAlignMask = vxAlignment - 1
vxAlignMask = 15 // align to 16 bytes
)
// hasVectorFacility reports whether the machine has the z/Architecture
@@ -49,20 +44,13 @@ func genericIEEE(crc uint32, p []byte) uint32 {
return update(crc, IEEETable, p)
}
// updateCastagnoli calculates the checksum of p using genericCastagnoli to
// align the data appropriately for vectorCastagnoli. It avoids using
// vectorCastagnoli entirely if the length of p is less than or equal to
// vxMinLen.
// updateCastagnoli calculates the checksum of p using
// vectorizedCastagnoli if possible and falling back onto
// genericCastagnoli as needed.
func updateCastagnoli(crc uint32, p []byte) uint32 {
// Use vectorized function if vector facility is available and
// data length is above threshold.
if hasVX && len(p) > vxMinLen {
pAddr := uintptr(unsafe.Pointer(&p[0]))
if pAddr&vxAlignMask != 0 {
prealign := vxAlignment - int(pAddr&vxAlignMask)
crc = genericCastagnoli(crc, p[:prealign])
p = p[prealign:]
}
if hasVX && len(p) >= vxMinLen {
aligned := len(p) & ^vxAlignMask
crc = vectorizedCastagnoli(crc, p[:aligned])
p = p[aligned:]
@@ -75,19 +63,12 @@ func updateCastagnoli(crc uint32, p []byte) uint32 {
return genericCastagnoli(crc, p)
}
// updateIEEE calculates the checksum of p using genericIEEE to align the data
// appropriately for vectorIEEE. It avoids using vectorIEEE entirely if the length
// of p is less than or equal to vxMinLen.
// updateIEEE calculates the checksum of p using vectorizedIEEE if
// possible and falling back onto genericIEEE as needed.
func updateIEEE(crc uint32, p []byte) uint32 {
// Use vectorized function if vector facility is available and
// data length is above threshold.
if hasVX && len(p) > vxMinLen {
pAddr := uintptr(unsafe.Pointer(&p[0]))
if pAddr&vxAlignMask != 0 {
prealign := vxAlignment - int(pAddr&vxAlignMask)
crc = genericIEEE(crc, p[:prealign])
p = p[prealign:]
}
if hasVX && len(p) >= vxMinLen {
aligned := len(p) & ^vxAlignMask
crc = vectorizedIEEE(crc, p[:aligned])
p = p[aligned:]

View File

@@ -128,6 +128,10 @@ TEXT vectorizedBody<>(SB),NOSPLIT,$0
VZERO V0
VLVGF $3, R2, V0
// Crash if the input size is less than 64-bytes.
CMP R4, $64
BLT crash
// Load a 64-byte data chunk and XOR with CRC
VLM 0(R3), V1, V4 // 64-bytes into V1..V4
@@ -243,3 +247,6 @@ done:
XOR $0xffffffff, R2 // NOTW R2
MOVWZ R2, ret + 32(FP)
RET
crash:
MOVD $0, (R0) // input size is less than 64-bytes

View File

@@ -18,15 +18,16 @@ func (mr *multiReader) Read(p []byte) (n int, err error) {
}
}
n, err = mr.readers[0].Read(p)
if err == EOF {
mr.readers = mr.readers[1:]
}
if n > 0 || err != EOF {
if err == EOF {
// Don't return EOF yet. There may be more bytes
// in the remaining readers.
if err == EOF && len(mr.readers) > 0 {
// Don't return EOF yet. More readers remain.
err = nil
}
return
}
mr.readers = mr.readers[1:]
}
return 0, EOF
}

View File

@@ -196,3 +196,41 @@ func TestMultiReaderFlatten(t *testing.T) {
myDepth+2, readDepth)
}
}
// byteAndEOFReader is a Reader which reads one byte (the underlying
// byte) and io.EOF at once in its Read call.
type byteAndEOFReader byte
func (b byteAndEOFReader) Read(p []byte) (n int, err error) {
if len(p) == 0 {
// Read(0 bytes) is useless. We expect no such useless
// calls in this test.
panic("unexpected call")
}
p[0] = byte(b)
return 1, EOF
}
// In Go 1.7, this yielded bytes forever.
func TestMultiReaderSingleByteWithEOF(t *testing.T) {
got, err := ioutil.ReadAll(LimitReader(MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10))
if err != nil {
t.Fatal(err)
}
const want = "ab"
if string(got) != want {
t.Errorf("got %q; want %q", got, want)
}
}
// Test that a reader returning (n, EOF) at the end of an MultiReader
// chain continues to return EOF on its final read, rather than
// yielding a (0, EOF).
func TestMultiReaderFinalEOF(t *testing.T) {
r := MultiReader(bytes.NewReader(nil), byteAndEOFReader('a'))
buf := make([]byte, 2)
n, err := r.Read(buf)
if n != 1 || err != EOF {
t.Errorf("got %v, %v; want 1, EOF", n, err)
}
}

View File

@@ -79,8 +79,10 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
if err != nil {
return nil, err
}
defer file.Close()
_, err = io.Copy(file, io.MultiReader(&b, p))
if cerr := file.Close(); err == nil {
err = cerr
}
if err != nil {
os.Remove(file.Name())
return nil, err

View File

@@ -141,7 +141,7 @@ func (d *Dialer) dialDNS(ctx context.Context, network, server string) (dnsConn,
}
// exchange sends a query on the connection and hopes for a response.
func exchange(ctx context.Context, server, name string, qtype uint16) (*dnsMsg, error) {
func exchange(ctx context.Context, server, name string, qtype uint16, timeout time.Duration) (*dnsMsg, error) {
d := testHookDNSDialer()
out := dnsMsg{
dnsMsgHdr: dnsMsgHdr{
@@ -152,6 +152,12 @@ func exchange(ctx context.Context, server, name string, qtype uint16) (*dnsMsg,
},
}
for _, network := range []string{"udp", "tcp"} {
// TODO(mdempsky): Refactor so defers from UDP-based
// exchanges happen before TCP-based exchange.
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(timeout))
defer cancel()
c, err := d.dialDNS(ctx, network, server)
if err != nil {
return nil, err
@@ -180,17 +186,10 @@ func tryOneName(ctx context.Context, cfg *dnsConfig, name string, qtype uint16)
return "", nil, &DNSError{Err: "no DNS servers", Name: name}
}
deadline := time.Now().Add(cfg.timeout)
if old, ok := ctx.Deadline(); !ok || deadline.Before(old) {
var cancel context.CancelFunc
ctx, cancel = context.WithDeadline(ctx, deadline)
defer cancel()
}
var lastErr error
for i := 0; i < cfg.attempts; i++ {
for _, server := range cfg.servers {
msg, err := exchange(ctx, server, name, qtype)
msg, err := exchange(ctx, server, name, qtype, cfg.timeout)
if err != nil {
lastErr = &DNSError{
Err: err.Error(),
@@ -338,8 +337,9 @@ func lookup(ctx context.Context, name string, qtype uint16) (cname string, rrs [
}
// avoidDNS reports whether this is a hostname for which we should not
// use DNS. Currently this includes only .onion and .local names,
// per RFC 7686 and RFC 6762, respectively. See golang.org/issue/13705.
// use DNS. Currently this includes only .onion, per RFC 7686. See
// golang.org/issue/13705. Does not cover .local names (RFC 6762),
// see golang.org/issue/16739.
func avoidDNS(name string) bool {
if name == "" {
return true
@@ -347,7 +347,7 @@ func avoidDNS(name string) bool {
if name[len(name)-1] == '.' {
name = name[:len(name)-1]
}
return stringsHasSuffixFold(name, ".onion") || stringsHasSuffixFold(name, ".local")
return stringsHasSuffixFold(name, ".onion")
}
// nameList returns a list of names for sequential DNS queries.

View File

@@ -40,9 +40,9 @@ func TestDNSTransportFallback(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
for _, tt := range dnsTransportFallbackTests {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(tt.timeout)*time.Second)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
msg, err := exchange(ctx, tt.server, tt.name, tt.qtype)
msg, err := exchange(ctx, tt.server, tt.name, tt.qtype, time.Second)
if err != nil {
t.Error(err)
continue
@@ -82,9 +82,9 @@ func TestSpecialDomainName(t *testing.T) {
server := "8.8.8.8:53"
for _, tt := range specialDomainNameTests {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
msg, err := exchange(ctx, server, tt.name, tt.qtype)
msg, err := exchange(ctx, server, tt.name, tt.qtype, 3*time.Second)
if err != nil {
t.Error(err)
continue
@@ -112,10 +112,11 @@ func TestAvoidDNSName(t *testing.T) {
{"foo.ONION", true},
{"foo.ONION.", true},
{"foo.local.", true},
{"foo.local", true},
{"foo.LOCAL", true},
{"foo.LOCAL.", true},
// But do resolve *.local address; Issue 16739
{"foo.local.", false},
{"foo.local", false},
{"foo.LOCAL", false},
{"foo.LOCAL.", false},
{"", true}, // will be rejected earlier too
@@ -500,7 +501,7 @@ func TestErrorForOriginalNameWhenSearching(t *testing.T) {
d := &fakeDNSDialer{}
testHookDNSDialer = func() dnsDialer { return d }
d.rh = func(s string, q *dnsMsg) (*dnsMsg, error) {
d.rh = func(s string, q *dnsMsg, _ time.Time) (*dnsMsg, error) {
r := &dnsMsg{
dnsMsgHdr: dnsMsgHdr{
id: q.id,
@@ -539,14 +540,15 @@ func TestIgnoreLameReferrals(t *testing.T) {
}
defer conf.teardown()
if err := conf.writeAndUpdate([]string{"nameserver 192.0.2.1", "nameserver 192.0.2.2"}); err != nil {
if err := conf.writeAndUpdate([]string{"nameserver 192.0.2.1", // the one that will give a lame referral
"nameserver 192.0.2.2"}); err != nil {
t.Fatal(err)
}
d := &fakeDNSDialer{}
testHookDNSDialer = func() dnsDialer { return d }
d.rh = func(s string, q *dnsMsg) (*dnsMsg, error) {
d.rh = func(s string, q *dnsMsg, _ time.Time) (*dnsMsg, error) {
t.Log(s, q)
r := &dnsMsg{
dnsMsgHdr: dnsMsgHdr{
@@ -633,28 +635,30 @@ func BenchmarkGoLookupIPWithBrokenNameServer(b *testing.B) {
type fakeDNSDialer struct {
// reply handler
rh func(s string, q *dnsMsg) (*dnsMsg, error)
rh func(s string, q *dnsMsg, t time.Time) (*dnsMsg, error)
}
func (f *fakeDNSDialer) dialDNS(_ context.Context, n, s string) (dnsConn, error) {
return &fakeDNSConn{f.rh, s}, nil
return &fakeDNSConn{f.rh, s, time.Time{}}, nil
}
type fakeDNSConn struct {
rh func(s string, q *dnsMsg) (*dnsMsg, error)
rh func(s string, q *dnsMsg, t time.Time) (*dnsMsg, error)
s string
t time.Time
}
func (f *fakeDNSConn) Close() error {
return nil
}
func (f *fakeDNSConn) SetDeadline(time.Time) error {
func (f *fakeDNSConn) SetDeadline(t time.Time) error {
f.t = t
return nil
}
func (f *fakeDNSConn) dnsRoundTrip(q *dnsMsg) (*dnsMsg, error) {
return f.rh(f.s, q)
return f.rh(f.s, q, f.t)
}
// UDP round-tripper algorithm should ignore invalid DNS responses (issue 13281).
@@ -724,3 +728,72 @@ func TestIgnoreDNSForgeries(t *testing.T) {
t.Errorf("got address %v, want %v", got, TestAddr)
}
}
// Issue 16865. If a name server times out, continue to the next.
func TestRetryTimeout(t *testing.T) {
origTestHookDNSDialer := testHookDNSDialer
defer func() { testHookDNSDialer = origTestHookDNSDialer }()
conf, err := newResolvConfTest()
if err != nil {
t.Fatal(err)
}
defer conf.teardown()
if err := conf.writeAndUpdate([]string{"nameserver 192.0.2.1", // the one that will timeout
"nameserver 192.0.2.2"}); err != nil {
t.Fatal(err)
}
d := &fakeDNSDialer{}
testHookDNSDialer = func() dnsDialer { return d }
var deadline0 time.Time
d.rh = func(s string, q *dnsMsg, deadline time.Time) (*dnsMsg, error) {
t.Log(s, q, deadline)
if deadline.IsZero() {
t.Error("zero deadline")
}
if s == "192.0.2.1:53" {
deadline0 = deadline
time.Sleep(10 * time.Millisecond)
return nil, errTimeout
}
if deadline == deadline0 {
t.Error("deadline didn't change")
}
r := &dnsMsg{
dnsMsgHdr: dnsMsgHdr{
id: q.id,
response: true,
recursion_available: true,
},
question: q.question,
answer: []dnsRR{
&dnsRR_CNAME{
Hdr: dnsRR_Header{
Name: q.question[0].Name,
Rrtype: dnsTypeCNAME,
Class: dnsClassINET,
},
Cname: "golang.org",
},
},
}
return r, nil
}
_, err = goLookupCNAME(context.Background(), "www.golang.org")
if err != nil {
t.Fatal(err)
}
if deadline0.IsZero() {
t.Error("deadline0 still zero", deadline0)
}
}

View File

@@ -468,7 +468,7 @@ func TestH12_RequestContentLength_Known_NonZero(t *testing.T) {
}
func TestH12_RequestContentLength_Known_Zero(t *testing.T) {
h12requestContentLength(t, func() io.Reader { return strings.NewReader("") }, 0)
h12requestContentLength(t, func() io.Reader { return nil }, 0)
}
func TestH12_RequestContentLength_Unknown(t *testing.T) {

View File

@@ -1,5 +1,5 @@
// Code generated by golang.org/x/tools/cmd/bundle.
//go:generate bundle -o h2_bundle.go -prefix http2 golang.org/x/net/http2
//go:generate bundle -o h2_bundle.go -prefix http2 -underscore golang.org/x/net/http2
// Package http2 implements the HTTP/2 protocol.
//
@@ -5448,28 +5448,17 @@ func http2checkConnHeaders(req *Request) error {
return nil
}
func http2bodyAndLength(req *Request) (body io.Reader, contentLen int64) {
body = req.Body
if body == nil {
return nil, 0
// actualContentLength returns a sanitized version of
// req.ContentLength, where 0 actually means zero (not unknown) and -1
// means unknown.
func http2actualContentLength(req *Request) int64 {
if req.Body == nil {
return 0
}
if req.ContentLength != 0 {
return req.Body, req.ContentLength
return req.ContentLength
}
// We have a body but a zero content length. Test to see if
// it's actually zero or just unset.
var buf [1]byte
n, rerr := io.ReadFull(body, buf[:])
if rerr != nil && rerr != io.EOF {
return http2errorReader{rerr}, -1
}
if n == 1 {
return io.MultiReader(bytes.NewReader(buf[:]), body), -1
}
return nil, 0
return -1
}
func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
@@ -5483,9 +5472,6 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
}
hasTrailers := trailers != ""
body, contentLen := http2bodyAndLength(req)
hasBody := body != nil
cc.mu.Lock()
cc.lastActive = time.Now()
if cc.closed || !cc.canTakeNewRequestLocked() {
@@ -5493,6 +5479,10 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
return nil, http2errClientConnUnusable
}
body := req.Body
hasBody := body != nil
contentLen := http2actualContentLength(req)
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
var requestedGzip bool
if !cc.t.disableCompression() &&
@@ -5714,8 +5704,13 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos
}
}
if sentEnd {
return nil
}
var trls []byte
if !sentEnd && hasTrailers {
if hasTrailers {
cc.mu.Lock()
defer cc.mu.Unlock()
trls = cc.encodeTrailers(req)

View File

@@ -498,8 +498,9 @@ func (t *Transport) CloseIdleConnections() {
// CancelRequest cancels an in-flight request by closing its connection.
// CancelRequest should only be called after RoundTrip has returned.
//
// Deprecated: Use Request.Cancel instead. CancelRequest cannot cancel
// HTTP/2 requests.
// Deprecated: Use Request.WithContext to create a request with a
// cancelable context instead. CancelRequest cannot cancel HTTP/2
// requests.
func (t *Transport) CancelRequest(req *Request) {
t.reqMu.Lock()
cancel := t.reqCanceler[req]
@@ -589,6 +590,7 @@ var (
errReadLoopExiting = errors.New("http: persistConn.readLoop exiting")
errServerClosedIdle = errors.New("http: server closed idle connection")
errIdleConnTimeout = errors.New("http: idle connection timeout")
errNotCachingH2Conn = errors.New("http: not caching alternate protocol's connections")
)
// transportReadFromServerError is used by Transport.readLoop when the
@@ -632,6 +634,9 @@ func (t *Transport) tryPutIdleConn(pconn *persistConn) error {
if pconn.isBroken() {
return errConnBroken
}
if pconn.alt != nil {
return errNotCachingH2Conn
}
pconn.markReused()
key := pconn.cacheKey

View File

@@ -3511,6 +3511,61 @@ func TestTransportIdleConnTimeout(t *testing.T) {
}
}
// Issue 16208: Go 1.7 crashed after Transport.IdleConnTimeout if an
// HTTP/2 connection was established but but its caller no longer
// wanted it. (Assuming the connection cache was enabled, which it is
// by default)
//
// This test reproduced the crash by setting the IdleConnTimeout low
// (to make the test reasonable) and then making a request which is
// canceled by the DialTLS hook, which then also waits to return the
// real connection until after the RoundTrip saw the error. Then we
// know the successful tls.Dial from DialTLS will need to go into the
// idle pool. Then we give it a of time to explode.
func TestIdleConnH2Crash(t *testing.T) {
cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
// nothing
}))
defer cst.close()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
gotErr := make(chan bool, 1)
cst.tr.IdleConnTimeout = 5 * time.Millisecond
cst.tr.DialTLS = func(network, addr string) (net.Conn, error) {
cancel()
<-gotErr
c, err := tls.Dial(network, addr, &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"h2"},
})
if err != nil {
t.Error(err)
return nil, err
}
if cs := c.ConnectionState(); cs.NegotiatedProtocol != "h2" {
t.Errorf("protocol = %q; want %q", cs.NegotiatedProtocol, "h2")
c.Close()
return nil, errors.New("bogus")
}
return c, nil
}
req, _ := NewRequest("GET", cst.ts.URL, nil)
req = req.WithContext(ctx)
res, err := cst.c.Do(req)
if err == nil {
res.Body.Close()
t.Fatal("unexpected success")
}
gotErr <- true
// Wait for the explosion.
time.Sleep(cst.tr.IdleConnTimeout * 10)
}
type funcConn struct {
net.Conn
read func([]byte) (int, error)

View File

@@ -4,4 +4,7 @@
package filepath
var ToNorm = toNorm
var (
ToNorm = toNorm
NormBase = normBase
)

View File

@@ -840,7 +840,7 @@ func TestEvalSymlinks(t *testing.T) {
if p, err := filepath.EvalSymlinks(path); err != nil {
t.Errorf("EvalSymlinks(%q) error: %v", d.path, err)
} else if filepath.Clean(p) != filepath.Clean(dest) {
t.Errorf("Clean(%q)=%q, want %q", path, p, dest)
t.Errorf("EvalSymlinks(%q)=%q, want %q", path, p, dest)
}
// test EvalSymlinks(".")
@@ -872,6 +872,34 @@ func TestEvalSymlinks(t *testing.T) {
t.Errorf(`EvalSymlinks(".") in %q directory returns %q, want "." or %q`, d.path, p, want)
}()
// test EvalSymlinks(".."+path)
func() {
defer func() {
err := os.Chdir(wd)
if err != nil {
t.Fatal(err)
}
}()
err := os.Chdir(simpleJoin(tmpDir, "test"))
if err != nil {
t.Error(err)
return
}
path := simpleJoin("..", d.path)
dest := simpleJoin("..", d.dest)
if filepath.IsAbs(d.dest) || os.IsPathSeparator(d.dest[0]) {
dest = d.dest
}
if p, err := filepath.EvalSymlinks(path); err != nil {
t.Errorf("EvalSymlinks(%q) error: %v", d.path, err)
} else if filepath.Clean(p) != filepath.Clean(dest) {
t.Errorf("EvalSymlinks(%q)=%q, want %q", path, p, dest)
}
}()
// test EvalSymlinks where parameter is relative path
func() {
defer func() {
@@ -889,7 +917,7 @@ func TestEvalSymlinks(t *testing.T) {
if p, err := filepath.EvalSymlinks(d.path); err != nil {
t.Errorf("EvalSymlinks(%q) error: %v", d.path, err)
} else if filepath.Clean(p) != filepath.Clean(d.dest) {
t.Errorf("Clean(%q)=%q, want %q", d.path, p, d.dest)
t.Errorf("EvalSymlinks(%q)=%q, want %q", d.path, p, d.dest)
}
}()
}

View File

@@ -329,9 +329,106 @@ func TestToNorm(t *testing.T) {
for _, test := range tests {
got, err := filepath.ToNorm(test.arg, stubBase)
if err != nil {
t.Errorf("unexpected toNorm error, arg: %s, err: %v\n", test.arg, err)
t.Errorf("toNorm(%s) failed: %v\n", test.arg, err)
} else if got != test.want {
t.Errorf("toNorm error, arg: %s, want: %s, got: %s\n", test.arg, test.want, got)
t.Errorf("toNorm(%s) returns %s, but %s expected\n", test.arg, got, test.want)
}
}
testPath := `{{tmp}}\test\foo\bar`
testsDir := []struct {
wd string
arg string
want string
}{
// test absolute paths
{".", `{{tmp}}\test\foo\bar`, `{{tmp}}\test\foo\bar`},
{".", `{{tmp}}\.\test/foo\bar`, `{{tmp}}\test\foo\bar`},
{".", `{{tmp}}\test\..\test\foo\bar`, `{{tmp}}\test\foo\bar`},
{".", `{{tmp}}\TEST\FOO\BAR`, `{{tmp}}\test\foo\bar`},
// test relative paths begin with drive letter
{`{{tmp}}\test`, `{{tmpvol}}.`, `{{tmpvol}}.`},
{`{{tmp}}\test`, `{{tmpvol}}..`, `{{tmpvol}}..`},
{`{{tmp}}\test`, `{{tmpvol}}foo\bar`, `{{tmpvol}}foo\bar`},
{`{{tmp}}\test`, `{{tmpvol}}.\foo\bar`, `{{tmpvol}}foo\bar`},
{`{{tmp}}\test`, `{{tmpvol}}foo\..\foo\bar`, `{{tmpvol}}foo\bar`},
{`{{tmp}}\test`, `{{tmpvol}}FOO\BAR`, `{{tmpvol}}foo\bar`},
// test relative paths begin with '\'
{".", `{{tmpnovol}}\test\foo\bar`, `{{tmpnovol}}\test\foo\bar`},
{".", `{{tmpnovol}}\.\test\foo\bar`, `{{tmpnovol}}\test\foo\bar`},
{".", `{{tmpnovol}}\test\..\test\foo\bar`, `{{tmpnovol}}\test\foo\bar`},
{".", `{{tmpnovol}}\TEST\FOO\BAR`, `{{tmpnovol}}\test\foo\bar`},
// test relative paths begin without '\'
{`{{tmp}}\test`, ".", `.`},
{`{{tmp}}\test`, "..", `..`},
{`{{tmp}}\test`, `foo\bar`, `foo\bar`},
{`{{tmp}}\test`, `.\foo\bar`, `foo\bar`},
{`{{tmp}}\test`, `foo\..\foo\bar`, `foo\bar`},
{`{{tmp}}\test`, `FOO\BAR`, `foo\bar`},
}
cwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
defer func() {
err := os.Chdir(cwd)
if err != nil {
t.Fatal(err)
}
}()
tmp, err := ioutil.TempDir("", "testToNorm")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmp)
// ioutil.TempDir might return "non-canonical" name.
tmp, err = filepath.EvalSymlinks(tmp)
if err != nil {
t.Fatal(err)
}
err = os.MkdirAll(strings.Replace(testPath, "{{tmp}}", tmp, -1), 0777)
if err != nil {
t.Fatal(err)
}
tmpVol := filepath.VolumeName(tmp)
tmpNoVol := tmp[len(tmpVol):]
for _, test := range testsDir {
wd := strings.Replace(strings.Replace(strings.Replace(test.wd, "{{tmp}}", tmp, -1), "{{tmpvol}}", tmpVol, -1), "{{tmpnovol}}", tmpNoVol, -1)
arg := strings.Replace(strings.Replace(strings.Replace(test.arg, "{{tmp}}", tmp, -1), "{{tmpvol}}", tmpVol, -1), "{{tmpnovol}}", tmpNoVol, -1)
want := strings.Replace(strings.Replace(strings.Replace(test.want, "{{tmp}}", tmp, -1), "{{tmpvol}}", tmpVol, -1), "{{tmpnovol}}", tmpNoVol, -1)
if test.wd == "." {
err := os.Chdir(cwd)
if err != nil {
t.Error(err)
continue
}
} else {
err := os.Chdir(wd)
if err != nil {
t.Error(err)
continue
}
}
got, err := filepath.ToNorm(arg, filepath.NormBase)
if err != nil {
t.Errorf("toNorm(%s) failed: %v (wd=%s)\n", arg, err, wd)
} else if got != want {
t.Errorf("toNorm(%s) returns %s, but %s expected (wd=%s)\n", arg, got, want, wd)
}
}
}

View File

@@ -22,7 +22,7 @@ func normVolumeName(path string) string {
return strings.ToUpper(volume)
}
// normBase retruns the last element of path.
// normBase returns the last element of path with correct case.
func normBase(path string) (string, error) {
p, err := syscall.UTF16PtrFromString(path)
if err != nil {
@@ -40,7 +40,24 @@ func normBase(path string) (string, error) {
return syscall.UTF16ToString(data.FileName[:]), nil
}
func toNorm(path string, base func(string) (string, error)) (string, error) {
// baseIsDotDot returns whether the last element of path is "..".
// The given path should be 'Clean'-ed in advance.
func baseIsDotDot(path string) bool {
i := strings.LastIndexByte(path, Separator)
return path[i+1:] == ".."
}
// toNorm returns the normalized path that is guranteed to be unique.
// It should accept the following formats:
// * UNC paths (e.g \\server\share\foo\bar)
// * absolute paths (e.g C:\foo\bar)
// * relative paths begin with drive letter (e.g C:foo\bar, C:..\foo\bar, C:.., C:.)
// * relative paths begin with '\' (e.g \foo\bar)
// * relative paths begin without '\' (e.g foo\bar, ..\foo\bar, .., .)
// The returned normalized path will be in the same form (of 5 listed above) as the input path.
// If two paths A and B are indicating the same file with the same format, toNorm(A) should be equal to toNorm(B).
// The normBase parameter should be equal to the normBase func, except for in tests. See docs on the normBase func.
func toNorm(path string, normBase func(string) (string, error)) (string, error) {
if path == "" {
return path, nil
}
@@ -58,7 +75,13 @@ func toNorm(path string, base func(string) (string, error)) (string, error) {
var normPath string
for {
name, err := base(volume + path)
if baseIsDotDot(path) {
normPath = path + `\` + normPath
break
}
name, err := normBase(volume + path)
if err != nil {
return "", err
}

View File

@@ -5720,6 +5720,8 @@ func TestTypeStrings(t *testing.T) {
{TypeOf(new(XM)), "*reflect_test.XM"},
{TypeOf(new(XM).String), "func() string"},
{TypeOf(new(XM)).Method(0).Type, "func(*reflect_test.XM) string"},
{ChanOf(3, TypeOf(XM{})), "chan reflect_test.XM"},
{MapOf(TypeOf(int(0)), TypeOf(XM{})), "map[int]reflect_test.XM"},
}
for i, test := range stringTests {

View File

@@ -70,6 +70,8 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
// word in the passed-in argument frame.
func makeFuncStub()
// This type is partially duplicated as runtime.reflectMethodValue.
// Any changes should be reflected in both.
type methodValue struct {
fn uintptr
stack *bitVector // stack bitmap for args - offset known to runtime

View File

@@ -1848,6 +1848,7 @@ func ChanOf(dir ChanDir, t Type) Type {
prototype := *(**chanType)(unsafe.Pointer(&ichan))
ch := new(chanType)
*ch = *prototype
ch.tflag = 0
ch.dir = uintptr(dir)
ch.str = resolveReflectName(newName(s, "", "", false))
ch.hash = fnv1(typ.hash, 'c', byte(dir))
@@ -1892,6 +1893,7 @@ func MapOf(key, elem Type) Type {
mt := new(mapType)
*mt = **(**mapType)(unsafe.Pointer(&imap))
mt.str = resolveReflectName(newName(s, "", "", false))
mt.tflag = 0
mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
mt.key = ktyp
mt.elem = etyp

View File

@@ -20,6 +20,7 @@ TEXT runtime·checkvectorfacility(SB),NOSPLIT,$32-0
MOVD $2, R0
MOVD R1, tmp-32(SP)
MOVD $x-24(SP), R1
XC $24, 0(R1), 0(R1)
// STFLE 0(R1)
WORD $0xB2B01000
MOVBZ z-8(SP), R1

View File

@@ -23,6 +23,7 @@ package runtime
#include <sys/mman.h>
#include <sys/ucontext.h>
#include <sys/umtx.h>
#include <sys/_umtx.h>
#include <sys/rtprio.h>
#include <sys/thr.h>
#include <sys/_sigset.h>
@@ -49,6 +50,8 @@ const (
SA_RESTART = C.SA_RESTART
SA_ONSTACK = C.SA_ONSTACK
CLOCK_MONOTONIC = C.CLOCK_MONOTONIC
UMTX_OP_WAIT_UINT = C.UMTX_OP_WAIT_UINT
UMTX_OP_WAIT_UINT_PRIVATE = C.UMTX_OP_WAIT_UINT_PRIVATE
UMTX_OP_WAKE = C.UMTX_OP_WAKE
@@ -130,4 +133,6 @@ type Timespec C.struct_timespec
type Timeval C.struct_timeval
type Itimerval C.struct_itimerval
type Umtx_time C.struct__umtx_time
type Kevent C.struct_kevent

View File

@@ -24,6 +24,8 @@ const (
_SA_RESTART = 0x2
_SA_ONSTACK = 0x1
_CLOCK_MONOTONIC = 0x4
_UMTX_OP_WAIT_UINT = 0xb
_UMTX_OP_WAIT_UINT_PRIVATE = 0xf
_UMTX_OP_WAKE = 0x3
@@ -203,6 +205,12 @@ type itimerval struct {
it_value timeval
}
type umtx_time struct {
_timeout timespec
_flags uint32
_clockid uint32
}
type keventt struct {
ident uint32
filter int16

View File

@@ -24,6 +24,8 @@ const (
_SA_RESTART = 0x2
_SA_ONSTACK = 0x1
_CLOCK_MONOTONIC = 0x4
_UMTX_OP_WAIT_UINT = 0xb
_UMTX_OP_WAIT_UINT_PRIVATE = 0xf
_UMTX_OP_WAKE = 0x3
@@ -214,6 +216,12 @@ type itimerval struct {
it_value timeval
}
type umtx_time struct {
_timeout timespec
_flags uint32
_clockid uint32
}
type keventt struct {
ident uint64
filter int16

View File

@@ -24,6 +24,8 @@ const (
_SA_RESTART = 0x2
_SA_ONSTACK = 0x1
_CLOCK_MONOTONIC = 0x4
_UMTX_OP_WAIT_UINT = 0xb
_UMTX_OP_WAIT_UINT_PRIVATE = 0xf
_UMTX_OP_WAKE = 0x3
@@ -176,6 +178,12 @@ type itimerval struct {
it_value timeval
}
type umtx_time struct {
_timeout timespec
_flags uint32
_clockid uint32
}
type keventt struct {
ident uint32
filter int16

View File

@@ -1076,8 +1076,6 @@ top:
// objects reachable from global roots since they don't have write
// barriers. Rescan some roots and flush work caches.
gcMarkRootCheck()
// Disallow caching workbufs and indicate that we're in mark 2.
gcBlackenPromptly = true
@@ -1101,6 +1099,16 @@ top:
})
})
// Check that roots are marked. We should be able to
// do this before the forEachP, but based on issue
// #16083 there may be a (harmless) race where we can
// enter mark 2 while some workers are still scanning
// stacks. The forEachP ensures these scans are done.
//
// TODO(austin): Figure out the race and fix this
// properly.
gcMarkRootCheck()
// Now we can start up mark 2 workers.
atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, 0xffffffff)
atomic.Xaddint64(&gcController.fractionalMarkWorkersNeeded, 0xffffffff)

View File

@@ -106,26 +106,32 @@ func gcMarkRootCheck() {
lock(&allglock)
// Check that stacks have been scanned.
var gp *g
if gcphase == _GCmarktermination {
for i := 0; i < len(allgs); i++ {
gp := allgs[i]
gp = allgs[i]
if !(gp.gcscandone && gp.gcscanvalid) && readgstatus(gp) != _Gdead {
println("gp", gp, "goid", gp.goid,
"status", readgstatus(gp),
"gcscandone", gp.gcscandone,
"gcscanvalid", gp.gcscanvalid)
throw("scan missed a g")
goto fail
}
}
} else {
for i := 0; i < work.nStackRoots; i++ {
gp := allgs[i]
gp = allgs[i]
if !gp.gcscandone {
throw("scan missed a g")
goto fail
}
}
}
unlock(&allglock)
return
fail:
println("gp", gp, "goid", gp.goid,
"status", readgstatus(gp),
"gcscandone", gp.gcscandone,
"gcscanvalid", gp.gcscanvalid)
unlock(&allglock) // Avoid self-deadlock with traceback.
throw("scan missed a g")
}
// ptrmask for an allocation containing a single pointer.

View File

@@ -917,7 +917,9 @@ func scavengelist(list *mSpanList, now, limit uint64) uintptr {
// more memory than we want.)
start = (start + sys.PhysPageSize - 1) &^ (sys.PhysPageSize - 1)
end &^= sys.PhysPageSize - 1
if start == end {
if end <= start {
// start and end don't span a
// whole physical page.
continue
}
}

View File

@@ -35,7 +35,7 @@ func raise(sig int32)
func raiseproc(sig int32)
//go:noescape
func sys_umtx_op(addr *uint32, mode int32, val uint32, ptr2, ts *timespec) int32
func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uintptr, ut *umtx_time) int32
func osyield()
@@ -70,14 +70,14 @@ func futexsleep(addr *uint32, val uint32, ns int64) {
}
func futexsleep1(addr *uint32, val uint32, ns int64) {
var tsp *timespec
var utp *umtx_time
if ns >= 0 {
var ts timespec
ts.tv_nsec = 0
ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
tsp = &ts
var ut umtx_time
ut._clockid = _CLOCK_MONOTONIC
ut._timeout.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ut._timeout.tv_nsec)))))
utp = &ut
}
ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, nil, tsp)
ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, unsafe.Sizeof(*utp), utp)
if ret >= 0 || ret == -_EINTR {
return
}
@@ -87,7 +87,7 @@ func futexsleep1(addr *uint32, val uint32, ns int64) {
//go:nosplit
func futexwakeup(addr *uint32, cnt uint32) {
ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, nil, nil)
ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, 0, nil)
if ret >= 0 {
return
}

View File

@@ -422,8 +422,62 @@ loop:
gp.param = nil
gopark(selparkcommit, nil, "select", traceEvGoBlockSelect, 2)
// someone woke us up
sellock(scases, lockorder)
// While we were asleep, some goroutine came along and completed
// one of the cases in the select and woke us up (called ready).
// As part of that process, the goroutine did a cas on done above
// (aka *sg.selectdone for all queued sg) to win the right to
// complete the select. Now done = 1.
//
// If we copy (grow) our own stack, we will update the
// selectdone pointers inside the gp.waiting sudog list to point
// at the new stack. Another goroutine attempting to
// complete one of our (still linked in) select cases might
// see the new selectdone pointer (pointing at the new stack)
// before the new stack has real data; if the new stack has done = 0
// (before the old values are copied over), the goroutine might
// do a cas via sg.selectdone and incorrectly believe that it has
// won the right to complete the select, executing a second
// communication and attempting to wake us (call ready) again.
//
// Then things break.
//
// The best break is that the goroutine doing ready sees the
// _Gcopystack status and throws, as in #17007.
// A worse break would be for us to continue on, start running real code,
// block in a semaphore acquisition (sema.go), and have the other
// goroutine wake us up without having really acquired the semaphore.
// That would result in the goroutine spuriously running and then
// queue up another spurious wakeup when the semaphore really is ready.
// In general the situation can cascade until something notices the
// problem and causes a crash.
//
// A stack shrink does not have this problem, because it locks
// all the channels that are involved first, blocking out the
// possibility of a cas on selectdone.
//
// A stack growth before gopark above does not have this
// problem, because we hold those channel locks (released by
// selparkcommit).
//
// A stack growth after sellock below does not have this
// problem, because again we hold those channel locks.
//
// The only problem is a stack growth during sellock.
// To keep that from happening, run sellock on the system stack.
//
// It might be that we could avoid this if copystack copied the
// stack before calling adjustsudogs. In that case,
// syncadjustsudogs would need to recopy the tiny part that
// it copies today, resulting in a little bit of extra copying.
//
// An even better fix, not for the week before a release candidate,
// would be to put space in every sudog and make selectdone
// point at (say) the space in the first sudog.
systemstack(func() {
sellock(scases, lockorder)
})
sg = (*sudog)(gp.param)
gp.param = nil
@@ -464,8 +518,15 @@ loop:
}
if cas == nil {
// This can happen if we were woken up by a close().
// TODO: figure that out explicitly so we don't need this loop.
// We can wake up with gp.param == nil (so cas == nil)
// when a channel involved in the select has been closed.
// It is easiest to loop and re-run the operation;
// we'll see that it's now closed.
// Maybe some day we can signal the close explicitly,
// but we'd have to distinguish close-on-reader from close-on-writer.
// It's easiest not to duplicate the code and just recheck above.
// We know that something closed, and things never un-close,
// so we won't block again.
goto loop
}

View File

@@ -14,8 +14,8 @@ TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
MOVQ addr+0(FP), DI
MOVL mode+8(FP), SI
MOVL val+12(FP), DX
MOVQ ptr2+16(FP), R10
MOVQ ts+24(FP), R8
MOVQ uaddr1+16(FP), R10
MOVQ ut+24(FP), R8
MOVL $454, AX
SYSCALL
MOVL AX, ret+32(FP)

View File

@@ -45,7 +45,7 @@ TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
MOVW addr+0(FP), R0
MOVW mode+4(FP), R1
MOVW val+8(FP), R2
MOVW ptr2+12(FP), R3
MOVW uaddr1+12(FP), R3
ADD $20, R13 // arg 5 is passed on stack
MOVW $SYS__umtx_op, R7
SWI $0

View File

@@ -107,7 +107,7 @@ func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v uns
}
frame.fn = f
frame.argp = uintptr(deferArgs(d))
frame.arglen, frame.argmap = getArgInfo(&frame, f, true)
frame.arglen, frame.argmap = getArgInfo(&frame, f, true, fn)
}
frame.continpc = frame.pc
if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) {
@@ -339,7 +339,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
// metadata recorded by f's caller.
if callback != nil || printing {
frame.argp = frame.fp + sys.MinFrameSize
frame.arglen, frame.argmap = getArgInfo(&frame, f, callback != nil)
frame.arglen, frame.argmap = getArgInfo(&frame, f, callback != nil, nil)
}
// Determine frame's 'continuation PC', where it can continue.
@@ -546,19 +546,48 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
return n
}
func getArgInfo(frame *stkframe, f *_func, needArgMap bool) (arglen uintptr, argmap *bitvector) {
// reflectMethodValue is a partial duplicate of reflect.methodValue.
type reflectMethodValue struct {
fn uintptr
stack *bitvector // args bitmap
}
// getArgInfo returns the argument frame information for a call to f
// with call frame frame.
//
// This is used for both actual calls with active stack frames and for
// deferred calls that are not yet executing. If this is an actual
// call, ctxt must be nil (getArgInfo will retrieve what it needs from
// the active stack frame). If this is a deferred call, ctxt must be
// the function object that was deferred.
func getArgInfo(frame *stkframe, f *_func, needArgMap bool, ctxt *funcval) (arglen uintptr, argmap *bitvector) {
arglen = uintptr(f.args)
if needArgMap && f.args == _ArgsSizeUnknown {
// Extract argument bitmaps for reflect stubs from the calls they made to reflect.
switch funcname(f) {
case "reflect.makeFuncStub", "reflect.methodValueCall":
arg0 := frame.sp + sys.MinFrameSize
fn := *(**[2]uintptr)(unsafe.Pointer(arg0))
if fn[0] != f.entry {
// These take a *reflect.methodValue as their
// context register.
var mv *reflectMethodValue
if ctxt != nil {
// This is not an actual call, but a
// deferred call. The function value
// is itself the *reflect.methodValue.
mv = (*reflectMethodValue)(unsafe.Pointer(ctxt))
} else {
// This is a real call that took the
// *reflect.methodValue as its context
// register and immediately saved it
// to 0(SP). Get the methodValue from
// 0(SP).
arg0 := frame.sp + sys.MinFrameSize
mv = *(**reflectMethodValue)(unsafe.Pointer(arg0))
}
if mv.fn != f.entry {
print("runtime: confused by ", funcname(f), "\n")
throw("reflect mismatch")
}
bv := (*bitvector)(unsafe.Pointer(fn[1]))
bv := mv.stack
arglen = uintptr(bv.n * sys.PtrSize)
argmap = bv
}

View File

@@ -7,28 +7,45 @@
package syscall_test
import (
"os/exec"
"syscall"
"testing"
)
const MNT_WAIT = 1
const MNT_NOWAIT = 2
func TestGetfsstat(t *testing.T) {
n, err := syscall.Getfsstat(nil, MNT_WAIT)
const flags = MNT_NOWAIT // see Issue 16937
n, err := syscall.Getfsstat(nil, flags)
t.Logf("Getfsstat(nil, %d) = (%v, %v)", flags, n, err)
if err != nil {
t.Fatal(err)
}
data := make([]syscall.Statfs_t, n)
n, err = syscall.Getfsstat(data, MNT_WAIT)
n2, err := syscall.Getfsstat(data, flags)
t.Logf("Getfsstat([]syscall.Statfs_t, %d) = (%v, %v)", flags, n2, err)
if err != nil {
t.Fatal(err)
}
empty := syscall.Statfs_t{}
for _, stat := range data {
if stat == empty {
t.Fatal("an empty Statfs_t struct was returned")
if n != n2 {
t.Errorf("Getfsstat(nil) = %d, but subsequent Getfsstat(slice) = %d", n, n2)
}
for i, stat := range data {
if stat == (syscall.Statfs_t{}) {
t.Errorf("index %v is an empty Statfs_t struct", i)
}
}
if t.Failed() {
for i, stat := range data[:n2] {
t.Logf("data[%v] = %+v", i, stat)
}
mount, err := exec.Command("mount").CombinedOutput()
if err != nil {
t.Logf("mount: %v\n%s", err, mount)
} else {
t.Logf("mount: %s", mount)
}
}
}

View File

@@ -939,8 +939,11 @@ func TestLoadFixed(t *testing.T) {
// but Go and most other systems use "east is positive".
// So GMT+1 corresponds to -3600 in the Go zone, not +3600.
name, offset := Now().In(loc).Zone()
if name != "GMT+1" || offset != -1*60*60 {
t.Errorf("Now().In(loc).Zone() = %q, %d, want %q, %d", name, offset, "GMT+1", -1*60*60)
// The zone abbreviation is "-01" since tzdata-2016g, and "GMT+1"
// on earlier versions; we accept both. (Issue #17276).
if !(name == "GMT+1" || name == "-01") || offset != -1*60*60 {
t.Errorf("Now().In(loc).Zone() = %q, %d, want %q or %q, %d",
name, offset, "GMT+1", "-01", -1*60*60)
}
}

View File

@@ -0,0 +1,48 @@
// run
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Perform tracebackdefers with a deferred reflection method.
package main
import "reflect"
type T struct{}
func (T) M() {
}
func F(args []reflect.Value) (results []reflect.Value) {
return nil
}
func main() {
done := make(chan bool)
go func() {
// Test reflect.makeFuncStub.
t := reflect.TypeOf((func())(nil))
f := reflect.MakeFunc(t, F).Interface().(func())
defer f()
growstack(10000)
done <- true
}()
<-done
go func() {
// Test reflect.methodValueCall.
f := reflect.ValueOf(T{}).Method(0).Interface().(func())
defer f()
growstack(10000)
done <- true
}()
<-done
}
func growstack(x int) {
if x == 0 {
return
}
growstack(x - 1)
}

View File

@@ -0,0 +1,47 @@
// errorcheck -0 -N -m -l
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The escape analyzer needs to run till its root set settles
// (this is not that often, it turns out).
// This test is likely to become stale because the leak depends
// on a spurious-escape bug -- return an interface as a named
// output parameter appears to cause the called closure to escape,
// where returning it as a regular type does not.
package main
import (
"fmt"
)
type closure func(i, j int) ent
type ent int
func (e ent) String() string {
return fmt.Sprintf("%d", int(e)) // ERROR "ent.String ... argument does not escape$" "int\(e\) escapes to heap$"
}
//go:noinline
func foo(ops closure, j int) (err fmt.Stringer) { // ERROR "leaking param: ops$" "leaking param: ops to result err level=0$"
enqueue := func(i int) fmt.Stringer { // ERROR "func literal escapes to heap$"
return ops(i, j) // ERROR "ops\(i, j\) escapes to heap$"
}
err = enqueue(4)
if err != nil {
return err
}
return // return result of enqueue, a fmt.Stringer
}
func main() {
// 3 identical functions, to get different escape behavior.
f := func(i, j int) ent { // ERROR "func literal escapes to heap$"
return ent(i + j)
}
i := foo(f, 3).(ent)
fmt.Printf("foo(f,3)=%d\n", int(i)) // ERROR "int\(i\) escapes to heap$" "main ... argument does not escape$"
}

View File

@@ -0,0 +1,40 @@
// run
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This checks partially initialized structure literals
// used to create value.method functions have their
// non-initialized fields properly zeroed/nil'd
package main
type X struct {
A, B, C *int
}
//go:noinline
func (t X) Print() {
if t.B != nil {
panic("t.B must be nil")
}
}
//go:noinline
func caller(f func()) {
f()
}
//go:noinline
func test() {
var i, j int
x := X{A: &i, C: &j}
caller(func() { X{A: &i, C: &j}.Print() })
caller(X{A: &i, C: &j}.Print)
caller(x.Print)
}
func main() {
test()
}