mirror of
https://github.com/golang/go.git
synced 2026-01-29 15:12:08 +03:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90c8964486 | ||
|
|
897b44e439 | ||
|
|
914efab0eb | ||
|
|
d39cd4d6d7 | ||
|
|
d01ccd8ee8 | ||
|
|
5aedc8af94 | ||
|
|
8954addb32 | ||
|
|
df52396943 | ||
|
|
e8a95aeb75 | ||
|
|
bbce36c1d8 | ||
|
|
6fb1030157 | ||
|
|
68ad1d60a2 | ||
|
|
369c188667 | ||
|
|
eb46d15471 | ||
|
|
ce6c8a5101 | ||
|
|
97781d2ed1 | ||
|
|
edb6c16b9b | ||
|
|
05b2b9b4d5 | ||
|
|
844bb04531 | ||
|
|
c33153f7b4 | ||
|
|
aa0966105e | ||
|
|
19fe28a3dc | ||
|
|
e9c178da3b | ||
|
|
26957168c4 | ||
|
|
52c4bdb65d | ||
|
|
92ae524bc5 | ||
|
|
307f8b5a6d | ||
|
|
58c9bd9bfb | ||
|
|
3afa9dfa9b | ||
|
|
a2f1c8e2ad | ||
|
|
34e5a852e0 | ||
|
|
7544ac632f | ||
|
|
05a0c7b4c6 | ||
|
|
e535c71009 | ||
|
|
b5ed6ec140 | ||
|
|
f2113d94c1 | ||
|
|
c9ca36fb70 | ||
|
|
0541668416 | ||
|
|
5a25f45bce | ||
|
|
eeaf877114 | ||
|
|
71fce844b5 | ||
|
|
cd9f60131b | ||
|
|
57534891d4 | ||
|
|
ebf5d985d1 | ||
|
|
ad116f72b9 | ||
|
|
359a02b0fc | ||
|
|
6d601b8a95 | ||
|
|
523dc5a412 | ||
|
|
41e62b8c49 | ||
|
|
89eb905c6d | ||
|
|
f5c8875aef | ||
|
|
c7415c1bd4 | ||
|
|
08c66d75ec | ||
|
|
02c0c32960 | ||
|
|
ca25572abb | ||
|
|
2eb8116f9e | ||
|
|
4124fe1c2c | ||
|
|
4383edf1c6 | ||
|
|
e1ad7cdf4f | ||
|
|
811b0c1bf5 | ||
|
|
ece4cdb9cb | ||
|
|
673a05e4df | ||
|
|
807e7f2420 |
@@ -1,7 +1,7 @@
|
||||
pkg crypto/cipher, func NewGCMWithTagSize(Block, int) (AEAD, error)
|
||||
pkg crypto/rsa, method (*PrivateKey) Size() int
|
||||
pkg crypto/rsa, method (*PublicKey) Size() int
|
||||
pkg crypto/tls, type ConnectionState struct, ExportKeyingMaterial func(string, []uint8, int) ([]uint8, bool)
|
||||
pkg crypto/tls, method (*ConnectionState) ExportKeyingMaterial(string, []uint8, int) ([]uint8, error)
|
||||
pkg database/sql, method (IsolationLevel) String() string
|
||||
pkg database/sql, type DBStats struct, Idle int
|
||||
pkg database/sql, type DBStats struct, InUse int
|
||||
|
||||
@@ -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.11">Go 1.11</a> <small>(August 2018)</small></li>
|
||||
<li><a href="/doc/go1.10">Go 1.10</a> <small>(February 2018)</small></li>
|
||||
<li><a href="/doc/go1.9">Go 1.9</a> <small>(August 2017)</small></li>
|
||||
<li><a href="/doc/go1.8">Go 1.8</a> <small>(February 2017)</small></li>
|
||||
|
||||
@@ -23,6 +23,39 @@ in supported releases as needed by issuing minor revisions
|
||||
(for example, Go 1.6.1, Go 1.6.2, and so on).
|
||||
</p>
|
||||
|
||||
<h2 id="go1.11">go1.11 (released 2018/08/24)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.11 is a major release of Go.
|
||||
Read the <a href="/doc/go1.11">Go 1.11 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.11.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.11.1 (released 2018/10/01) includes fixes to the compiler, documentation, go
|
||||
command, runtime, and the <code>crypto/x509</code>, <code>encoding/json</code>,
|
||||
<code>go/types</code>, <code>net</code>, <code>net/http</code>, and
|
||||
<code>reflect</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.1">Go
|
||||
1.11.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.2 (released 2018/11/02) includes fixes to the compiler, linker,
|
||||
documentation, go command, and the <code>database/sql</code> and
|
||||
<code>go/types</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.2">Go
|
||||
1.11.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.3 (released 2018/12/12) includes three security fixes to "go get" and
|
||||
the <code>crypto/x509</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.3">Go
|
||||
1.11.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.10">go1.10 (released 2018/02/16)</h2>
|
||||
|
||||
<p>
|
||||
@@ -57,6 +90,29 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.3">Go
|
||||
1.10.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.4 (released 2018/08/24) includes fixes to the go command, linker, and the
|
||||
<code>net/http</code>, <code>mime/multipart</code>, <code>ld/macho</code>,
|
||||
<code>bytes</code>, and <code>strings</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.4">Go
|
||||
1.10.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.5 (released 2018/11/02) includes fixes to the go command, linker, runtime
|
||||
and the <code>database/sql</code> package.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.5">Go
|
||||
1.10.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.6 (released 2018/12/12) includes three security fixes to "go get" and
|
||||
the <code>crypto/x509</code> package.
|
||||
It contains the same fixes as Go 1.11.3 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.6">Go
|
||||
1.10.6 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.9">go1.9 (released 2017/08/24)</h2>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -50,10 +50,10 @@ learned. You can {{if not $.GoogleCN}}<a href="//tour.golang.org/">take the tour
|
||||
online</a> or{{end}} install it locally with:
|
||||
</p>
|
||||
<pre>
|
||||
$ go get golang.org/x/tour/gotour
|
||||
$ go get golang.org/x/tour
|
||||
</pre>
|
||||
<p>
|
||||
This will place the <code>gotour</code> binary in your workspace's <code>bin</code> directory.
|
||||
This will place the <code>tour</code> binary in your workspace's <code>bin</code> directory.
|
||||
</p>
|
||||
|
||||
<h3 id="code"><a href="code.html">How to write Go code</a></h3>
|
||||
|
||||
@@ -15,14 +15,7 @@ Do not send CLs removing the interior tags from such phrases.
|
||||
ul li { margin: 0.5em 0; }
|
||||
</style>
|
||||
|
||||
<h2 id="introduction">DRAFT RELEASE NOTES - Introduction to Go 1.11</h2>
|
||||
|
||||
<p>
|
||||
<strong>
|
||||
Go 1.11 is not yet released. These are work-in-progress
|
||||
release notes. Go 1.11 is expected to be released in August 2018.
|
||||
</strong>
|
||||
</p>
|
||||
<h2 id="introduction">Introduction to Go 1.11</h2>
|
||||
|
||||
<p>
|
||||
The latest Go release, version 1.11, arrives six months after <a href="go1.10">Go 1.10</a>.
|
||||
@@ -95,7 +88,8 @@ Do not send CLs removing the interior tags from such phrases.
|
||||
|
||||
<h3 id="wasm">WebAssembly</h3>
|
||||
<p>
|
||||
Go 1.11 adds an experimental port to WebAssembly (<code>js/wasm</code>).
|
||||
Go 1.11 adds an experimental port to <a href="https://webassembly.org">WebAssembly</a>
|
||||
(<code>js/wasm</code>).
|
||||
</p>
|
||||
<p>
|
||||
Go programs currently compile to one WebAssembly module that
|
||||
@@ -116,6 +110,10 @@ Do not send CLs removing the interior tags from such phrases.
|
||||
tools</a> except when those GOOS/GOARCH values are being used.
|
||||
If you have existing filenames matching those patterns, you will need to rename them.
|
||||
</p>
|
||||
<p>
|
||||
More information can be found on the
|
||||
<a href="https://golang.org/wiki/WebAssembly">WebAssembly wiki page</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="riscv">RISC-V GOARCH values reserved</h3>
|
||||
<p><!-- CL 106256 -->
|
||||
@@ -350,6 +348,20 @@ updating. See the <a href="go1.10.html#cgo">Go 1.10 release notes</a> for
|
||||
details. <!-- CL 126275, CL 127156, CL 122217, CL 122575, CL 123177 -->
|
||||
</p>
|
||||
|
||||
<h3 id="go_command">Go command</h3>
|
||||
|
||||
<p><!-- CL 126656 -->
|
||||
The environment variable <code>GOFLAGS</code> may now be used
|
||||
to set default flags for the <code>go</code> command.
|
||||
This is useful in certain situations.
|
||||
Linking can be noticeably slower on underpowered systems due to DWARF,
|
||||
and users may want to set <code>-ldflags=-w</code> by default.
|
||||
For modules, some users and CI systems will want vendoring always,
|
||||
so they should set <code>-mod=vendor</code> by default.
|
||||
For more information, see the <a href="/cmd/go/#hdr-Environment_variables"><code>go</code>
|
||||
command documentation</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="godoc">Godoc</h3>
|
||||
|
||||
<p>
|
||||
@@ -384,7 +396,7 @@ details. <!-- CL 126275, CL 127156, CL 122217, CL 122575, CL 123177 -->
|
||||
time.
|
||||
In general, systems that need consistent formatting of Go source code should
|
||||
use a specific version of the <code>gofmt</code> binary.
|
||||
See the <a href="/pkg/go/format/">go/format</a> package godoc for more
|
||||
See the <a href="/pkg/go/format/">go/format</a> package documentation for more
|
||||
information.
|
||||
</p>
|
||||
|
||||
@@ -398,7 +410,7 @@ details. <!-- CL 126275, CL 127156, CL 122217, CL 122575, CL 123177 -->
|
||||
</p>
|
||||
|
||||
<p><!-- CL 108679, CL 106156 -->
|
||||
On macOS and iOS, the runtime now uses <code>libSystem.so</code> instead of
|
||||
On macOS and iOS, the runtime now uses <code>libSystem.dylib</code> instead of
|
||||
calling the kernel directly. This should make Go binaries more
|
||||
compatible with future versions of macOS and iOS.
|
||||
The <a href="/pkg/syscall">syscall</a> package still makes direct
|
||||
@@ -500,7 +512,8 @@ for k := range m {
|
||||
<dd>
|
||||
<p><!-- CL 85115 -->
|
||||
<a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>'s new
|
||||
<code>ExportKeyingMaterial</code> field allows exporting keying material bound to the
|
||||
<a href="/pkg/crypto/tls/#ConnectionState.ExportKeyingMaterial"><code>ExportKeyingMaterial</code></a>
|
||||
method allows exporting keying material bound to the
|
||||
connection according to RFC 5705.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -12,6 +12,11 @@ license that can be found in the LICENSE file.
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--
|
||||
Add the following polyfill for Microsoft Edge 17/18 support:
|
||||
<script src="https://cdn.jsdelivr.net/npm/text-encoding@0.7.0/lib/encoding.min.js"></script>
|
||||
(see https://caniuse.com/#feat=textencoder)
|
||||
-->
|
||||
<script src="wasm_exec.js"></script>
|
||||
<script>
|
||||
if (!WebAssembly.instantiateStreaming) { // polyfill
|
||||
|
||||
@@ -121,6 +121,17 @@ func (n *Node) Int64() int64 {
|
||||
return n.Val().U.(*Mpint).Int64()
|
||||
}
|
||||
|
||||
// CanInt64 reports whether it is safe to call Int64() on n.
|
||||
func (n *Node) CanInt64() bool {
|
||||
if !Isconst(n, CTINT) {
|
||||
return false
|
||||
}
|
||||
|
||||
// if the value inside n cannot be represented as an int64, the
|
||||
// return value of Int64 is undefined
|
||||
return n.Val().U.(*Mpint).CmpInt64(n.Int64()) == 0
|
||||
}
|
||||
|
||||
// Bool returns n as a bool.
|
||||
// n must be a boolean constant.
|
||||
func (n *Node) Bool() bool {
|
||||
|
||||
@@ -1263,7 +1263,7 @@ func typecheck1(n *Node, top int) *Node {
|
||||
n.Op = OCALLFUNC
|
||||
if t.Etype != TFUNC {
|
||||
name := l.String()
|
||||
if isBuiltinFuncName(name) {
|
||||
if isBuiltinFuncName(name) && l.Name.Defn != nil {
|
||||
// be more specific when the function
|
||||
// name matches a predeclared function
|
||||
yyerror("cannot call non-function %s (type %v), declared at %s",
|
||||
|
||||
@@ -3701,6 +3701,12 @@ func walkinrange(n *Node, init *Nodes) *Node {
|
||||
return n
|
||||
}
|
||||
|
||||
// Ensure that Int64() does not overflow on a and c (it'll happen
|
||||
// for any const above 2**63; see issue #27143).
|
||||
if !a.CanInt64() || !c.CanInt64() {
|
||||
return n
|
||||
}
|
||||
|
||||
if opl == OLT {
|
||||
// We have a < b && ...
|
||||
// We need a ≤ b && ... to safely use unsigned comparison tricks.
|
||||
|
||||
@@ -197,7 +197,8 @@ func elimDeadAutosGeneric(f *Func) {
|
||||
panic("unhandled op with sym effect")
|
||||
}
|
||||
|
||||
if v.Uses == 0 || len(args) == 0 {
|
||||
if v.Uses == 0 && v.Op != OpNilCheck || len(args) == 0 {
|
||||
// Nil check has no use, but we need to keep it.
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1539,8 +1539,8 @@
|
||||
// Don't Move from memory if the values are likely to already be
|
||||
// in registers.
|
||||
(Move {t1} [n] dst p1
|
||||
mem:(Store {t2} op2:(OffPtr [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr [0] p3) d2 _)))
|
||||
mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _)))
|
||||
&& isSamePtr(p1, p2) && isSamePtr(p2, p3)
|
||||
&& alignof(t2) <= alignof(t1)
|
||||
&& alignof(t3) <= alignof(t1)
|
||||
@@ -1548,12 +1548,12 @@
|
||||
&& registerizable(b, t3)
|
||||
&& o2 == sizeof(t3)
|
||||
&& n == sizeof(t2) + sizeof(t3)
|
||||
-> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
|
||||
-> (Store {t2} (OffPtr <tt2> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
|
||||
(Move {t1} [n] dst p1
|
||||
mem:(Store {t2} op2:(OffPtr [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr [o3] p3) d2
|
||||
(Store {t4} op4:(OffPtr [0] p4) d3 _))))
|
||||
mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
|
||||
(Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _))))
|
||||
&& isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
|
||||
&& alignof(t2) <= alignof(t1)
|
||||
&& alignof(t3) <= alignof(t1)
|
||||
@@ -1564,14 +1564,14 @@
|
||||
&& o3 == sizeof(t4)
|
||||
&& o2-o3 == sizeof(t3)
|
||||
&& n == sizeof(t2) + sizeof(t3) + sizeof(t4)
|
||||
-> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
|
||||
(Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
|
||||
-> (Store {t2} (OffPtr <tt2> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <tt3> [o3] dst) d2
|
||||
(Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
|
||||
(Move {t1} [n] dst p1
|
||||
mem:(Store {t2} op2:(OffPtr [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr [o3] p3) d2
|
||||
(Store {t4} op4:(OffPtr [o4] p4) d3
|
||||
(Store {t5} op5:(OffPtr [0] p5) d4 _)))))
|
||||
mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
|
||||
(Store {t4} op4:(OffPtr <tt4> [o4] p4) d3
|
||||
(Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _)))))
|
||||
&& isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
|
||||
&& alignof(t2) <= alignof(t1)
|
||||
&& alignof(t3) <= alignof(t1)
|
||||
@@ -1585,16 +1585,16 @@
|
||||
&& o3-o4 == sizeof(t4)
|
||||
&& o2-o3 == sizeof(t3)
|
||||
&& n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
|
||||
-> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
|
||||
(Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3
|
||||
(Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
|
||||
-> (Store {t2} (OffPtr <tt2> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <tt3> [o3] dst) d2
|
||||
(Store {t4} (OffPtr <tt4> [o4] dst) d3
|
||||
(Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
|
||||
|
||||
// Same thing but with VarDef in the middle.
|
||||
(Move {t1} [n] dst p1
|
||||
mem:(VarDef
|
||||
(Store {t2} op2:(OffPtr [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr [0] p3) d2 _))))
|
||||
(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _))))
|
||||
&& isSamePtr(p1, p2) && isSamePtr(p2, p3)
|
||||
&& alignof(t2) <= alignof(t1)
|
||||
&& alignof(t3) <= alignof(t1)
|
||||
@@ -1602,13 +1602,13 @@
|
||||
&& registerizable(b, t3)
|
||||
&& o2 == sizeof(t3)
|
||||
&& n == sizeof(t2) + sizeof(t3)
|
||||
-> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
|
||||
-> (Store {t2} (OffPtr <tt2> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
|
||||
(Move {t1} [n] dst p1
|
||||
mem:(VarDef
|
||||
(Store {t2} op2:(OffPtr [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr [o3] p3) d2
|
||||
(Store {t4} op4:(OffPtr [0] p4) d3 _)))))
|
||||
(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
|
||||
(Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _)))))
|
||||
&& isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
|
||||
&& alignof(t2) <= alignof(t1)
|
||||
&& alignof(t3) <= alignof(t1)
|
||||
@@ -1619,15 +1619,15 @@
|
||||
&& o3 == sizeof(t4)
|
||||
&& o2-o3 == sizeof(t3)
|
||||
&& n == sizeof(t2) + sizeof(t3) + sizeof(t4)
|
||||
-> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
|
||||
(Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
|
||||
-> (Store {t2} (OffPtr <tt2> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <tt3> [o3] dst) d2
|
||||
(Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
|
||||
(Move {t1} [n] dst p1
|
||||
mem:(VarDef
|
||||
(Store {t2} op2:(OffPtr [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr [o3] p3) d2
|
||||
(Store {t4} op4:(OffPtr [o4] p4) d3
|
||||
(Store {t5} op5:(OffPtr [0] p5) d4 _))))))
|
||||
(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
|
||||
(Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
|
||||
(Store {t4} op4:(OffPtr <tt4> [o4] p4) d3
|
||||
(Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _))))))
|
||||
&& isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
|
||||
&& alignof(t2) <= alignof(t1)
|
||||
&& alignof(t3) <= alignof(t1)
|
||||
@@ -1641,10 +1641,10 @@
|
||||
&& o3-o4 == sizeof(t4)
|
||||
&& o2-o3 == sizeof(t3)
|
||||
&& n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
|
||||
-> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
|
||||
(Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3
|
||||
(Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
|
||||
-> (Store {t2} (OffPtr <tt2> [o2] dst) d1
|
||||
(Store {t3} (OffPtr <tt3> [o3] dst) d2
|
||||
(Store {t4} (OffPtr <tt4> [o4] dst) d3
|
||||
(Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
|
||||
|
||||
// Prefer to Zero and Store than to Move.
|
||||
(Move {t1} [n] dst p1
|
||||
|
||||
@@ -425,13 +425,13 @@ func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
|
||||
//
|
||||
// Useful for i > 0; s[i-1].
|
||||
lim, ok := ft.limits[x.ID]
|
||||
if ok && lim.min > opMin[v.Op] {
|
||||
if ok && ((d == signed && lim.min > opMin[v.Op]) || (d == unsigned && lim.umin > 0)) {
|
||||
ft.update(parent, x, w, d, gt)
|
||||
}
|
||||
} else if x, delta := isConstDelta(w); x != nil && delta == 1 {
|
||||
// v >= x+1 && x < max ⇒ v > x
|
||||
lim, ok := ft.limits[x.ID]
|
||||
if ok && lim.max < opMax[w.Op] {
|
||||
if ok && ((d == signed && lim.max < opMax[w.Op]) || (d == unsigned && lim.umax < opUMax[w.Op])) {
|
||||
ft.update(parent, v, x, d, gt)
|
||||
}
|
||||
}
|
||||
@@ -527,6 +527,11 @@ var opMax = map[Op]int64{
|
||||
OpAdd32: math.MaxInt32, OpSub32: math.MaxInt32,
|
||||
}
|
||||
|
||||
var opUMax = map[Op]uint64{
|
||||
OpAdd64: math.MaxUint64, OpSub64: math.MaxUint64,
|
||||
OpAdd32: math.MaxUint32, OpSub32: math.MaxUint32,
|
||||
}
|
||||
|
||||
// isNonNegative reports whether v is known to be non-negative.
|
||||
func (ft *factsTable) isNonNegative(v *Value) bool {
|
||||
if isNonNegative(v) {
|
||||
|
||||
@@ -16223,9 +16223,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [0] p3) d2 _)))
|
||||
// match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _)))
|
||||
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && o2 == sizeof(t3) && n == sizeof(t2) + sizeof(t3)
|
||||
// result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
|
||||
// result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
|
||||
for {
|
||||
n := v.AuxInt
|
||||
t1 := v.Aux
|
||||
@@ -16242,6 +16242,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
if op2.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt2 := op2.Type
|
||||
o2 := op2.AuxInt
|
||||
p2 := op2.Args[0]
|
||||
d1 := mem.Args[1]
|
||||
@@ -16255,6 +16256,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
if op3.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt3 := op3.Type
|
||||
if op3.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
@@ -16265,14 +16267,14 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
}
|
||||
v.reset(OpStore)
|
||||
v.Aux = t2
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
|
||||
v0.AuxInt = o2
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(d1)
|
||||
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v1.Aux = t3
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
|
||||
v2.AuxInt = 0
|
||||
v2.AddArg(dst)
|
||||
v1.AddArg(v2)
|
||||
@@ -16281,9 +16283,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
// match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [0] p4) d3 _))))
|
||||
// match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _))))
|
||||
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4)
|
||||
// result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
|
||||
// result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
|
||||
for {
|
||||
n := v.AuxInt
|
||||
t1 := v.Aux
|
||||
@@ -16300,6 +16302,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
if op2.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt2 := op2.Type
|
||||
o2 := op2.AuxInt
|
||||
p2 := op2.Args[0]
|
||||
d1 := mem.Args[1]
|
||||
@@ -16313,6 +16316,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
if op3.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt3 := op3.Type
|
||||
o3 := op3.AuxInt
|
||||
p3 := op3.Args[0]
|
||||
d2 := mem_2.Args[1]
|
||||
@@ -16326,6 +16330,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
if op4.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt4 := op4.Type
|
||||
if op4.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
@@ -16336,21 +16341,21 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
}
|
||||
v.reset(OpStore)
|
||||
v.Aux = t2
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
|
||||
v0.AuxInt = o2
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(d1)
|
||||
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v1.Aux = t3
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
|
||||
v2.AuxInt = o3
|
||||
v2.AddArg(dst)
|
||||
v1.AddArg(v2)
|
||||
v1.AddArg(d2)
|
||||
v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v3.Aux = t4
|
||||
v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
|
||||
v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
|
||||
v4.AuxInt = 0
|
||||
v4.AddArg(dst)
|
||||
v3.AddArg(v4)
|
||||
@@ -16360,9 +16365,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
// match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [o4] p4) d3 (Store {t5} op5:(OffPtr [0] p5) d4 _)))))
|
||||
// match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3 (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _)))))
|
||||
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && alignof(t5) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == sizeof(t5) && o3-o4 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
|
||||
// result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3 (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
|
||||
// result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
|
||||
for {
|
||||
n := v.AuxInt
|
||||
t1 := v.Aux
|
||||
@@ -16379,6 +16384,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
if op2.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt2 := op2.Type
|
||||
o2 := op2.AuxInt
|
||||
p2 := op2.Args[0]
|
||||
d1 := mem.Args[1]
|
||||
@@ -16392,6 +16398,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
if op3.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt3 := op3.Type
|
||||
o3 := op3.AuxInt
|
||||
p3 := op3.Args[0]
|
||||
d2 := mem_2.Args[1]
|
||||
@@ -16405,6 +16412,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
if op4.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt4 := op4.Type
|
||||
o4 := op4.AuxInt
|
||||
p4 := op4.Args[0]
|
||||
d3 := mem_2_2.Args[1]
|
||||
@@ -16418,6 +16426,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
if op5.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt5 := op5.Type
|
||||
if op5.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
@@ -16428,28 +16437,28 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
}
|
||||
v.reset(OpStore)
|
||||
v.Aux = t2
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
|
||||
v0.AuxInt = o2
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(d1)
|
||||
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v1.Aux = t3
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
|
||||
v2.AuxInt = o3
|
||||
v2.AddArg(dst)
|
||||
v1.AddArg(v2)
|
||||
v1.AddArg(d2)
|
||||
v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v3.Aux = t4
|
||||
v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
|
||||
v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
|
||||
v4.AuxInt = o4
|
||||
v4.AddArg(dst)
|
||||
v3.AddArg(v4)
|
||||
v3.AddArg(d3)
|
||||
v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v5.Aux = t5
|
||||
v6 := b.NewValue0(v.Pos, OpOffPtr, t5.(*types.Type))
|
||||
v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
|
||||
v6.AuxInt = 0
|
||||
v6.AddArg(dst)
|
||||
v5.AddArg(v6)
|
||||
@@ -16465,9 +16474,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
|
||||
func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [0] p3) d2 _))))
|
||||
// match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _))))
|
||||
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && o2 == sizeof(t3) && n == sizeof(t2) + sizeof(t3)
|
||||
// result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
|
||||
// result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
|
||||
for {
|
||||
n := v.AuxInt
|
||||
t1 := v.Aux
|
||||
@@ -16488,6 +16497,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
if op2.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt2 := op2.Type
|
||||
o2 := op2.AuxInt
|
||||
p2 := op2.Args[0]
|
||||
d1 := mem_0.Args[1]
|
||||
@@ -16501,6 +16511,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
if op3.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt3 := op3.Type
|
||||
if op3.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
@@ -16511,14 +16522,14 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
}
|
||||
v.reset(OpStore)
|
||||
v.Aux = t2
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
|
||||
v0.AuxInt = o2
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(d1)
|
||||
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v1.Aux = t3
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
|
||||
v2.AuxInt = 0
|
||||
v2.AddArg(dst)
|
||||
v1.AddArg(v2)
|
||||
@@ -16527,9 +16538,9 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
// match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [0] p4) d3 _)))))
|
||||
// match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _)))))
|
||||
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4)
|
||||
// result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
|
||||
// result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
|
||||
for {
|
||||
n := v.AuxInt
|
||||
t1 := v.Aux
|
||||
@@ -16550,6 +16561,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
if op2.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt2 := op2.Type
|
||||
o2 := op2.AuxInt
|
||||
p2 := op2.Args[0]
|
||||
d1 := mem_0.Args[1]
|
||||
@@ -16563,6 +16575,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
if op3.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt3 := op3.Type
|
||||
o3 := op3.AuxInt
|
||||
p3 := op3.Args[0]
|
||||
d2 := mem_0_2.Args[1]
|
||||
@@ -16576,6 +16589,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
if op4.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt4 := op4.Type
|
||||
if op4.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
@@ -16586,21 +16600,21 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
}
|
||||
v.reset(OpStore)
|
||||
v.Aux = t2
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
|
||||
v0.AuxInt = o2
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(d1)
|
||||
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v1.Aux = t3
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
|
||||
v2.AuxInt = o3
|
||||
v2.AddArg(dst)
|
||||
v1.AddArg(v2)
|
||||
v1.AddArg(d2)
|
||||
v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v3.Aux = t4
|
||||
v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
|
||||
v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
|
||||
v4.AuxInt = 0
|
||||
v4.AddArg(dst)
|
||||
v3.AddArg(v4)
|
||||
@@ -16610,9 +16624,9 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
// match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [o4] p4) d3 (Store {t5} op5:(OffPtr [0] p5) d4 _))))))
|
||||
// match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3 (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _))))))
|
||||
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && alignof(t5) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == sizeof(t5) && o3-o4 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
|
||||
// result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3 (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
|
||||
// result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
|
||||
for {
|
||||
n := v.AuxInt
|
||||
t1 := v.Aux
|
||||
@@ -16633,6 +16647,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
if op2.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt2 := op2.Type
|
||||
o2 := op2.AuxInt
|
||||
p2 := op2.Args[0]
|
||||
d1 := mem_0.Args[1]
|
||||
@@ -16646,6 +16661,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
if op3.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt3 := op3.Type
|
||||
o3 := op3.AuxInt
|
||||
p3 := op3.Args[0]
|
||||
d2 := mem_0_2.Args[1]
|
||||
@@ -16659,6 +16675,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
if op4.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt4 := op4.Type
|
||||
o4 := op4.AuxInt
|
||||
p4 := op4.Args[0]
|
||||
d3 := mem_0_2_2.Args[1]
|
||||
@@ -16672,6 +16689,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
if op5.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
tt5 := op5.Type
|
||||
if op5.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
@@ -16682,28 +16700,28 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
|
||||
}
|
||||
v.reset(OpStore)
|
||||
v.Aux = t2
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
|
||||
v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
|
||||
v0.AuxInt = o2
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(d1)
|
||||
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v1.Aux = t3
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
|
||||
v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
|
||||
v2.AuxInt = o3
|
||||
v2.AddArg(dst)
|
||||
v1.AddArg(v2)
|
||||
v1.AddArg(d2)
|
||||
v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v3.Aux = t4
|
||||
v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
|
||||
v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
|
||||
v4.AuxInt = o4
|
||||
v4.AddArg(dst)
|
||||
v3.AddArg(v4)
|
||||
v3.AddArg(d3)
|
||||
v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
|
||||
v5.Aux = t5
|
||||
v6 := b.NewValue0(v.Pos, OpOffPtr, t5.(*types.Type))
|
||||
v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
|
||||
v6.AuxInt = 0
|
||||
v6.AddArg(dst)
|
||||
v5.AddArg(v6)
|
||||
|
||||
@@ -817,7 +817,7 @@ func (t *Type) ChanArgs() *Type {
|
||||
return t.Extra.(ChanArgs).T
|
||||
}
|
||||
|
||||
// FuncArgs returns the channel type for TFUNCARGS type t.
|
||||
// FuncArgs returns the func type for TFUNCARGS type t.
|
||||
func (t *Type) FuncArgs() *Type {
|
||||
t.wantEtype(TFUNCARGS)
|
||||
return t.Extra.(FuncArgs).T
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
// link against shared libraries previously created with
|
||||
// -buildmode=shared.
|
||||
// -mod mode
|
||||
// module download mode to use: readonly, release, or vendor.
|
||||
// module download mode to use: readonly or vendor.
|
||||
// See 'go help modules' for more.
|
||||
// -pkgdir dir
|
||||
// install and load all packages from dir instead of the usual locations.
|
||||
@@ -889,7 +889,7 @@
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// go mod download [-dir] [-json] [modules]
|
||||
// go mod download [-json] [modules]
|
||||
//
|
||||
// Download downloads the named modules, which can be module patterns selecting
|
||||
// dependencies of the main module or module queries of the form path@version.
|
||||
@@ -905,13 +905,15 @@
|
||||
// corresponding to this Go struct:
|
||||
//
|
||||
// type Module struct {
|
||||
// Path string // module path
|
||||
// Version string // module version
|
||||
// Error string // error loading module
|
||||
// Info string // absolute path to cached .info file
|
||||
// GoMod string // absolute path to cached .mod file
|
||||
// Zip string // absolute path to cached .zip file
|
||||
// Dir string // absolute path to cached source root directory
|
||||
// Path string // module path
|
||||
// Version string // module version
|
||||
// Error string // error loading module
|
||||
// Info string // absolute path to cached .info file
|
||||
// GoMod string // absolute path to cached .mod file
|
||||
// Zip string // absolute path to cached .zip file
|
||||
// Dir string // absolute path to cached source root directory
|
||||
// Sum string // checksum for path, version (as in go.sum)
|
||||
// GoModSum string // checksum for go.mod (as in go.sum)
|
||||
// }
|
||||
//
|
||||
// See 'go help modules' for more about module queries.
|
||||
@@ -1447,6 +1449,12 @@
|
||||
// The directory where the go command will write
|
||||
// temporary source files, packages, and binaries.
|
||||
//
|
||||
// Each entry in the GOFLAGS list must be a standalone flag.
|
||||
// Because the entries are space-separated, flag values must
|
||||
// not contain spaces. In some cases, you can provide multiple flag
|
||||
// values instead: for example, to set '-ldflags=-s -w'
|
||||
// you can use 'GOFLAGS=-ldflags=-s -ldflags=-w'.
|
||||
//
|
||||
// Environment variables for use with cgo:
|
||||
//
|
||||
// CC
|
||||
@@ -1614,7 +1622,19 @@
|
||||
//
|
||||
// The go command automatically updates go.mod each time it uses the
|
||||
// module graph, to make sure go.mod always accurately reflects reality
|
||||
// and is properly formatted.
|
||||
// and is properly formatted. For example, consider this go.mod file:
|
||||
//
|
||||
// module M
|
||||
//
|
||||
// require (
|
||||
// A v1
|
||||
// B v1.0.0
|
||||
// C v1.0.0
|
||||
// D v1.2.3
|
||||
// E dev
|
||||
// )
|
||||
//
|
||||
// exclude D v1.2.3
|
||||
//
|
||||
// The update rewrites non-canonical version identifiers to semver form,
|
||||
// so A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the
|
||||
|
||||
@@ -402,6 +402,10 @@ func downloadPackage(p *load.Package) error {
|
||||
security = web.Insecure
|
||||
}
|
||||
|
||||
if err := CheckImportPath(p.ImportPath); err != nil {
|
||||
return fmt.Errorf("%s: invalid import path: %v", p.ImportPath, err)
|
||||
}
|
||||
|
||||
if p.Internal.Build.SrcRoot != "" {
|
||||
// Directory exists. Look for checkout along path to src.
|
||||
vcs, rootPath, err = vcsFromDir(p.Dir, p.Internal.Build.SrcRoot)
|
||||
|
||||
192
src/cmd/go/internal/get/path.go
Normal file
192
src/cmd/go/internal/get/path.go
Normal file
@@ -0,0 +1,192 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package get
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// The following functions are copied verbatim from cmd/go/internal/module/module.go,
|
||||
// with a change to additionally reject Windows short-names,
|
||||
// and one to accept arbitrary letters (golang.org/issue/29101).
|
||||
//
|
||||
// TODO(bcmills): After the call site for this function is backported,
|
||||
// consolidate this back down to a single copy.
|
||||
//
|
||||
// NOTE: DO NOT MERGE THESE UNTIL WE DECIDE ABOUT ARBITRARY LETTERS IN MODULE MODE.
|
||||
|
||||
// CheckImportPath checks that an import path is valid.
|
||||
func CheckImportPath(path string) error {
|
||||
if err := checkPath(path, false); err != nil {
|
||||
return fmt.Errorf("malformed import path %q: %v", path, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkPath checks that a general path is valid.
|
||||
// It returns an error describing why but not mentioning path.
|
||||
// Because these checks apply to both module paths and import paths,
|
||||
// the caller is expected to add the "malformed ___ path %q: " prefix.
|
||||
// fileName indicates whether the final element of the path is a file name
|
||||
// (as opposed to a directory name).
|
||||
func checkPath(path string, fileName bool) error {
|
||||
if !utf8.ValidString(path) {
|
||||
return fmt.Errorf("invalid UTF-8")
|
||||
}
|
||||
if path == "" {
|
||||
return fmt.Errorf("empty string")
|
||||
}
|
||||
if strings.Contains(path, "..") {
|
||||
return fmt.Errorf("double dot")
|
||||
}
|
||||
if strings.Contains(path, "//") {
|
||||
return fmt.Errorf("double slash")
|
||||
}
|
||||
if path[len(path)-1] == '/' {
|
||||
return fmt.Errorf("trailing slash")
|
||||
}
|
||||
elemStart := 0
|
||||
for i, r := range path {
|
||||
if r == '/' {
|
||||
if err := checkElem(path[elemStart:i], fileName); err != nil {
|
||||
return err
|
||||
}
|
||||
elemStart = i + 1
|
||||
}
|
||||
}
|
||||
if err := checkElem(path[elemStart:], fileName); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkElem checks whether an individual path element is valid.
|
||||
// fileName indicates whether the element is a file name (not a directory name).
|
||||
func checkElem(elem string, fileName bool) error {
|
||||
if elem == "" {
|
||||
return fmt.Errorf("empty path element")
|
||||
}
|
||||
if strings.Count(elem, ".") == len(elem) {
|
||||
return fmt.Errorf("invalid path element %q", elem)
|
||||
}
|
||||
if elem[0] == '.' && !fileName {
|
||||
return fmt.Errorf("leading dot in path element")
|
||||
}
|
||||
if elem[len(elem)-1] == '.' {
|
||||
return fmt.Errorf("trailing dot in path element")
|
||||
}
|
||||
|
||||
charOK := pathOK
|
||||
if fileName {
|
||||
charOK = fileNameOK
|
||||
}
|
||||
for _, r := range elem {
|
||||
if !charOK(r) {
|
||||
return fmt.Errorf("invalid char %q", r)
|
||||
}
|
||||
}
|
||||
|
||||
// Windows disallows a bunch of path elements, sadly.
|
||||
// See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
|
||||
short := elem
|
||||
if i := strings.Index(short, "."); i >= 0 {
|
||||
short = short[:i]
|
||||
}
|
||||
for _, bad := range badWindowsNames {
|
||||
if strings.EqualFold(bad, short) {
|
||||
return fmt.Errorf("disallowed path element %q", elem)
|
||||
}
|
||||
}
|
||||
|
||||
// Reject path components that look like Windows short-names.
|
||||
// Those usually end in a tilde followed by one or more ASCII digits.
|
||||
if tilde := strings.LastIndexByte(short, '~'); tilde >= 0 && tilde < len(short)-1 {
|
||||
suffix := short[tilde+1:]
|
||||
suffixIsDigits := true
|
||||
for _, r := range suffix {
|
||||
if r < '0' || r > '9' {
|
||||
suffixIsDigits = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if suffixIsDigits {
|
||||
return fmt.Errorf("trailing tilde and digits in path element")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// pathOK reports whether r can appear in an import path element.
|
||||
//
|
||||
// NOTE: This function DIVERGES from module mode pathOK by accepting Unicode letters.
|
||||
func pathOK(r rune) bool {
|
||||
if r < utf8.RuneSelf {
|
||||
return r == '+' || r == '-' || r == '.' || r == '_' || r == '~' ||
|
||||
'0' <= r && r <= '9' ||
|
||||
'A' <= r && r <= 'Z' ||
|
||||
'a' <= r && r <= 'z'
|
||||
}
|
||||
return unicode.IsLetter(r)
|
||||
}
|
||||
|
||||
// fileNameOK reports whether r can appear in a file name.
|
||||
// For now we allow all Unicode letters but otherwise limit to pathOK plus a few more punctuation characters.
|
||||
// If we expand the set of allowed characters here, we have to
|
||||
// work harder at detecting potential case-folding and normalization collisions.
|
||||
// See note about "safe encoding" below.
|
||||
func fileNameOK(r rune) bool {
|
||||
if r < utf8.RuneSelf {
|
||||
// Entire set of ASCII punctuation, from which we remove characters:
|
||||
// ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
|
||||
// We disallow some shell special characters: " ' * < > ? ` |
|
||||
// (Note that some of those are disallowed by the Windows file system as well.)
|
||||
// We also disallow path separators / : and \ (fileNameOK is only called on path element characters).
|
||||
// We allow spaces (U+0020) in file names.
|
||||
const allowed = "!#$%&()+,-.=@[]^_{}~ "
|
||||
if '0' <= r && r <= '9' || 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' {
|
||||
return true
|
||||
}
|
||||
for i := 0; i < len(allowed); i++ {
|
||||
if rune(allowed[i]) == r {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
// It may be OK to add more ASCII punctuation here, but only carefully.
|
||||
// For example Windows disallows < > \, and macOS disallows :, so we must not allow those.
|
||||
return unicode.IsLetter(r)
|
||||
}
|
||||
|
||||
// badWindowsNames are the reserved file path elements on Windows.
|
||||
// See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
|
||||
var badWindowsNames = []string{
|
||||
"CON",
|
||||
"PRN",
|
||||
"AUX",
|
||||
"NUL",
|
||||
"COM1",
|
||||
"COM2",
|
||||
"COM3",
|
||||
"COM4",
|
||||
"COM5",
|
||||
"COM6",
|
||||
"COM7",
|
||||
"COM8",
|
||||
"COM9",
|
||||
"LPT1",
|
||||
"LPT2",
|
||||
"LPT3",
|
||||
"LPT4",
|
||||
"LPT5",
|
||||
"LPT6",
|
||||
"LPT7",
|
||||
"LPT8",
|
||||
"LPT9",
|
||||
}
|
||||
@@ -966,10 +966,14 @@ func matchGoImport(imports []metaImport, importPath string) (metaImport, error)
|
||||
|
||||
// expand rewrites s to replace {k} with match[k] for each key k in match.
|
||||
func expand(match map[string]string, s string) string {
|
||||
// We want to replace each match exactly once, and the result of expansion
|
||||
// must not depend on the iteration order through the map.
|
||||
// A strings.Replacer has exactly the properties we're looking for.
|
||||
oldNew := make([]string, 0, 2*len(match))
|
||||
for k, v := range match {
|
||||
s = strings.Replace(s, "{"+k+"}", v, -1)
|
||||
oldNew = append(oldNew, "{"+k+"}", v)
|
||||
}
|
||||
return s
|
||||
return strings.NewReplacer(oldNew...).Replace(s)
|
||||
}
|
||||
|
||||
// vcsPaths defines the meaning of import paths referring to
|
||||
|
||||
@@ -507,6 +507,12 @@ General-purpose environment variables:
|
||||
The directory where the go command will write
|
||||
temporary source files, packages, and binaries.
|
||||
|
||||
Each entry in the GOFLAGS list must be a standalone flag.
|
||||
Because the entries are space-separated, flag values must
|
||||
not contain spaces. In some cases, you can provide multiple flag
|
||||
values instead: for example, to set '-ldflags=-s -w'
|
||||
you can use 'GOFLAGS=-ldflags=-s -ldflags=-w'.
|
||||
|
||||
Environment variables for use with cgo:
|
||||
|
||||
CC
|
||||
|
||||
@@ -510,7 +510,9 @@ func runList(cmd *base.Command, args []string) {
|
||||
a := &work.Action{}
|
||||
// TODO: Use pkgsFilter?
|
||||
for _, p := range pkgs {
|
||||
a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p))
|
||||
if len(p.GoFiles)+len(p.CgoFiles) > 0 {
|
||||
a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p))
|
||||
}
|
||||
}
|
||||
b.Do(a)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
var cmdDownload = &base.Command{
|
||||
UsageLine: "go mod download [-dir] [-json] [modules]",
|
||||
UsageLine: "go mod download [-json] [modules]",
|
||||
Short: "download modules to local cache",
|
||||
Long: `
|
||||
Download downloads the named modules, which can be module patterns selecting
|
||||
@@ -32,13 +32,15 @@ to standard output, describing each downloaded module (or failure),
|
||||
corresponding to this Go struct:
|
||||
|
||||
type Module struct {
|
||||
Path string // module path
|
||||
Version string // module version
|
||||
Error string // error loading module
|
||||
Info string // absolute path to cached .info file
|
||||
GoMod string // absolute path to cached .mod file
|
||||
Zip string // absolute path to cached .zip file
|
||||
Dir string // absolute path to cached source root directory
|
||||
Path string // module path
|
||||
Version string // module version
|
||||
Error string // error loading module
|
||||
Info string // absolute path to cached .info file
|
||||
GoMod string // absolute path to cached .mod file
|
||||
Zip string // absolute path to cached .zip file
|
||||
Dir string // absolute path to cached source root directory
|
||||
Sum string // checksum for path, version (as in go.sum)
|
||||
GoModSum string // checksum for go.mod (as in go.sum)
|
||||
}
|
||||
|
||||
See 'go help modules' for more about module queries.
|
||||
@@ -52,13 +54,15 @@ func init() {
|
||||
}
|
||||
|
||||
type moduleJSON struct {
|
||||
Path string `json:",omitempty"`
|
||||
Version string `json:",omitempty"`
|
||||
Error string `json:",omitempty"`
|
||||
Info string `json:",omitempty"`
|
||||
GoMod string `json:",omitempty"`
|
||||
Zip string `json:",omitempty"`
|
||||
Dir string `json:",omitempty"`
|
||||
Path string `json:",omitempty"`
|
||||
Version string `json:",omitempty"`
|
||||
Error string `json:",omitempty"`
|
||||
Info string `json:",omitempty"`
|
||||
GoMod string `json:",omitempty"`
|
||||
Zip string `json:",omitempty"`
|
||||
Dir string `json:",omitempty"`
|
||||
Sum string `json:",omitempty"`
|
||||
GoModSum string `json:",omitempty"`
|
||||
}
|
||||
|
||||
func runDownload(cmd *base.Command, args []string) {
|
||||
@@ -98,12 +102,18 @@ func runDownload(cmd *base.Command, args []string) {
|
||||
m.Error = err.Error()
|
||||
return
|
||||
}
|
||||
m.GoModSum, err = modfetch.GoModSum(m.Path, m.Version)
|
||||
if err != nil {
|
||||
m.Error = err.Error()
|
||||
return
|
||||
}
|
||||
mod := module.Version{Path: m.Path, Version: m.Version}
|
||||
m.Zip, err = modfetch.DownloadZip(mod)
|
||||
if err != nil {
|
||||
m.Error = err.Error()
|
||||
return
|
||||
}
|
||||
m.Sum = modfetch.Sum(mod)
|
||||
m.Dir, err = modfetch.Download(mod)
|
||||
if err != nil {
|
||||
m.Error = err.Error()
|
||||
|
||||
@@ -290,6 +290,23 @@ func GoModFile(path, version string) (string, error) {
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// GoModSum returns the go.sum entry for the module version's go.mod file.
|
||||
// (That is, it returns the entry listed in go.sum as "path version/go.mod".)
|
||||
func GoModSum(path, version string) (string, error) {
|
||||
if !semver.IsValid(version) {
|
||||
return "", fmt.Errorf("invalid version %q", version)
|
||||
}
|
||||
data, err := GoMod(path, version)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sum, err := goModSum(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
var errNotCached = fmt.Errorf("not in cache")
|
||||
|
||||
// readDiskStat reads a cached stat result from disk,
|
||||
|
||||
@@ -694,6 +694,10 @@ func (r *gitRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser,
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if err := ensureGitAttributes(r.dir); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// Incredibly, git produces different archives depending on whether
|
||||
// it is running on a Windows system or not, in an attempt to normalize
|
||||
// text file line endings. Setting -c core.autocrlf=input means only
|
||||
@@ -709,3 +713,43 @@ func (r *gitRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser,
|
||||
|
||||
return ioutil.NopCloser(bytes.NewReader(archive)), "", nil
|
||||
}
|
||||
|
||||
// ensureGitAttributes makes sure export-subst and export-ignore features are
|
||||
// disabled for this repo. This is intended to be run prior to running git
|
||||
// archive so that zip files are generated that produce consistent ziphashes
|
||||
// for a given revision, independent of variables such as git version and the
|
||||
// size of the repo.
|
||||
//
|
||||
// See: https://github.com/golang/go/issues/27153
|
||||
func ensureGitAttributes(repoDir string) (err error) {
|
||||
const attr = "\n* -export-subst -export-ignore\n"
|
||||
|
||||
d := repoDir + "/info"
|
||||
p := d + "/attributes"
|
||||
|
||||
if err := os.MkdirAll(d, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(p, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
closeErr := f.Close()
|
||||
if closeErr != nil {
|
||||
err = closeErr
|
||||
}
|
||||
}()
|
||||
|
||||
b, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.HasSuffix(b, []byte(attr)) {
|
||||
_, err := f.WriteString(attr)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -253,12 +253,17 @@ func checkSum(mod module.Version) {
|
||||
checkOneSum(mod, h)
|
||||
}
|
||||
|
||||
// goModSum returns the checksum for the go.mod contents.
|
||||
func goModSum(data []byte) (string, error) {
|
||||
return dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) {
|
||||
return ioutil.NopCloser(bytes.NewReader(data)), nil
|
||||
})
|
||||
}
|
||||
|
||||
// checkGoMod checks the given module's go.mod checksum;
|
||||
// data is the go.mod content.
|
||||
func checkGoMod(path, version string, data []byte) {
|
||||
h, err := dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) {
|
||||
return ioutil.NopCloser(bytes.NewReader(data)), nil
|
||||
})
|
||||
h, err := goModSum(data)
|
||||
if err != nil {
|
||||
base.Fatalf("go: verifying %s %s go.mod: %v", path, version, err)
|
||||
}
|
||||
|
||||
@@ -25,15 +25,21 @@ var (
|
||||
)
|
||||
|
||||
func isStandardImportPath(path string) bool {
|
||||
return findStandardImportPath(path) != ""
|
||||
}
|
||||
|
||||
func findStandardImportPath(path string) string {
|
||||
if search.IsStandardImportPath(path) {
|
||||
if _, err := os.Stat(filepath.Join(cfg.GOROOT, "src", path)); err == nil {
|
||||
return true
|
||||
dir := filepath.Join(cfg.GOROOT, "src", path)
|
||||
if _, err := os.Stat(dir); err == nil {
|
||||
return dir
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(cfg.GOROOT, "src/vendor", path)); err == nil {
|
||||
return true
|
||||
dir = filepath.Join(cfg.GOROOT, "src/vendor", path)
|
||||
if _, err := os.Stat(dir); err == nil {
|
||||
return dir
|
||||
}
|
||||
}
|
||||
return false
|
||||
return ""
|
||||
}
|
||||
|
||||
func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic {
|
||||
|
||||
@@ -420,7 +420,19 @@ See 'go help mod edit'.
|
||||
|
||||
The go command automatically updates go.mod each time it uses the
|
||||
module graph, to make sure go.mod always accurately reflects reality
|
||||
and is properly formatted.
|
||||
and is properly formatted. For example, consider this go.mod file:
|
||||
|
||||
module M
|
||||
|
||||
require (
|
||||
A v1
|
||||
B v1.0.0
|
||||
C v1.0.0
|
||||
D v1.2.3
|
||||
E dev
|
||||
)
|
||||
|
||||
exclude D v1.2.3
|
||||
|
||||
The update rewrites non-canonical version identifiers to semver form,
|
||||
so A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the
|
||||
|
||||
@@ -181,7 +181,7 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile
|
||||
// So we only check local module trees
|
||||
// (the main module, and any directory trees pointed at by replace directives).
|
||||
if isLocal {
|
||||
for d := dir; d != mdir && len(d) > len(mdir); d = filepath.Dir(d) {
|
||||
for d := dir; d != mdir && len(d) > len(mdir); {
|
||||
haveGoMod := haveGoModCache.Do(d, func() interface{} {
|
||||
_, err := os.Stat(filepath.Join(d, "go.mod"))
|
||||
return err == nil
|
||||
@@ -190,6 +190,13 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile
|
||||
if haveGoMod {
|
||||
return "", false
|
||||
}
|
||||
parent := filepath.Dir(d)
|
||||
if parent == d {
|
||||
// Break the loop, as otherwise we'd loop
|
||||
// forever if d=="." and mdir=="".
|
||||
break
|
||||
}
|
||||
d = parent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ var importTests = []struct {
|
||||
},
|
||||
{
|
||||
path: "golang.org/x/net",
|
||||
err: "missing module for import: golang.org/x/net@.* provides golang.org/x/net",
|
||||
err: "cannot find module providing package golang.org/x/net",
|
||||
},
|
||||
{
|
||||
path: "golang.org/x/text",
|
||||
|
||||
@@ -399,11 +399,17 @@ func ModuleUsedDirectly(path string) bool {
|
||||
func Lookup(path string) (dir, realPath string, err error) {
|
||||
pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
|
||||
if !ok {
|
||||
if isStandardImportPath(path) {
|
||||
dir := filepath.Join(cfg.GOROOT, "src", path)
|
||||
if _, err := os.Stat(dir); err == nil {
|
||||
return dir, path, nil
|
||||
}
|
||||
// The loader should have found all the relevant paths.
|
||||
// There are a few exceptions, though:
|
||||
// - during go list without -test, the p.Resolve calls to process p.TestImports and p.XTestImports
|
||||
// end up here to canonicalize the import paths.
|
||||
// - during any load, non-loaded packages like "unsafe" end up here.
|
||||
// - during any load, build-injected dependencies like "runtime/cgo" end up here.
|
||||
// - because we ignore appengine/* in the module loader,
|
||||
// the dependencies of any actual appengine/* library end up here.
|
||||
dir := findStandardImportPath(path)
|
||||
if dir != "" {
|
||||
return dir, path, nil
|
||||
}
|
||||
return "", "", errMissing
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ and test commands:
|
||||
link against shared libraries previously created with
|
||||
-buildmode=shared.
|
||||
-mod mode
|
||||
module download mode to use: readonly, release, or vendor.
|
||||
module download mode to use: readonly or vendor.
|
||||
See 'go help modules' for more.
|
||||
-pkgdir dir
|
||||
install and load all packages from dir instead of the usual locations.
|
||||
|
||||
@@ -224,7 +224,9 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
|
||||
if len(p.SFiles) > 0 {
|
||||
fmt.Fprintf(h, "asm %q %q %q\n", b.toolID("asm"), forcedAsmflags, p.Internal.Asmflags)
|
||||
}
|
||||
fmt.Fprintf(h, "GO$GOARCH=%s\n", os.Getenv("GO"+strings.ToUpper(cfg.BuildContext.GOARCH))) // GO386, GOARM, etc
|
||||
// GO386, GOARM, GOMIPS, etc.
|
||||
baseArch := strings.TrimSuffix(cfg.BuildContext.GOARCH, "le")
|
||||
fmt.Fprintf(h, "GO$GOARCH=%s\n", os.Getenv("GO"+strings.ToUpper(baseArch)))
|
||||
|
||||
// TODO(rsc): Convince compiler team not to add more magic environment variables,
|
||||
// or perhaps restrict the environment variables passed to subprocesses.
|
||||
@@ -2075,14 +2077,37 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
|
||||
}
|
||||
|
||||
// gccld runs the gcc linker to create an executable from a set of object files.
|
||||
func (b *Builder) gccld(p *load.Package, objdir, out string, flags []string, objs []string) error {
|
||||
func (b *Builder) gccld(p *load.Package, objdir, outfile string, flags []string, objs []string) error {
|
||||
var cmd []string
|
||||
if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 {
|
||||
cmd = b.GxxCmd(p.Dir, objdir)
|
||||
} else {
|
||||
cmd = b.GccCmd(p.Dir, objdir)
|
||||
}
|
||||
return b.run(nil, p.Dir, p.ImportPath, b.cCompilerEnv(), cmd, "-o", out, objs, flags)
|
||||
|
||||
cmdargs := []interface{}{cmd, "-o", outfile, objs, flags}
|
||||
dir := p.Dir
|
||||
out, err := b.runOut(dir, b.cCompilerEnv(), cmdargs...)
|
||||
if len(out) > 0 {
|
||||
// Filter out useless linker warnings caused by bugs outside Go.
|
||||
// See also cmd/link/internal/ld's hostlink method.
|
||||
var save [][]byte
|
||||
for _, line := range bytes.SplitAfter(out, []byte("\n")) {
|
||||
// golang.org/issue/26073 - Apple Xcode bug
|
||||
if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
|
||||
continue
|
||||
}
|
||||
save = append(save, line)
|
||||
}
|
||||
out = bytes.Join(save, nil)
|
||||
if len(out) > 0 {
|
||||
b.showOutput(nil, dir, p.ImportPath, b.processOutput(out))
|
||||
if err != nil {
|
||||
err = errPrintedOutput
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Grab these before main helpfully overwrites them.
|
||||
|
||||
@@ -170,6 +170,7 @@ var validLinkerFlags = []*regexp.Regexp{
|
||||
re(`-Wl,-e[=,][a-zA-Z0-9]*`),
|
||||
re(`-Wl,--enable-new-dtags`),
|
||||
re(`-Wl,--end-group`),
|
||||
re(`-Wl,--(no-)?export-dynamic`),
|
||||
re(`-Wl,-framework,[^,@\-][^,]+`),
|
||||
re(`-Wl,-headerpad_max_install_names`),
|
||||
re(`-Wl,--no-undefined`),
|
||||
|
||||
@@ -629,6 +629,9 @@ func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
|
||||
text = string(data)
|
||||
}
|
||||
|
||||
// Matching against workdir would be misleading.
|
||||
text = strings.Replace(text, ts.workdir, "$WORK", -1)
|
||||
|
||||
if neg {
|
||||
if re.MatchString(text) {
|
||||
if isGrep {
|
||||
|
||||
37
src/cmd/go/testdata/script/build_cache_gomips.txt
vendored
Normal file
37
src/cmd/go/testdata/script/build_cache_gomips.txt
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# Set up fresh GOCACHE.
|
||||
env GOCACHE=$WORK/gocache
|
||||
mkdir $GOCACHE
|
||||
|
||||
# Building for mipsle without setting GOMIPS will use floating point registers.
|
||||
env GOARCH=mipsle
|
||||
env GOOS=linux
|
||||
go build -gcflags=-S f.go
|
||||
stderr ADDD.F[0-9]+,.F[0-9]+,.F[0-9]+
|
||||
|
||||
# Clean cache
|
||||
go clean -cache
|
||||
|
||||
# Building with GOMIPS=softfloat will not use floating point registers
|
||||
env GOMIPS=softfloat
|
||||
go build -gcflags=-S f.go
|
||||
! stderr ADDD.F[0-9]+,.F[0-9]+,.F[0-9]+
|
||||
|
||||
# Clean cache
|
||||
go clean -cache
|
||||
|
||||
# Build without setting GOMIPS
|
||||
env GOMIPS=
|
||||
go build -gcflags=-S f.go
|
||||
stderr ADDD.F[0-9]+,.F[0-9]+,.F[0-9]+
|
||||
|
||||
# Building with GOMIPS should still not use floating point registers.
|
||||
env GOMIPS=softfloat
|
||||
go build -gcflags=-S f.go
|
||||
! stderr ADDD.F[0-9]+,.F[0-9]+,.F[0-9]+
|
||||
|
||||
-- f.go --
|
||||
package f
|
||||
|
||||
func F(x float64) float64 {
|
||||
return x + x
|
||||
}
|
||||
49
src/cmd/go/testdata/script/get_brace.txt
vendored
Normal file
49
src/cmd/go/testdata/script/get_brace.txt
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
[!exec:git] skip
|
||||
|
||||
# Set up some empty repositories.
|
||||
cd $WORK/_origin/foo
|
||||
exec git init
|
||||
exec git config user.name 'Nameless Gopher'
|
||||
exec git config user.email 'nobody@golang.org'
|
||||
exec git commit --allow-empty -m 'create master branch'
|
||||
|
||||
cd $WORK
|
||||
cd '_origin/{confusing}'
|
||||
exec git init
|
||||
exec git config user.name 'Nameless Gopher'
|
||||
exec git config user.email 'nobody@golang.org'
|
||||
exec git commit --allow-empty -m 'create master branch'
|
||||
|
||||
# Clone the empty repositories into GOPATH.
|
||||
# This tells the Go command where to find them: it takes the place of a user's meta-tag redirector.
|
||||
mkdir $GOPATH/src/example.com
|
||||
cd $GOPATH/src/example.com
|
||||
exec git clone $WORK/_origin/foo
|
||||
exec git clone $WORK/_origin/{confusing}
|
||||
|
||||
# Commit contents to the repositories.
|
||||
cd $WORK/_origin/foo
|
||||
exec git add main.go
|
||||
exec git commit -m 'add main'
|
||||
|
||||
cd $WORK
|
||||
cd '_origin/{confusing}'
|
||||
exec git add confusing.go
|
||||
exec git commit -m 'just try to delete this!'
|
||||
|
||||
# 'go get' should refuse to download or update the confusingly-named repo.
|
||||
cd $GOPATH/src/example.com/foo
|
||||
! go get -u 'example.com/{confusing}'
|
||||
stderr 'invalid char'
|
||||
! go get -u example.com/foo
|
||||
stderr 'invalid import path'
|
||||
! exists example.com/{confusing}
|
||||
|
||||
-- $WORK/_origin/foo/main.go --
|
||||
package main
|
||||
import _ "example.com/{confusing}"
|
||||
|
||||
func main() {}
|
||||
|
||||
-- $WORK/_origin/{confusing}/confusing.go --
|
||||
package confusing
|
||||
61
src/cmd/go/testdata/script/get_dotfiles.txt
vendored
Normal file
61
src/cmd/go/testdata/script/get_dotfiles.txt
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
[!exec:git] skip
|
||||
|
||||
# Set up a benign repository and a repository with a dotfile name.
|
||||
cd $WORK/_origin/foo
|
||||
exec git init
|
||||
exec git config user.name 'Nameless Gopher'
|
||||
exec git config user.email 'nobody@golang.org'
|
||||
exec git commit --allow-empty -m 'create master branch'
|
||||
|
||||
cd $WORK/_origin/.hidden
|
||||
exec git init
|
||||
exec git config user.name 'Nameless Gopher'
|
||||
exec git config user.email 'nobody@golang.org'
|
||||
exec git commit --allow-empty -m 'create master branch'
|
||||
|
||||
# Clone the empty repositories into GOPATH.
|
||||
# This tells the Go command where to find them: it takes the place of a user's meta-tag redirector.
|
||||
mkdir $GOPATH/src/example.com
|
||||
cd $GOPATH/src/example.com
|
||||
exec git clone $WORK/_origin/foo
|
||||
exec git clone $WORK/_origin/.hidden
|
||||
|
||||
# Add a benign commit.
|
||||
cd $WORK/_origin/foo
|
||||
cp _ok/main.go main.go
|
||||
exec git add main.go
|
||||
exec git commit -m 'add ok'
|
||||
|
||||
# 'go get' should install the benign commit.
|
||||
cd $GOPATH
|
||||
go get -u example.com/foo
|
||||
|
||||
# Now sneak in an import of a dotfile path.
|
||||
cd $WORK/_origin/.hidden
|
||||
exec git add hidden.go
|
||||
exec git commit -m 'nothing to see here, move along'
|
||||
|
||||
cd $WORK/_origin/foo
|
||||
cp _sneaky/main.go main.go
|
||||
exec git add main.go
|
||||
exec git commit -m 'fix typo (heh heh heh)'
|
||||
|
||||
# 'go get -u' should refuse to download or update the dotfile-named repo.
|
||||
cd $GOPATH/src/example.com/foo
|
||||
! go get -u example.com/foo
|
||||
stderr 'leading dot'
|
||||
! exists example.com/.hidden/hidden.go
|
||||
|
||||
-- $WORK/_origin/foo/_ok/main.go --
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
|
||||
-- $WORK/_origin/foo/_sneaky/main.go --
|
||||
package main
|
||||
import _ "example.com/.hidden"
|
||||
|
||||
func main() {}
|
||||
|
||||
-- $WORK/_origin/.hidden/hidden.go --
|
||||
package hidden
|
||||
21
src/cmd/go/testdata/script/get_tilde.txt
vendored
Normal file
21
src/cmd/go/testdata/script/get_tilde.txt
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Paths containing windows short names should be rejected before attempting to fetch.
|
||||
! go get example.com/longna~1.dir/thing
|
||||
stderr 'trailing tilde and digits'
|
||||
! go get example.com/longna~1/thing
|
||||
stderr 'trailing tilde and digits'
|
||||
! go get example.com/~9999999/thing
|
||||
stderr 'trailing tilde and digits'
|
||||
|
||||
# A path containing an element that is just a tilde, or a tilde followed by non-digits,
|
||||
# should attempt to resolve.
|
||||
! go get example.com/~glenda/notfound
|
||||
! stderr 'trailing tilde and digits'
|
||||
stderr 'unrecognized import path'
|
||||
|
||||
! go get example.com/~glenda2/notfound
|
||||
! stderr 'trailing tilde and digits'
|
||||
stderr 'unrecognized import path'
|
||||
|
||||
! go get example.com/~/notfound
|
||||
! stderr 'trailing tilde and digits'
|
||||
stderr 'unrecognized import path'
|
||||
37
src/cmd/go/testdata/script/get_unicode.txt
vendored
Normal file
37
src/cmd/go/testdata/script/get_unicode.txt
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
[!exec:git] skip
|
||||
|
||||
# Construct a repository that imports a non-ASCII path.
|
||||
cd $WORK/_origin/example.com/unicode
|
||||
exec git init
|
||||
exec git config user.name 'Nameless Gopher'
|
||||
exec git config user.email 'nobody@golang.org'
|
||||
exec git add unicode.go
|
||||
exec git commit -m 'add unicode.go'
|
||||
|
||||
# Clone the repo into GOPATH so that 'go get -u' can find it.
|
||||
mkdir $GOPATH/src/example.com/unicode
|
||||
cd $GOPATH/src/example.com/unicode
|
||||
exec git clone $WORK/_origin/example.com/unicode .
|
||||
|
||||
# Construct the imported repository.
|
||||
cd $WORK/_origin/example.com/испытание
|
||||
exec git init
|
||||
exec git config user.name 'Nameless Gopher'
|
||||
exec git config user.email 'nobody@golang.org'
|
||||
exec git add испытание.go
|
||||
exec git commit -m 'add испытание.go'
|
||||
|
||||
# Clone that repo into GOPATH too.
|
||||
mkdir $GOPATH/src/example.com/испытание
|
||||
cd $GOPATH/src/example.com/испытание
|
||||
exec git clone $WORK/_origin/example.com/испытание .
|
||||
|
||||
# Upgrading the importer should pull from the non-ASCII repo.
|
||||
cd $GOPATH
|
||||
go get -u example.com/unicode
|
||||
|
||||
-- $WORK/_origin/example.com/unicode/unicode.go --
|
||||
package unicode
|
||||
import _ "example.com/испытание"
|
||||
-- $WORK/_origin/example.com/испытание/испытание.go --
|
||||
package испытание
|
||||
2
src/cmd/go/testdata/script/mod_download.txt
vendored
2
src/cmd/go/testdata/script/mod_download.txt
vendored
@@ -15,6 +15,8 @@ stdout '^\t"Version": "v1.5.0"'
|
||||
stdout '^\t"Info": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.info"'
|
||||
stdout '^\t"GoMod": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.mod"'
|
||||
stdout '^\t"Zip": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.zip"'
|
||||
stdout '^\t"Sum": "h1:6fJa6E\+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE="' # hash of testdata/mod version, not real version!
|
||||
stdout '^\t"GoModSum": "h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe\+TKr0="'
|
||||
! stdout '"Error"'
|
||||
|
||||
# download queries above should not have added to go.mod.
|
||||
|
||||
21
src/cmd/go/testdata/script/mod_git_export_subst.txt
vendored
Normal file
21
src/cmd/go/testdata/script/mod_git_export_subst.txt
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
env GO111MODULE=on
|
||||
env GOPROXY=
|
||||
|
||||
# Testing that git export-subst is disabled
|
||||
[!net] skip
|
||||
[!exec:git] skip
|
||||
go build
|
||||
|
||||
-- x.go --
|
||||
package x
|
||||
|
||||
import _ "github.com/jasonkeene/export-subst"
|
||||
|
||||
-- go.mod --
|
||||
module x
|
||||
|
||||
require github.com/jasonkeene/export-subst v0.0.0-20180927204031-5845945ec626
|
||||
|
||||
-- go.sum --
|
||||
github.com/jasonkeene/export-subst v0.0.0-20180927204031-5845945ec626 h1:AUkXi/xFnm7lH2pgtvVkGb7buRn1ywFHw+xDpZ29Rz0=
|
||||
github.com/jasonkeene/export-subst v0.0.0-20180927204031-5845945ec626/go.mod h1:DwJXqVtrgrQkv3Giuf2Jh4YyubVe7y41S1eOIaysTJw=
|
||||
16
src/cmd/go/testdata/script/mod_list_test.txt
vendored
Normal file
16
src/cmd/go/testdata/script/mod_list_test.txt
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
env GO111MODULE=on
|
||||
|
||||
# go list -compiled -test must handle test-only packages
|
||||
# golang.org/issue/27097.
|
||||
go list -compiled -test
|
||||
stdout '^m$'
|
||||
stdout '^m\.test$'
|
||||
stdout '^m \[m\.test\]$'
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
-- x_test.go --
|
||||
package x
|
||||
import "testing"
|
||||
func Test(t *testing.T) {}
|
||||
19
src/cmd/go/testdata/script/mod_std_vendor.txt
vendored
Normal file
19
src/cmd/go/testdata/script/mod_std_vendor.txt
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
env GO111MODULE=on
|
||||
|
||||
go list -f '{{.TestImports}}'
|
||||
stdout net/http # from .TestImports
|
||||
|
||||
go list -test -f '{{.Deps}}'
|
||||
stdout golang_org/x/crypto # dep of .TestImports
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
-- x.go --
|
||||
package x
|
||||
|
||||
-- x_test.go --
|
||||
package x
|
||||
import "testing"
|
||||
import _ "net/http"
|
||||
func Test(t *testing.T) {}
|
||||
@@ -1323,9 +1323,24 @@ func (ctxt *Link) hostlink() {
|
||||
ctxt.Logf("\n")
|
||||
}
|
||||
|
||||
if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
|
||||
out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput()
|
||||
if err != nil {
|
||||
Exitf("running %s failed: %v\n%s", argv[0], err, out)
|
||||
} else if len(out) > 0 {
|
||||
}
|
||||
|
||||
// Filter out useless linker warnings caused by bugs outside Go.
|
||||
// See also cmd/go/internal/work/exec.go's gccld method.
|
||||
var save [][]byte
|
||||
for _, line := range bytes.SplitAfter(out, []byte("\n")) {
|
||||
// golang.org/issue/26073 - Apple Xcode bug
|
||||
if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
|
||||
continue
|
||||
}
|
||||
save = append(save, line)
|
||||
}
|
||||
out = bytes.Join(save, nil)
|
||||
|
||||
if len(out) > 0 {
|
||||
// always print external output even if the command is successful, so that we don't
|
||||
// swallow linker warnings (see https://golang.org/issue/17935).
|
||||
ctxt.Logf("%s", out)
|
||||
|
||||
@@ -685,13 +685,14 @@ func generateTrace(params *traceParams, consumer traceConsumer) error {
|
||||
}
|
||||
ctx.emitSlice(&fakeMarkStart, text)
|
||||
case trace.EvGCSweepStart:
|
||||
slice := ctx.emitSlice(ev, "SWEEP")
|
||||
slice := ctx.makeSlice(ev, "SWEEP")
|
||||
if done := ev.Link; done != nil && done.Args[0] != 0 {
|
||||
slice.Arg = struct {
|
||||
Swept uint64 `json:"Swept bytes"`
|
||||
Reclaimed uint64 `json:"Reclaimed bytes"`
|
||||
}{done.Args[0], done.Args[1]}
|
||||
}
|
||||
ctx.emit(slice)
|
||||
case trace.EvGoStart, trace.EvGoStartLabel:
|
||||
info := getGInfo(ev.G)
|
||||
if ev.Type == trace.EvGoStartLabel {
|
||||
@@ -846,7 +847,11 @@ func (ctx *traceContext) proc(ev *trace.Event) uint64 {
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *traceContext) emitSlice(ev *trace.Event, name string) *ViewerEvent {
|
||||
func (ctx *traceContext) emitSlice(ev *trace.Event, name string) {
|
||||
ctx.emit(ctx.makeSlice(ev, name))
|
||||
}
|
||||
|
||||
func (ctx *traceContext) makeSlice(ev *trace.Event, name string) *ViewerEvent {
|
||||
// If ViewerEvent.Dur is not a positive value,
|
||||
// trace viewer handles it as a non-terminating time interval.
|
||||
// Avoid it by setting the field with a small value.
|
||||
@@ -885,7 +890,6 @@ func (ctx *traceContext) emitSlice(ev *trace.Event, name string) *ViewerEvent {
|
||||
sl.Cname = colorLightGrey
|
||||
}
|
||||
}
|
||||
ctx.emit(sl)
|
||||
return sl
|
||||
}
|
||||
|
||||
|
||||
@@ -164,11 +164,8 @@ type ConnectionState struct {
|
||||
SignedCertificateTimestamps [][]byte // SCTs from the server, if any
|
||||
OCSPResponse []byte // stapled OCSP response from server, if any
|
||||
|
||||
// ExportKeyMaterial returns length bytes of exported key material as
|
||||
// defined in https://tools.ietf.org/html/rfc5705. If context is nil, it is
|
||||
// not used as part of the seed. If Config.Renegotiation was set to allow
|
||||
// renegotiation, this function will always return nil, false.
|
||||
ExportKeyingMaterial func(label string, context []byte, length int) ([]byte, bool)
|
||||
// ekm is a closure exposed via ExportKeyingMaterial.
|
||||
ekm func(label string, context []byte, length int) ([]byte, error)
|
||||
|
||||
// TLSUnique contains the "tls-unique" channel binding value (see RFC
|
||||
// 5929, section 3). For resumed sessions this value will be nil
|
||||
@@ -179,6 +176,14 @@ type ConnectionState struct {
|
||||
TLSUnique []byte
|
||||
}
|
||||
|
||||
// ExportKeyingMaterial returns length bytes of exported key material in a new
|
||||
// slice as defined in https://tools.ietf.org/html/rfc5705. If context is nil,
|
||||
// it is not used as part of the seed. If the connection was set to allow
|
||||
// renegotiation via Config.Renegotiation, this function will return an error.
|
||||
func (cs *ConnectionState) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
|
||||
return cs.ekm(label, context, length)
|
||||
}
|
||||
|
||||
// ClientAuthType declares the policy the server will follow for
|
||||
// TLS Client Authentication.
|
||||
type ClientAuthType int
|
||||
|
||||
@@ -56,7 +56,7 @@ type Conn struct {
|
||||
// renegotiation is not supported in that case.)
|
||||
secureRenegotiation bool
|
||||
// ekm is a closure for exporting keying material.
|
||||
ekm func(label string, context []byte, length int) ([]byte, bool)
|
||||
ekm func(label string, context []byte, length int) ([]byte, error)
|
||||
|
||||
// clientFinishedIsFirst is true if the client sent the first Finished
|
||||
// message during the most recent handshake. This is recorded because
|
||||
@@ -1315,9 +1315,9 @@ func (c *Conn) ConnectionState() ConnectionState {
|
||||
}
|
||||
}
|
||||
if c.config.Renegotiation != RenegotiateNever {
|
||||
state.ExportKeyingMaterial = noExportedKeyingMaterial
|
||||
state.ekm = noExportedKeyingMaterial
|
||||
} else {
|
||||
state.ExportKeyingMaterial = c.ekm
|
||||
state.ekm = c.ekm
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -979,6 +979,24 @@ func TestRenegotiateTwiceRejected(t *testing.T) {
|
||||
runClientTestTLS12(t, test)
|
||||
}
|
||||
|
||||
func TestHandshakeClientExportKeyingMaterial(t *testing.T) {
|
||||
test := &clientTest{
|
||||
name: "ExportKeyingMaterial",
|
||||
command: []string{"openssl", "s_server"},
|
||||
config: testConfig.Clone(),
|
||||
validate: func(state ConnectionState) error {
|
||||
if km, err := state.ExportKeyingMaterial("test", nil, 42); err != nil {
|
||||
return fmt.Errorf("ExportKeyingMaterial failed: %v", err)
|
||||
} else if len(km) != 42 {
|
||||
return fmt.Errorf("Got %d bytes from ExportKeyingMaterial, wanted %d", len(km), 42)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
runClientTestTLS10(t, test)
|
||||
runClientTestTLS12(t, test)
|
||||
}
|
||||
|
||||
var hostnameInSNITests = []struct {
|
||||
in, out string
|
||||
}{
|
||||
|
||||
@@ -998,6 +998,24 @@ func TestFallbackSCSV(t *testing.T) {
|
||||
runServerTestTLS11(t, test)
|
||||
}
|
||||
|
||||
func TestHandshakeServerExportKeyingMaterial(t *testing.T) {
|
||||
test := &serverTest{
|
||||
name: "ExportKeyingMaterial",
|
||||
command: []string{"openssl", "s_client"},
|
||||
config: testConfig.Clone(),
|
||||
validate: func(state ConnectionState) error {
|
||||
if km, err := state.ExportKeyingMaterial("test", nil, 42); err != nil {
|
||||
return fmt.Errorf("ExportKeyingMaterial failed: %v", err)
|
||||
} else if len(km) != 42 {
|
||||
return fmt.Errorf("Got %d bytes from ExportKeyingMaterial, wanted %d", len(km), 42)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
runServerTestTLS10(t, test)
|
||||
runServerTestTLS12(t, test)
|
||||
}
|
||||
|
||||
func benchmarkHandshakeServer(b *testing.B, cipherSuite uint16, curve CurveID, cert []byte, key crypto.PrivateKey) {
|
||||
config := testConfig.Clone()
|
||||
config.CipherSuites = []uint16{cipherSuite}
|
||||
|
||||
@@ -347,20 +347,20 @@ func (h *finishedHash) discardHandshakeBuffer() {
|
||||
}
|
||||
|
||||
// noExportedKeyingMaterial is used as a value of
|
||||
// ConnectionState.ExportKeyingMaterial when renegotation is enabled and thus
|
||||
// ConnectionState.ekm when renegotation is enabled and thus
|
||||
// we wish to fail all key-material export requests.
|
||||
func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, bool) {
|
||||
return nil, false
|
||||
func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
|
||||
return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled")
|
||||
}
|
||||
|
||||
// ekmFromMasterSecret generates exported keying material as defined in
|
||||
// https://tools.ietf.org/html/rfc5705.
|
||||
func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, bool) {
|
||||
return func(label string, context []byte, length int) ([]byte, bool) {
|
||||
func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) {
|
||||
return func(label string, context []byte, length int) ([]byte, error) {
|
||||
switch label {
|
||||
case "client finished", "server finished", "master secret", "key expansion":
|
||||
// These values are reserved and may not be used.
|
||||
return nil, false
|
||||
return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label)
|
||||
}
|
||||
|
||||
seedLen := len(serverRandom) + len(clientRandom)
|
||||
@@ -374,7 +374,7 @@ func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clien
|
||||
|
||||
if context != nil {
|
||||
if len(context) >= 1<<16 {
|
||||
return nil, false
|
||||
return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long")
|
||||
}
|
||||
seed = append(seed, byte(len(context)>>8), byte(len(context)))
|
||||
seed = append(seed, context...)
|
||||
@@ -382,6 +382,6 @@ func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clien
|
||||
|
||||
keyMaterial := make([]byte, length)
|
||||
prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed)
|
||||
return keyMaterial, true
|
||||
return keyMaterial, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,14 +70,14 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
|
||||
}
|
||||
|
||||
ekm := ekmFromMasterSecret(test.version, test.suite, masterSecret, clientRandom, serverRandom)
|
||||
contextKeyingMaterial, ok := ekm("label", []byte("context"), 32)
|
||||
if !ok {
|
||||
t.Fatalf("ekmFromMasterSecret failed")
|
||||
contextKeyingMaterial, err := ekm("label", []byte("context"), 32)
|
||||
if err != nil {
|
||||
t.Fatalf("ekmFromMasterSecret failed: %v", err)
|
||||
}
|
||||
|
||||
noContextKeyingMaterial, ok := ekm("label", nil, 32)
|
||||
if !ok {
|
||||
t.Fatalf("ekmFromMasterSecret failed")
|
||||
noContextKeyingMaterial, err := ekm("label", nil, 32)
|
||||
if err != nil {
|
||||
t.Fatalf("ekmFromMasterSecret failed: %v", err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(contextKeyingMaterial) != test.contextKeyingMaterial ||
|
||||
|
||||
89
src/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial
vendored
Normal file
89
src/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
>>> Flow 1 (client to server)
|
||||
00000000 16 03 01 00 95 01 00 00 91 03 03 00 00 00 00 00 |................|
|
||||
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
|
||||
00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
|
||||
00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
|
||||
00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 3c 00 05 |.............<..|
|
||||
00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
|
||||
00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 12 00 |................|
|
||||
00000080 10 04 01 04 03 05 01 05 03 06 01 06 03 02 01 02 |................|
|
||||
00000090 03 ff 01 00 01 00 00 12 00 00 |..........|
|
||||
>>> Flow 2 (server to client)
|
||||
00000000 16 03 01 00 59 02 00 00 55 03 01 67 4f 02 da 87 |....Y...U..gO...|
|
||||
00000010 52 30 9a f0 3b e0 63 42 bf 6c 18 58 00 06 70 cf |R0..;.cB.l.X..p.|
|
||||
00000020 2a 27 5a 00 a7 57 49 fe 03 dd 3b 20 7c 2c 74 00 |*'Z..WI...; |,t.|
|
||||
00000030 6e b2 35 ca 1b b5 8c 46 f7 78 ab 11 92 43 8c f6 |n.5....F.x...C..|
|
||||
00000040 97 d3 b8 07 4c 9c 95 2b 08 fe e8 82 c0 13 00 00 |....L..+........|
|
||||
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
|
||||
00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
|
||||
00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
|
||||
00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
|
||||
00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
|
||||
000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
|
||||
000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
|
||||
000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
|
||||
000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
|
||||
000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
|
||||
000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
|
||||
00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
|
||||
00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
|
||||
00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
|
||||
00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
|
||||
00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
|
||||
00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
|
||||
00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
|
||||
00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
|
||||
00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
|
||||
00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
|
||||
000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
|
||||
000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
|
||||
000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
|
||||
000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
|
||||
000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
|
||||
000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
|
||||
00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
|
||||
00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
|
||||
00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
|
||||
00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
|
||||
00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
|
||||
00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
|
||||
00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
|
||||
00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
|
||||
00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
|
||||
00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
|
||||
000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
|
||||
000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......|
|
||||
000002c0 aa 0c 00 00 a6 03 00 1d 20 a0 0e 1d 92 2d b0 a5 |........ ....-..|
|
||||
000002d0 f0 ab d5 79 a0 bb 12 ff 23 46 bc 27 0d 73 ff 3e |...y....#F.'.s.>|
|
||||
000002e0 ad 06 d6 57 6b c2 11 76 2d 00 80 77 bf cd 2b cb |...Wk..v-..w..+.|
|
||||
000002f0 66 c2 fa 30 ed b1 e7 44 79 1b 28 e6 89 62 17 07 |f..0...Dy.(..b..|
|
||||
00000300 82 c1 5f dc b2 20 4e 42 ed 54 d6 28 3a 2a e3 a3 |.._.. NB.T.(:*..|
|
||||
00000310 79 06 e3 08 3c c1 3e b9 c6 41 71 2f d0 29 82 36 |y...<.>..Aq/.).6|
|
||||
00000320 ef 8d 67 c8 77 d0 32 d3 33 5f 77 92 dd 98 bb 03 |..g.w.2.3_w.....|
|
||||
00000330 cc 0b a6 75 8f 4a 1d f5 6e 1b 06 5b 4a 8b 16 a4 |...u.J..n..[J...|
|
||||
00000340 c1 ce 11 9d 70 bc 62 7f 58 a5 86 76 91 3d 3a 04 |....p.b.X..v.=:.|
|
||||
00000350 93 92 89 42 9b a7 7d 9d 75 25 6d 98 f3 e6 68 7e |...B..}.u%m...h~|
|
||||
00000360 a8 c6 b1 db a7 95 63 39 94 5a 05 16 03 01 00 04 |......c9.Z......|
|
||||
00000370 0e 00 00 00 |....|
|
||||
>>> Flow 3 (client to server)
|
||||
00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
|
||||
00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
|
||||
00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......|
|
||||
00000030 16 03 01 00 30 73 ad 46 66 66 e8 bd 44 e4 bf 71 |....0s.Fff..D..q|
|
||||
00000040 a2 d4 87 e2 4b a3 4a b2 a0 ca ed ac 61 8c 1e 7f |....K.J.....a...|
|
||||
00000050 68 bf 6f 98 b1 fb 10 1a 5a e6 36 61 91 ac c4 55 |h.o.....Z.6a...U|
|
||||
00000060 a3 4d 69 66 6e |.Mifn|
|
||||
>>> Flow 4 (server to client)
|
||||
00000000 14 03 01 00 01 01 16 03 01 00 30 57 aa 5c d5 dc |..........0W.\..|
|
||||
00000010 83 4b 23 80 34 4e 36 e8 d6 f3 40 7e ae 12 44 a6 |.K#.4N6...@~..D.|
|
||||
00000020 c7 48 99 99 0a 85 3c 59 75 32 4e 88 3c 98 a0 23 |.H....<Yu2N.<..#|
|
||||
00000030 78 c8 a7 2b 43 25 6a ad d1 78 54 |x..+C%j..xT|
|
||||
>>> Flow 5 (client to server)
|
||||
00000000 17 03 01 00 20 e4 9c f4 fa 6b e8 85 87 6f 20 45 |.... ....k...o E|
|
||||
00000010 71 d3 e2 9e e3 14 2a 7c 64 e8 11 53 fd 93 c1 4a |q.....*|d..S...J|
|
||||
00000020 1b 94 f8 48 78 17 03 01 00 20 b9 41 32 1d e8 70 |...Hx.... .A2..p|
|
||||
00000030 87 5f 2c c6 67 d1 77 3c 30 83 0c 66 35 eb 1d da |._,.g.w<0..f5...|
|
||||
00000040 6e dd 30 ff 82 05 5f f1 cd e7 15 03 01 00 20 6c |n.0..._....... l|
|
||||
00000050 47 82 5e 90 5b 84 15 78 05 bd 48 63 d5 46 2f 7e |G.^.[..x..Hc.F/~|
|
||||
00000060 83 49 ce 3c 0f 04 92 52 5b e7 d5 cf 2c bf 65 |.I.<...R[...,.e|
|
||||
84
src/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial
vendored
Normal file
84
src/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
>>> Flow 1 (client to server)
|
||||
00000000 16 03 01 00 95 01 00 00 91 03 03 00 00 00 00 00 |................|
|
||||
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
|
||||
00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
|
||||
00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
|
||||
00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 3c 00 05 |.............<..|
|
||||
00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
|
||||
00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 12 00 |................|
|
||||
00000080 10 04 01 04 03 05 01 05 03 06 01 06 03 02 01 02 |................|
|
||||
00000090 03 ff 01 00 01 00 00 12 00 00 |..........|
|
||||
>>> Flow 2 (server to client)
|
||||
00000000 16 03 03 00 59 02 00 00 55 03 03 fc 37 e8 a4 e3 |....Y...U...7...|
|
||||
00000010 5d da a5 95 0b fb e0 c3 d9 78 8b 91 bd 5c 1c b1 |]........x...\..|
|
||||
00000020 c6 8d 69 62 f9 c6 0f 12 da 46 ba 20 34 a3 22 f2 |..ib.....F. 4.".|
|
||||
00000030 a9 f7 da 3a c4 5f 6f f7 4b be df 03 e5 b6 d0 ff |...:._o.K.......|
|
||||
00000040 ca 54 68 59 57 53 63 a5 2f 91 1d 1e cc a8 00 00 |.ThYWSc./.......|
|
||||
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
|
||||
00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
|
||||
00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
|
||||
00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
|
||||
00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
|
||||
000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
|
||||
000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
|
||||
000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
|
||||
000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
|
||||
000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
|
||||
000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
|
||||
00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
|
||||
00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
|
||||
00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
|
||||
00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
|
||||
00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
|
||||
00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
|
||||
00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
|
||||
00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
|
||||
00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
|
||||
00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
|
||||
000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
|
||||
000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
|
||||
000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
|
||||
000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
|
||||
000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
|
||||
000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
|
||||
00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
|
||||
00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
|
||||
00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
|
||||
00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
|
||||
00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
|
||||
00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
|
||||
00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
|
||||
00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
|
||||
00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
|
||||
00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
|
||||
000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
|
||||
000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
|
||||
000002c0 ac 0c 00 00 a8 03 00 1d 20 cc e9 71 f5 36 52 5a |........ ..q.6RZ|
|
||||
000002d0 d8 19 ce e4 0d 41 8d a6 9b f3 19 56 8d 81 fe 84 |.....A.....V....|
|
||||
000002e0 71 2f d7 fb e7 86 23 4c 04 04 01 00 80 90 da 29 |q/....#L.......)|
|
||||
000002f0 79 18 70 e8 81 66 83 70 97 f1 d1 5f dc 1d a2 0a |y.p..f.p..._....|
|
||||
00000300 94 d8 e8 b8 32 4f 03 34 0b af e8 2d 94 b2 eb 30 |....2O.4...-...0|
|
||||
00000310 57 b5 a5 92 9e 9a df a6 bc 3e 25 0e 18 cb ea 84 |W........>%.....|
|
||||
00000320 34 89 08 8a d4 be 16 a3 5d 3a 7d 32 10 9b 41 1c |4.......]:}2..A.|
|
||||
00000330 2a 1e 05 68 5f fa d9 56 30 b6 44 08 b0 a5 25 5a |*..h_..V0.D...%Z|
|
||||
00000340 c3 60 c0 9a 98 fd 48 5f a4 18 d0 15 0f fb b3 ea |.`....H_........|
|
||||
00000350 b9 c4 e3 c6 0c 27 51 64 01 de 65 78 c7 a0 57 df |.....'Qd..ex..W.|
|
||||
00000360 9b de 2f 74 bc 72 e5 e0 57 7c 59 e6 ae 16 03 03 |../t.r..W|Y.....|
|
||||
00000370 00 04 0e 00 00 00 |......|
|
||||
>>> Flow 3 (client to server)
|
||||
00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
|
||||
00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
|
||||
00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
|
||||
00000030 16 03 03 00 20 92 0a 4e aa 2d b3 9b c8 b9 80 28 |.... ..N.-.....(|
|
||||
00000040 f3 22 e2 57 15 ff a1 9a 33 9b e8 4c 5c dc f4 29 |.".W....3..L\..)|
|
||||
00000050 7d 25 d7 df bc |}%...|
|
||||
>>> Flow 4 (server to client)
|
||||
00000000 14 03 03 00 01 01 16 03 03 00 20 91 85 06 0e 00 |.......... .....|
|
||||
00000010 ad 96 2e 1c a5 4d f7 63 f9 84 1c 6e da 54 0b e0 |.....M.c...n.T..|
|
||||
00000020 44 37 6a 90 4c fd f5 e8 45 1d ce |D7j.L...E..|
|
||||
>>> Flow 5 (client to server)
|
||||
00000000 17 03 03 00 16 4c e8 8a e0 a6 95 f3 df 37 8a 2d |.....L.......7.-|
|
||||
00000010 4f 11 ce a6 53 16 2c b0 bb c5 7f 15 03 03 00 12 |O...S.,.........|
|
||||
00000020 4e 91 d8 67 c5 16 d2 4e cc b8 0a 00 76 91 68 7a |N..g...N....v.hz|
|
||||
00000030 85 2e |..|
|
||||
92
src/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial
vendored
Normal file
92
src/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
>>> Flow 1 (client to server)
|
||||
00000000 16 03 01 00 61 01 00 00 5d 03 01 f4 ec 99 73 ec |....a...].....s.|
|
||||
00000010 36 30 c7 0b 26 33 a2 c4 26 8e 9f 04 f7 5b e7 4f |60..&3..&....[.O|
|
||||
00000020 86 85 14 bf f7 49 96 a4 ae c9 1d 00 00 12 c0 0a |.....I..........|
|
||||
00000030 c0 14 00 39 c0 09 c0 13 00 33 00 35 00 2f 00 ff |...9.....3.5./..|
|
||||
00000040 01 00 00 22 00 0b 00 04 03 00 01 02 00 0a 00 0a |..."............|
|
||||
00000050 00 08 00 1d 00 17 00 19 00 18 00 23 00 00 00 16 |...........#....|
|
||||
00000060 00 00 00 17 00 00 |......|
|
||||
>>> Flow 2 (server to client)
|
||||
00000000 16 03 01 00 35 02 00 00 31 03 01 00 00 00 00 00 |....5...1.......|
|
||||
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 00 |................|
|
||||
00000030 09 00 23 00 00 ff 01 00 01 00 16 03 01 02 59 0b |..#...........Y.|
|
||||
00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..|
|
||||
00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.|
|
||||
00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........|
|
||||
00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1|
|
||||
00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
|
||||
00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000|
|
||||
000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
|
||||
000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go|
|
||||
000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..|
|
||||
000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........|
|
||||
000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...|
|
||||
000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R|
|
||||
00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....|
|
||||
00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.|
|
||||
00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..|
|
||||
00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.|
|
||||
00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.|
|
||||
00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C|
|
||||
00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......|
|
||||
00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......|
|
||||
00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.|
|
||||
00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...|
|
||||
000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......|
|
||||
000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........|
|
||||
000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..|
|
||||
000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~|
|
||||
000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.|
|
||||
000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g|
|
||||
00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....|
|
||||
00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.|
|
||||
00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.|
|
||||
00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....|
|
||||
00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ |
|
||||
00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\|
|
||||
00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...|
|
||||
00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.|
|
||||
00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`|
|
||||
00000290 84 5c 21 d3 3b e9 fa e7 16 03 01 00 aa 0c 00 00 |.\!.;...........|
|
||||
000002a0 a6 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 28 da |.... /.}.G.bC.(.|
|
||||
000002b0 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........|
|
||||
000002c0 5f 58 cb 3b 74 00 80 8e fe 28 f2 06 d8 b9 d6 74 |_X.;t....(.....t|
|
||||
000002d0 72 34 dc fa 00 38 56 1a fc a1 68 e8 ca 8f 7a 61 |r4...8V...h...za|
|
||||
000002e0 92 e2 2a 63 ce 4d 96 c6 bb 84 82 41 2d 97 35 13 |..*c.M.....A-.5.|
|
||||
000002f0 e1 ff 4c ec f2 e6 62 16 15 35 da 8a 57 55 cb 28 |..L...b..5..WU.(|
|
||||
00000300 26 35 e6 86 00 b0 92 44 b7 40 7b 6a c4 b0 b8 10 |&5.....D.@{j....|
|
||||
00000310 b7 16 97 a7 26 eb 1e 0b 99 b3 22 4a 6b 7f 0b 69 |....&....."Jk..i|
|
||||
00000320 0d 21 1e 33 6d fd 78 b5 62 68 53 db 62 69 ba b4 |.!.3m.x.bhS.bi..|
|
||||
00000330 bc 74 b3 d4 ce a2 41 d7 ba 62 aa cc b2 39 65 86 |.t....A..b...9e.|
|
||||
00000340 5f 00 68 e2 16 a5 13 16 03 01 00 04 0e 00 00 00 |_.h.............|
|
||||
>>> Flow 3 (client to server)
|
||||
00000000 16 03 01 00 25 10 00 00 21 20 81 08 e4 37 1d 03 |....%...! ...7..|
|
||||
00000010 87 5a 00 68 ae 49 76 08 4a e2 20 82 0b e5 7c 3e |.Z.h.Iv.J. ...|>|
|
||||
00000020 90 49 9b c3 b9 c7 c9 3c 29 24 14 03 01 00 01 01 |.I.....<)$......|
|
||||
00000030 16 03 01 00 30 33 07 d5 08 ca ae f9 70 50 93 0a |....03......pP..|
|
||||
00000040 55 2e e0 df 1d 88 ae 1e 06 17 47 64 a3 52 36 37 |U.........Gd.R67|
|
||||
00000050 d5 ca f1 b1 d2 76 7b f8 89 59 13 e9 ab b1 cb dc |.....v{..Y......|
|
||||
00000060 1f a8 89 f4 2f |..../|
|
||||
>>> Flow 4 (server to client)
|
||||
00000000 16 03 01 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
|
||||
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
|
||||
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
|
||||
00000030 6d ec a4 83 61 a4 a1 9c 14 de f8 59 c8 c7 f0 10 |m...a......Y....|
|
||||
00000040 08 fe c9 37 29 ed 47 05 d2 bd a8 4c 05 b9 8c f8 |...7).G....L....|
|
||||
00000050 b5 4d e4 a6 30 0f 49 4a b1 73 1f 89 73 c8 bb 36 |.M..0.IJ.s..s..6|
|
||||
00000060 14 9d d2 95 70 33 94 fb 82 e6 fe 3e 64 8c 9d e8 |....p3.....>d...|
|
||||
00000070 e3 e5 93 3d fe 4e 23 a3 97 8a a3 91 80 c9 00 01 |...=.N#.........|
|
||||
00000080 a6 f0 47 cf 11 a6 90 14 03 01 00 01 01 16 03 01 |..G.............|
|
||||
00000090 00 30 1f 70 17 a1 30 82 5a 32 e7 aa a1 7f 1b f6 |.0.p..0.Z2......|
|
||||
000000a0 d8 aa 6a 51 64 1b 4a f1 94 12 08 2f 5d 95 fe 83 |..jQd.J..../]...|
|
||||
000000b0 52 c8 3b d4 58 73 50 19 b8 08 61 b3 3a 5d f6 d3 |R.;.XsP...a.:]..|
|
||||
000000c0 67 e6 17 03 01 00 20 bd 79 44 08 9d 86 cf 5e e9 |g..... .yD....^.|
|
||||
000000d0 e4 3c 80 ed b7 18 10 07 0f 42 85 ca a4 51 fd 9b |.<.......B...Q..|
|
||||
000000e0 38 3e 04 7e 72 6e 80 17 03 01 00 30 2c 46 c2 71 |8>.~rn.....0,F.q|
|
||||
000000f0 4a 83 46 eb 63 87 f5 83 b4 72 70 4f a3 59 b3 ff |J.F.c....rpO.Y..|
|
||||
00000100 3c 00 74 12 db 33 51 4c 7c e0 c1 27 44 20 68 25 |<.t..3QL|..'D h%|
|
||||
00000110 95 f1 37 2a 24 f1 85 a3 5a e4 50 fe 15 03 01 00 |..7*$...Z.P.....|
|
||||
00000120 20 72 01 cc 74 d5 b4 6b 05 ce de f0 b4 fe 4f 6b | r..t..k......Ok|
|
||||
00000130 a8 8f ad 5a c2 7d 40 65 d6 a2 57 52 b8 8a c5 4f |...Z.}@e..WR...O|
|
||||
00000140 d9 |.|
|
||||
92
src/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial
vendored
Normal file
92
src/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
>>> Flow 1 (client to server)
|
||||
00000000 16 03 01 00 ab 01 00 00 a7 03 03 7a 49 9d 20 62 |...........zI. b|
|
||||
00000010 45 8d 0c 1e 8e eb b1 5e 73 62 6d 48 61 31 cb 1a |E......^sbmHa1..|
|
||||
00000020 89 b2 68 1b 2c cb 35 87 2a 17 fb 00 00 38 c0 2c |..h.,.5.*....8.,|
|
||||
00000030 c0 30 00 9f cc a9 cc a8 cc aa c0 2b c0 2f 00 9e |.0.........+./..|
|
||||
00000040 c0 24 c0 28 00 6b c0 23 c0 27 00 67 c0 0a c0 14 |.$.(.k.#.'.g....|
|
||||
00000050 00 39 c0 09 c0 13 00 33 00 9d 00 9c 00 3d 00 3c |.9.....3.....=.<|
|
||||
00000060 00 35 00 2f 00 ff 01 00 00 46 00 0b 00 04 03 00 |.5./.....F......|
|
||||
00000070 01 02 00 0a 00 0a 00 08 00 1d 00 17 00 19 00 18 |................|
|
||||
00000080 00 23 00 00 00 16 00 00 00 17 00 00 00 0d 00 20 |.#............. |
|
||||
00000090 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 |................|
|
||||
000000a0 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 |................|
|
||||
>>> Flow 2 (server to client)
|
||||
00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......|
|
||||
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 30 00 00 |.............0..|
|
||||
00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 59 0b |..#...........Y.|
|
||||
00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..|
|
||||
00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.|
|
||||
00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........|
|
||||
00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1|
|
||||
00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
|
||||
00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000|
|
||||
000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
|
||||
000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go|
|
||||
000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..|
|
||||
000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........|
|
||||
000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...|
|
||||
000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R|
|
||||
00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....|
|
||||
00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.|
|
||||
00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..|
|
||||
00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.|
|
||||
00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.|
|
||||
00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C|
|
||||
00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......|
|
||||
00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......|
|
||||
00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.|
|
||||
00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...|
|
||||
000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......|
|
||||
000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........|
|
||||
000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..|
|
||||
000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~|
|
||||
000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.|
|
||||
000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g|
|
||||
00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....|
|
||||
00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.|
|
||||
00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.|
|
||||
00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....|
|
||||
00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ |
|
||||
00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\|
|
||||
00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...|
|
||||
00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.|
|
||||
00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`|
|
||||
00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 00 |.\!.;...........|
|
||||
000002a0 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 28 da |.... /.}.G.bC.(.|
|
||||
000002b0 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........|
|
||||
000002c0 5f 58 cb 3b 74 06 01 00 80 7f ee dd 6b 38 23 29 |_X.;t.......k8#)|
|
||||
000002d0 56 ff d2 c2 08 86 52 b6 e3 8a d5 fe 47 79 5e ef |V.....R.....Gy^.|
|
||||
000002e0 99 7a 0b d7 44 84 b9 2f 7a 2c 64 4f b3 7c aa 44 |.z..D../z,dO.|.D|
|
||||
000002f0 aa 38 5d 1b 69 16 9f f2 7d f8 24 43 47 ad 31 bc |.8].i...}.$CG.1.|
|
||||
00000300 f5 3d b8 c8 33 6e 3f 6f 2b ea 19 a2 30 32 2b 2a |.=..3n?o+...02+*|
|
||||
00000310 81 64 3c ee ed 78 4c fa 80 fd e7 5f ef 85 98 d4 |.d<..xL...._....|
|
||||
00000320 48 06 b8 f5 5e 1e e6 f3 42 a8 2f 99 5f ea b3 ba |H...^...B./._...|
|
||||
00000330 8e a8 31 99 85 f2 46 11 a3 d2 c6 81 4b f1 22 7d |..1...F.....K."}|
|
||||
00000340 d7 45 04 f1 a6 d6 7e 8f 9d 16 03 03 00 04 0e 00 |.E....~.........|
|
||||
00000350 00 00 |..|
|
||||
>>> Flow 3 (client to server)
|
||||
00000000 16 03 03 00 25 10 00 00 21 20 22 e7 e7 61 a9 27 |....%...! "..a.'|
|
||||
00000010 7b 93 d1 42 76 dd 16 32 e8 92 37 37 2f fd 0d 92 |{..Bv..2..77/...|
|
||||
00000020 1f 8e b7 c5 69 40 d3 1a 7d 06 14 03 03 00 01 01 |....i@..}.......|
|
||||
00000030 16 03 03 00 28 4e 7f b2 a2 20 5d cf a1 5a de 42 |....(N... ]..Z.B|
|
||||
00000040 c5 72 c3 ef c3 23 a7 2c f3 5b 3d a4 81 21 ac db |.r...#.,.[=..!..|
|
||||
00000050 44 1c f3 a1 83 aa a1 b7 85 9a c7 23 03 |D..........#.|
|
||||
>>> Flow 4 (server to client)
|
||||
00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
|
||||
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
|
||||
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
|
||||
00000030 6f ec 80 83 61 3f 55 e3 9d ab 39 87 5b d0 ba 44 |o...a?U...9.[..D|
|
||||
00000040 07 91 a8 d0 37 8a 7e 51 0d 00 97 ec 1b 61 f3 3b |....7.~Q.....a.;|
|
||||
00000050 9f 29 24 d5 98 f7 4d 3b 80 ef 2f 4d aa 02 98 93 |.)$...M;../M....|
|
||||
00000060 81 03 87 d8 06 33 94 f5 ed 5d cc 8f 57 97 70 26 |.....3...]..W.p&|
|
||||
00000070 00 dc 0d d2 96 16 a2 6d fc be 8d 4b fa 5f b3 04 |.......m...K._..|
|
||||
00000080 ce bb 48 ee c0 75 23 14 03 03 00 01 01 16 03 03 |..H..u#.........|
|
||||
00000090 00 28 00 00 00 00 00 00 00 00 3a 69 e0 40 e2 d1 |.(........:i.@..|
|
||||
000000a0 a6 96 33 0f b3 58 5a dc 41 ea d1 80 44 66 9f 2e |..3..XZ.A...Df..|
|
||||
000000b0 00 e4 9e 10 13 56 b4 1b c9 42 17 03 03 00 25 00 |.....V...B....%.|
|
||||
000000c0 00 00 00 00 00 00 01 88 f3 d9 5b ed 6b 3c 70 0c |..........[.k<p.|
|
||||
000000d0 df 36 9d 1c f6 f6 83 38 53 ad e2 06 47 3c e2 9f |.6.....8S...G<..|
|
||||
000000e0 42 87 d7 8a 15 03 03 00 1a 00 00 00 00 00 00 00 |B...............|
|
||||
000000f0 02 df 4a 92 13 c4 e6 ac 76 25 c6 72 27 be d6 09 |..J.....v%.r'...|
|
||||
00000100 eb 90 ed |...|
|
||||
@@ -7,6 +7,7 @@ package tls
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
@@ -907,3 +908,11 @@ func BenchmarkLatency(b *testing.B) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectionStateMarshal(t *testing.T) {
|
||||
cs := &ConnectionState{}
|
||||
_, err := json.Marshal(cs)
|
||||
if err != nil {
|
||||
t.Errorf("json.Marshal failed on ConnectionState: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,32 +65,16 @@ func SystemCertPool() (*CertPool, error) {
|
||||
return loadSystemRoots()
|
||||
}
|
||||
|
||||
// findVerifiedParents attempts to find certificates in s which have signed the
|
||||
// given certificate. If any candidates were rejected then errCert will be set
|
||||
// to one of them, arbitrarily, and err will contain the reason that it was
|
||||
// rejected.
|
||||
func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
|
||||
// findPotentialParents returns the indexes of certificates in s which might
|
||||
// have signed cert. The caller must not modify the returned slice.
|
||||
func (s *CertPool) findPotentialParents(cert *Certificate) []int {
|
||||
if s == nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
var candidates []int
|
||||
|
||||
if len(cert.AuthorityKeyId) > 0 {
|
||||
candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
|
||||
return s.bySubjectKeyId[string(cert.AuthorityKeyId)]
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
candidates = s.byName[string(cert.RawIssuer)]
|
||||
}
|
||||
|
||||
for _, c := range candidates {
|
||||
if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
|
||||
parents = append(parents, c)
|
||||
} else {
|
||||
errCert = s.certs[c]
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return s.byName[string(cert.RawIssuer)]
|
||||
}
|
||||
|
||||
func (s *CertPool) contains(cert *Certificate) bool {
|
||||
|
||||
@@ -765,7 +765,7 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
|
||||
if opts.Roots.contains(c) {
|
||||
candidateChains = append(candidateChains, []*Certificate{c})
|
||||
} else {
|
||||
if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil {
|
||||
if candidateChains, err = c.buildChains(nil, []*Certificate{c}, nil, &opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -802,58 +802,74 @@ func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate
|
||||
return n
|
||||
}
|
||||
|
||||
func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c)
|
||||
nextRoot:
|
||||
for _, rootNum := range possibleRoots {
|
||||
root := opts.Roots.certs[rootNum]
|
||||
// maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls
|
||||
// that an invocation of buildChains will (tranistively) make. Most chains are
|
||||
// less than 15 certificates long, so this leaves space for multiple chains and
|
||||
// for failed checks due to different intermediates having the same Subject.
|
||||
const maxChainSignatureChecks = 100
|
||||
|
||||
func (c *Certificate) buildChains(cache map[*Certificate][][]*Certificate, currentChain []*Certificate, sigChecks *int, opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
var (
|
||||
hintErr error
|
||||
hintCert *Certificate
|
||||
)
|
||||
|
||||
considerCandidate := func(certType int, candidate *Certificate) {
|
||||
for _, cert := range currentChain {
|
||||
if cert.Equal(root) {
|
||||
continue nextRoot
|
||||
if cert.Equal(candidate) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = root.isValid(rootCertificate, currentChain, opts)
|
||||
if err != nil {
|
||||
continue
|
||||
if sigChecks == nil {
|
||||
sigChecks = new(int)
|
||||
}
|
||||
*sigChecks++
|
||||
if *sigChecks > maxChainSignatureChecks {
|
||||
err = errors.New("x509: signature check attempts limit reached while verifying certificate chain")
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.CheckSignatureFrom(candidate); err != nil {
|
||||
if hintErr == nil {
|
||||
hintErr = err
|
||||
hintCert = candidate
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
err = candidate.isValid(certType, currentChain, opts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch certType {
|
||||
case rootCertificate:
|
||||
chains = append(chains, appendToFreshChain(currentChain, candidate))
|
||||
case intermediateCertificate:
|
||||
if cache == nil {
|
||||
cache = make(map[*Certificate][][]*Certificate)
|
||||
}
|
||||
childChains, ok := cache[candidate]
|
||||
if !ok {
|
||||
childChains, err = candidate.buildChains(cache, appendToFreshChain(currentChain, candidate), sigChecks, opts)
|
||||
cache[candidate] = childChains
|
||||
}
|
||||
chains = append(chains, childChains...)
|
||||
}
|
||||
chains = append(chains, appendToFreshChain(currentChain, root))
|
||||
}
|
||||
|
||||
possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c)
|
||||
nextIntermediate:
|
||||
for _, intermediateNum := range possibleIntermediates {
|
||||
intermediate := opts.Intermediates.certs[intermediateNum]
|
||||
for _, cert := range currentChain {
|
||||
if cert.Equal(intermediate) {
|
||||
continue nextIntermediate
|
||||
}
|
||||
}
|
||||
err = intermediate.isValid(intermediateCertificate, currentChain, opts)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var childChains [][]*Certificate
|
||||
childChains, ok := cache[intermediateNum]
|
||||
if !ok {
|
||||
childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts)
|
||||
cache[intermediateNum] = childChains
|
||||
}
|
||||
chains = append(chains, childChains...)
|
||||
for _, rootNum := range opts.Roots.findPotentialParents(c) {
|
||||
considerCandidate(rootCertificate, opts.Roots.certs[rootNum])
|
||||
}
|
||||
for _, intermediateNum := range opts.Intermediates.findPotentialParents(c) {
|
||||
considerCandidate(intermediateCertificate, opts.Intermediates.certs[intermediateNum])
|
||||
}
|
||||
|
||||
if len(chains) > 0 {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if len(chains) == 0 && err == nil {
|
||||
hintErr := rootErr
|
||||
hintCert := failedRoot
|
||||
if hintErr == nil {
|
||||
hintErr = intermediateErr
|
||||
hintCert = failedIntermediate
|
||||
}
|
||||
err = UnknownAuthorityError{c, hintErr, hintCert}
|
||||
}
|
||||
|
||||
@@ -894,8 +910,8 @@ func validHostname(host string) bool {
|
||||
if c == '-' && j != 0 {
|
||||
continue
|
||||
}
|
||||
if c == '_' {
|
||||
// _ is not a valid character in hostnames, but it's commonly
|
||||
if c == '_' || c == ':' {
|
||||
// Not valid characters in hostnames, but commonly
|
||||
// found in deployments outside the WebPKI.
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -5,10 +5,15 @@
|
||||
package x509
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -1881,6 +1886,7 @@ func TestValidHostname(t *testing.T) {
|
||||
{"foo.*.example.com", false},
|
||||
{"exa_mple.com", true},
|
||||
{"foo,bar", false},
|
||||
{"project-dev:us-central1:main", true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := validHostname(tt.host); got != tt.want {
|
||||
@@ -1888,3 +1894,117 @@ func TestValidHostname(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateCert(cn string, isCA bool, issuer *Certificate, issuerKey crypto.PrivateKey) (*Certificate, crypto.PrivateKey, error) {
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||
serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit)
|
||||
|
||||
template := &Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
Subject: pkix.Name{CommonName: cn},
|
||||
NotBefore: time.Now().Add(-1 * time.Hour),
|
||||
NotAfter: time.Now().Add(24 * time.Hour),
|
||||
|
||||
KeyUsage: KeyUsageKeyEncipherment | KeyUsageDigitalSignature | KeyUsageCertSign,
|
||||
ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: isCA,
|
||||
}
|
||||
if issuer == nil {
|
||||
issuer = template
|
||||
issuerKey = priv
|
||||
}
|
||||
|
||||
derBytes, err := CreateCertificate(rand.Reader, template, issuer, priv.Public(), issuerKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
cert, err := ParseCertificate(derBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return cert, priv, nil
|
||||
}
|
||||
|
||||
func TestPathologicalChain(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping generation of a long chain of certificates in short mode")
|
||||
}
|
||||
|
||||
// Build a chain where all intermediates share the same subject, to hit the
|
||||
// path building worst behavior.
|
||||
roots, intermediates := NewCertPool(), NewCertPool()
|
||||
|
||||
parent, parentKey, err := generateCert("Root CA", true, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
roots.AddCert(parent)
|
||||
|
||||
for i := 1; i < 100; i++ {
|
||||
parent, parentKey, err = generateCert("Intermediate CA", true, parent, parentKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
intermediates.AddCert(parent)
|
||||
}
|
||||
|
||||
leaf, _, err := generateCert("Leaf", false, parent, parentKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
_, err = leaf.Verify(VerifyOptions{
|
||||
Roots: roots,
|
||||
Intermediates: intermediates,
|
||||
})
|
||||
t.Logf("verification took %v", time.Since(start))
|
||||
|
||||
if err == nil || !strings.Contains(err.Error(), "signature check attempts limit") {
|
||||
t.Errorf("expected verification to fail with a signature checks limit error; got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLongChain(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping generation of a long chain of certificates in short mode")
|
||||
}
|
||||
|
||||
roots, intermediates := NewCertPool(), NewCertPool()
|
||||
|
||||
parent, parentKey, err := generateCert("Root CA", true, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
roots.AddCert(parent)
|
||||
|
||||
for i := 1; i < 15; i++ {
|
||||
name := fmt.Sprintf("Intermediate CA #%d", i)
|
||||
parent, parentKey, err = generateCert(name, true, parent, parentKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
intermediates.AddCert(parent)
|
||||
}
|
||||
|
||||
leaf, _, err := generateCert("Leaf", false, parent, parentKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
if _, err := leaf.Verify(VerifyOptions{
|
||||
Roots: roots,
|
||||
Intermediates: intermediates,
|
||||
}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
t.Logf("verification took %v", time.Since(start))
|
||||
}
|
||||
|
||||
@@ -1322,11 +1322,13 @@ func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
|
||||
err: err,
|
||||
}
|
||||
return true
|
||||
} else if err == nil && !db.closed && db.maxIdleConnsLocked() > len(db.freeConn) {
|
||||
db.freeConn = append(db.freeConn, dc)
|
||||
} else if err == nil && !db.closed {
|
||||
if db.maxIdleConnsLocked() > len(db.freeConn) {
|
||||
db.freeConn = append(db.freeConn, dc)
|
||||
db.startCleanerLocked()
|
||||
return true
|
||||
}
|
||||
db.maxIdleClosed++
|
||||
db.startCleanerLocked()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -3415,6 +3415,58 @@ func TestConnectionLeak(t *testing.T) {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestStatsMaxIdleClosedZero(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(1)
|
||||
db.SetConnMaxLifetime(0)
|
||||
|
||||
preMaxIdleClosed := db.Stats().MaxIdleClosed
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
rows, err := db.Query("SELECT|people|name|")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rows.Close()
|
||||
}
|
||||
|
||||
st := db.Stats()
|
||||
maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed
|
||||
t.Logf("MaxIdleClosed: %d", maxIdleClosed)
|
||||
if maxIdleClosed != 0 {
|
||||
t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsMaxIdleClosedTen(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(0)
|
||||
db.SetConnMaxLifetime(0)
|
||||
|
||||
preMaxIdleClosed := db.Stats().MaxIdleClosed
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
rows, err := db.Query("SELECT|people|name|")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rows.Close()
|
||||
}
|
||||
|
||||
st := db.Stats()
|
||||
maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed
|
||||
t.Logf("MaxIdleClosed: %d", maxIdleClosed)
|
||||
if maxIdleClosed != 10 {
|
||||
t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed)
|
||||
}
|
||||
}
|
||||
|
||||
type nvcDriver struct {
|
||||
fakeDriver
|
||||
skipNamedValueCheck bool
|
||||
|
||||
@@ -672,6 +672,7 @@ func (d *decodeState) object(v reflect.Value) error {
|
||||
}
|
||||
|
||||
var mapElem reflect.Value
|
||||
originalErrorContext := d.errorContext
|
||||
|
||||
for {
|
||||
// Read opening " of string key or closing }.
|
||||
@@ -832,8 +833,7 @@ func (d *decodeState) object(v reflect.Value) error {
|
||||
return errPhase
|
||||
}
|
||||
|
||||
d.errorContext.Struct = ""
|
||||
d.errorContext.Field = ""
|
||||
d.errorContext = originalErrorContext
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -991,7 +991,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||
if fromQuoted {
|
||||
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
|
||||
}
|
||||
return &UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}
|
||||
d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
|
||||
case reflect.Interface:
|
||||
n, err := d.convertNumber(s)
|
||||
if err != nil {
|
||||
|
||||
@@ -371,6 +371,10 @@ func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error {
|
||||
return (*intWithMarshalText)(b).UnmarshalText(data)
|
||||
}
|
||||
|
||||
type mapStringToStringData struct {
|
||||
Data map[string]string `json:"data"`
|
||||
}
|
||||
|
||||
type unmarshalTest struct {
|
||||
in string
|
||||
ptr interface{}
|
||||
@@ -401,6 +405,7 @@ var unmarshalTests = []unmarshalTest{
|
||||
{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
|
||||
{in: "null", ptr: new(interface{}), out: nil},
|
||||
{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}},
|
||||
{in: `{"X": 23}`, ptr: new(T), out: T{}, err: &UnmarshalTypeError{"number", reflect.TypeOf(""), 8, "T", "X"}}, {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
|
||||
{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
|
||||
{in: `{"x": 1}`, ptr: new(tx), err: fmt.Errorf("json: unknown field \"x\""), disallowUnknownFields: true},
|
||||
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
|
||||
@@ -866,6 +871,18 @@ var unmarshalTests = []unmarshalTest{
|
||||
err: fmt.Errorf("json: unknown field \"extra\""),
|
||||
disallowUnknownFields: true,
|
||||
},
|
||||
// issue 26444
|
||||
// UnmarshalTypeError without field & struct values
|
||||
{
|
||||
in: `{"data":{"test1": "bob", "test2": 123}}`,
|
||||
ptr: new(mapStringToStringData),
|
||||
err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 37, Struct: "mapStringToStringData", Field: "data"},
|
||||
},
|
||||
{
|
||||
in: `{"data":{"test1": 123, "test2": "bob"}}`,
|
||||
ptr: new(mapStringToStringData),
|
||||
err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 21, Struct: "mapStringToStringData", Field: "data"},
|
||||
},
|
||||
}
|
||||
|
||||
func TestMarshal(t *testing.T) {
|
||||
|
||||
@@ -261,6 +261,8 @@ func TestTypesInfo(t *testing.T) {
|
||||
{`package x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
|
||||
{`package x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
|
||||
{`package x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`},
|
||||
{`package x3; var x = panic("");`, `panic`, `func(interface{})`},
|
||||
{`package x4; func _() { panic("") }`, `panic`, `func(interface{})`},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
@@ -476,7 +476,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
// panic(x)
|
||||
// record panic call if inside a function with result parameters
|
||||
// (for use in Checker.isTerminating)
|
||||
if check.sig.results.Len() > 0 {
|
||||
if check.sig != nil && check.sig.results.Len() > 0 {
|
||||
// function has result parameters
|
||||
p := check.isPanic
|
||||
if p == nil {
|
||||
|
||||
@@ -355,3 +355,70 @@ func TestIssue25627(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue28005(t *testing.T) {
|
||||
// method names must match defining interface name for this test
|
||||
// (see last comment in this function)
|
||||
sources := [...]string{
|
||||
"package p; type A interface{ A() }",
|
||||
"package p; type B interface{ B() }",
|
||||
"package p; type X interface{ A; B }",
|
||||
}
|
||||
|
||||
// compute original file ASTs
|
||||
var orig [len(sources)]*ast.File
|
||||
for i, src := range sources {
|
||||
f, err := parser.ParseFile(fset, "", src, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
orig[i] = f
|
||||
}
|
||||
|
||||
// run the test for all order permutations of the incoming files
|
||||
for _, perm := range [][len(sources)]int{
|
||||
{0, 1, 2},
|
||||
{0, 2, 1},
|
||||
{1, 0, 2},
|
||||
{1, 2, 0},
|
||||
{2, 0, 1},
|
||||
{2, 1, 0},
|
||||
} {
|
||||
// create file order permutation
|
||||
files := make([]*ast.File, len(sources))
|
||||
for i := range perm {
|
||||
files[i] = orig[perm[i]]
|
||||
}
|
||||
|
||||
// type-check package with given file order permutation
|
||||
var conf Config
|
||||
info := &Info{Defs: make(map[*ast.Ident]Object)}
|
||||
_, err := conf.Check("", fset, files, info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// look for interface object X
|
||||
var obj Object
|
||||
for name, def := range info.Defs {
|
||||
if name.Name == "X" {
|
||||
obj = def
|
||||
break
|
||||
}
|
||||
}
|
||||
if obj == nil {
|
||||
t.Fatal("interface not found")
|
||||
}
|
||||
iface := obj.Type().Underlying().(*Interface) // I must be an interface
|
||||
|
||||
// Each iface method m is embedded; and m's receiver base type name
|
||||
// must match the method's name per the choice in the source file.
|
||||
for i := 0; i < iface.NumMethods(); i++ {
|
||||
m := iface.Method(i)
|
||||
recvName := m.Type().(*Signature).Recv().Type().(*Named).Obj().Name()
|
||||
if recvName != m.Name() {
|
||||
t.Errorf("perm %v: got recv %s; want %s", perm, recvName, m.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,6 +571,15 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
|
||||
recvTyp = def
|
||||
}
|
||||
|
||||
// Correct receiver type for all methods explicitly declared
|
||||
// by this interface after we're done with type-checking at
|
||||
// this level. See comment below for details.
|
||||
check.later(func() {
|
||||
for _, m := range ityp.methods {
|
||||
m.typ.(*Signature).recv.typ = recvTyp
|
||||
}
|
||||
})
|
||||
|
||||
// collect methods
|
||||
var sigfix []*methodInfo
|
||||
for i, minfo := range info.methods {
|
||||
@@ -580,9 +589,27 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
|
||||
pos := name.Pos()
|
||||
// Don't type-check signature yet - use an
|
||||
// empty signature now and update it later.
|
||||
// Since we know the receiver, set it up now
|
||||
// (required to avoid crash in ptrRecv; see
|
||||
// e.g. test case for issue 6638).
|
||||
// But set up receiver since we know it and
|
||||
// its position, and because interface method
|
||||
// signatures don't get a receiver via regular
|
||||
// type-checking (there isn't a receiver in the
|
||||
// method's AST). Setting the receiver type is
|
||||
// also important for ptrRecv() (see methodset.go).
|
||||
//
|
||||
// Note: For embedded methods, the receiver type
|
||||
// should be the type of the interface that declared
|
||||
// the methods in the first place. Since we get the
|
||||
// methods here via methodInfo, which may be computed
|
||||
// before we have all relevant interface types, we use
|
||||
// the current interface's type (recvType). This may be
|
||||
// the type of the interface embedding the interface that
|
||||
// declared the methods. This doesn't matter for type-
|
||||
// checking (we only care about the receiver type for
|
||||
// the ptrRecv predicate, and it's never a pointer recv
|
||||
// for interfaces), but it matters for go/types clients
|
||||
// and for printing. We correct the receiver after type-
|
||||
// checking.
|
||||
//
|
||||
// TODO(gri) Consider marking methods signatures
|
||||
// as incomplete, for better error messages. See
|
||||
// also the T4 and T5 tests in testdata/cycles2.src.
|
||||
|
||||
@@ -32,11 +32,17 @@ func SendFile(fd *FD, src syscall.Handle, n int64) (int64, error) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
o.o.OffsetHigh = uint32(curpos)
|
||||
o.o.Offset = uint32(curpos >> 32)
|
||||
o.o.Offset = uint32(curpos)
|
||||
o.o.OffsetHigh = uint32(curpos >> 32)
|
||||
|
||||
done, err := wsrv.ExecIO(o, func(o *operation) error {
|
||||
return syscall.TransmitFile(o.fd.Sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
|
||||
})
|
||||
if err == nil {
|
||||
// Some versions of Windows (Windows 10 1803) do not set
|
||||
// file position after TransmitFile completes.
|
||||
// So just use Seek to set file position.
|
||||
_, err = syscall.Seek(o.handle, curpos+int64(done), 0)
|
||||
}
|
||||
return int64(done), err
|
||||
}
|
||||
|
||||
@@ -27,6 +27,20 @@ import (
|
||||
"golang_org/x/net/dns/dnsmessage"
|
||||
)
|
||||
|
||||
var (
|
||||
errLameReferral = errors.New("lame referral")
|
||||
errCannotUnmarshalDNSMessage = errors.New("cannot unmarshal DNS message")
|
||||
errCannotMarshalDNSMessage = errors.New("cannot marshal DNS message")
|
||||
errServerMisbehaving = errors.New("server misbehaving")
|
||||
errInvalidDNSResponse = errors.New("invalid DNS response")
|
||||
errNoAnswerFromDNSServer = errors.New("no answer from DNS server")
|
||||
|
||||
// errServerTemporarlyMisbehaving is like errServerMisbehaving, except
|
||||
// that when it gets translated to a DNSError, the IsTemporary field
|
||||
// gets set to true.
|
||||
errServerTemporarlyMisbehaving = errors.New("server misbehaving")
|
||||
)
|
||||
|
||||
func newRequest(q dnsmessage.Question) (id uint16, udpReq, tcpReq []byte, err error) {
|
||||
id = uint16(rand.Int()) ^ uint16(time.Now().UnixNano())
|
||||
b := dnsmessage.NewBuilder(make([]byte, 2, 514), dnsmessage.Header{ID: id, RecursionDesired: true})
|
||||
@@ -105,14 +119,14 @@ func dnsStreamRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte)
|
||||
var p dnsmessage.Parser
|
||||
h, err := p.Start(b[:n])
|
||||
if err != nil {
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot unmarshal DNS message")
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
|
||||
}
|
||||
q, err := p.Question()
|
||||
if err != nil {
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot unmarshal DNS message")
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
|
||||
}
|
||||
if !checkResponse(id, query, h, q) {
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("invalid DNS response")
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
|
||||
}
|
||||
return p, h, nil
|
||||
}
|
||||
@@ -122,7 +136,7 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
|
||||
q.Class = dnsmessage.ClassINET
|
||||
id, udpReq, tcpReq, err := newRequest(q)
|
||||
if err != nil {
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot marshal DNS message")
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotMarshalDNSMessage
|
||||
}
|
||||
for _, network := range []string{"udp", "tcp"} {
|
||||
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(timeout))
|
||||
@@ -147,31 +161,31 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, mapErr(err)
|
||||
}
|
||||
if err := p.SkipQuestion(); err != dnsmessage.ErrSectionDone {
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("invalid DNS response")
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
|
||||
}
|
||||
if h.Truncated { // see RFC 5966
|
||||
continue
|
||||
}
|
||||
return p, h, nil
|
||||
}
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("no answer from DNS server")
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, errNoAnswerFromDNSServer
|
||||
}
|
||||
|
||||
// checkHeader performs basic sanity checks on the header.
|
||||
func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string) error {
|
||||
if h.RCode == dnsmessage.RCodeNameError {
|
||||
return errNoSuchHost
|
||||
}
|
||||
|
||||
_, err := p.AnswerHeader()
|
||||
if err != nil && err != dnsmessage.ErrSectionDone {
|
||||
return &DNSError{
|
||||
Err: "cannot unmarshal DNS message",
|
||||
Name: name,
|
||||
Server: server,
|
||||
}
|
||||
return errCannotUnmarshalDNSMessage
|
||||
}
|
||||
|
||||
// libresolv continues to the next server when it receives
|
||||
// an invalid referral response. See golang.org/issue/15434.
|
||||
if h.RCode == dnsmessage.RCodeSuccess && !h.Authoritative && !h.RecursionAvailable && err == dnsmessage.ErrSectionDone {
|
||||
return &DNSError{Err: "lame referral", Name: name, Server: server}
|
||||
return errLameReferral
|
||||
}
|
||||
|
||||
if h.RCode != dnsmessage.RCodeSuccess && h.RCode != dnsmessage.RCodeNameError {
|
||||
@@ -180,11 +194,10 @@ func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string)
|
||||
// a name error and we didn't get success,
|
||||
// the server is behaving incorrectly or
|
||||
// having temporary trouble.
|
||||
err := &DNSError{Err: "server misbehaving", Name: name, Server: server}
|
||||
if h.RCode == dnsmessage.RCodeServerFailure {
|
||||
err.IsTemporary = true
|
||||
return errServerTemporarlyMisbehaving
|
||||
}
|
||||
return err
|
||||
return errServerMisbehaving
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -194,28 +207,16 @@ func skipToAnswer(p *dnsmessage.Parser, qtype dnsmessage.Type, name, server stri
|
||||
for {
|
||||
h, err := p.AnswerHeader()
|
||||
if err == dnsmessage.ErrSectionDone {
|
||||
return &DNSError{
|
||||
Err: errNoSuchHost.Error(),
|
||||
Name: name,
|
||||
Server: server,
|
||||
}
|
||||
return errNoSuchHost
|
||||
}
|
||||
if err != nil {
|
||||
return &DNSError{
|
||||
Err: "cannot unmarshal DNS message",
|
||||
Name: name,
|
||||
Server: server,
|
||||
}
|
||||
return errCannotUnmarshalDNSMessage
|
||||
}
|
||||
if h.Type == qtype {
|
||||
return nil
|
||||
}
|
||||
if err := p.SkipAnswer(); err != nil {
|
||||
return &DNSError{
|
||||
Err: "cannot unmarshal DNS message",
|
||||
Name: name,
|
||||
Server: server,
|
||||
}
|
||||
return errCannotUnmarshalDNSMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -229,7 +230,7 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
|
||||
|
||||
n, err := dnsmessage.NewName(name)
|
||||
if err != nil {
|
||||
return dnsmessage.Parser{}, "", errors.New("cannot marshal DNS message")
|
||||
return dnsmessage.Parser{}, "", errCannotMarshalDNSMessage
|
||||
}
|
||||
q := dnsmessage.Question{
|
||||
Name: n,
|
||||
@@ -243,38 +244,62 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
|
||||
|
||||
p, h, err := r.exchange(ctx, server, q, cfg.timeout)
|
||||
if err != nil {
|
||||
lastErr = &DNSError{
|
||||
dnsErr := &DNSError{
|
||||
Err: err.Error(),
|
||||
Name: name,
|
||||
Server: server,
|
||||
}
|
||||
if nerr, ok := err.(Error); ok && nerr.Timeout() {
|
||||
lastErr.(*DNSError).IsTimeout = true
|
||||
dnsErr.IsTimeout = true
|
||||
}
|
||||
// Set IsTemporary for socket-level errors. Note that this flag
|
||||
// may also be used to indicate a SERVFAIL response.
|
||||
if _, ok := err.(*OpError); ok {
|
||||
lastErr.(*DNSError).IsTemporary = true
|
||||
dnsErr.IsTemporary = true
|
||||
}
|
||||
lastErr = dnsErr
|
||||
continue
|
||||
}
|
||||
|
||||
// The name does not exist, so trying another server won't help.
|
||||
//
|
||||
// TODO: indicate this in a more obvious way, such as a field on DNSError?
|
||||
if h.RCode == dnsmessage.RCodeNameError {
|
||||
return dnsmessage.Parser{}, "", &DNSError{Err: errNoSuchHost.Error(), Name: name, Server: server}
|
||||
}
|
||||
|
||||
lastErr = checkHeader(&p, h, name, server)
|
||||
if lastErr != nil {
|
||||
if err := checkHeader(&p, h, name, server); err != nil {
|
||||
dnsErr := &DNSError{
|
||||
Err: err.Error(),
|
||||
Name: name,
|
||||
Server: server,
|
||||
}
|
||||
if err == errServerTemporarlyMisbehaving {
|
||||
dnsErr.IsTemporary = true
|
||||
}
|
||||
if err == errNoSuchHost {
|
||||
// The name does not exist, so trying
|
||||
// another server won't help.
|
||||
//
|
||||
// TODO: indicate this in a more
|
||||
// obvious way, such as a field on
|
||||
// DNSError?
|
||||
return p, server, dnsErr
|
||||
}
|
||||
lastErr = dnsErr
|
||||
continue
|
||||
}
|
||||
|
||||
lastErr = skipToAnswer(&p, qtype, name, server)
|
||||
if lastErr == nil {
|
||||
err = skipToAnswer(&p, qtype, name, server)
|
||||
if err == nil {
|
||||
return p, server, nil
|
||||
}
|
||||
lastErr = &DNSError{
|
||||
Err: err.Error(),
|
||||
Name: name,
|
||||
Server: server,
|
||||
}
|
||||
if err == errNoSuchHost {
|
||||
// The name does not exist, so trying another
|
||||
// server won't help.
|
||||
//
|
||||
// TODO: indicate this in a more obvious way,
|
||||
// such as a field on DNSError?
|
||||
return p, server, lastErr
|
||||
}
|
||||
}
|
||||
}
|
||||
return dnsmessage.Parser{}, "", lastErr
|
||||
|
||||
@@ -1427,28 +1427,35 @@ func TestDNSGoroutineRace(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func lookupWithFake(fake fakeDNSServer, name string, typ dnsmessage.Type) error {
|
||||
r := Resolver{PreferGo: true, Dial: fake.DialContext}
|
||||
|
||||
resolvConf.mu.RLock()
|
||||
conf := resolvConf.dnsConfig
|
||||
resolvConf.mu.RUnlock()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
_, _, err := r.tryOneName(ctx, conf, name, typ)
|
||||
return err
|
||||
}
|
||||
|
||||
// Issue 8434: verify that Temporary returns true on an error when rcode
|
||||
// is SERVFAIL
|
||||
func TestIssue8434(t *testing.T) {
|
||||
msg := dnsmessage.Message{
|
||||
Header: dnsmessage.Header{
|
||||
RCode: dnsmessage.RCodeServerFailure,
|
||||
err := lookupWithFake(fakeDNSServer{
|
||||
rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
|
||||
return dnsmessage.Message{
|
||||
Header: dnsmessage.Header{
|
||||
ID: q.ID,
|
||||
Response: true,
|
||||
RCode: dnsmessage.RCodeServerFailure,
|
||||
},
|
||||
Questions: q.Questions,
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
b, err := msg.Pack()
|
||||
if err != nil {
|
||||
t.Fatal("Pack failed:", err)
|
||||
}
|
||||
var p dnsmessage.Parser
|
||||
h, err := p.Start(b)
|
||||
if err != nil {
|
||||
t.Fatal("Start failed:", err)
|
||||
}
|
||||
if err := p.SkipAllQuestions(); err != nil {
|
||||
t.Fatal("SkipAllQuestions failed:", err)
|
||||
}
|
||||
|
||||
err = checkHeader(&p, h, "golang.org", "foo:53")
|
||||
}, "golang.org.", dnsmessage.TypeALL)
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
@@ -1464,50 +1471,76 @@ func TestIssue8434(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 12778: verify that NXDOMAIN without RA bit errors as
|
||||
// "no such host" and not "server misbehaving"
|
||||
// TestNoSuchHost verifies that tryOneName works correctly when the domain does
|
||||
// not exist.
|
||||
//
|
||||
// Issue 12778: verify that NXDOMAIN without RA bit errors as "no such host"
|
||||
// and not "server misbehaving"
|
||||
//
|
||||
// Issue 25336: verify that NXDOMAIN errors fail fast.
|
||||
func TestIssue12778(t *testing.T) {
|
||||
lookups := 0
|
||||
fake := fakeDNSServer{
|
||||
rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
|
||||
lookups++
|
||||
return dnsmessage.Message{
|
||||
Header: dnsmessage.Header{
|
||||
ID: q.ID,
|
||||
Response: true,
|
||||
RCode: dnsmessage.RCodeNameError,
|
||||
RecursionAvailable: false,
|
||||
},
|
||||
Questions: q.Questions,
|
||||
}, nil
|
||||
//
|
||||
// Issue 27525: verify that empty answers fail fast.
|
||||
func TestNoSuchHost(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
f func(string, string, dnsmessage.Message, time.Time) (dnsmessage.Message, error)
|
||||
}{
|
||||
{
|
||||
"NXDOMAIN",
|
||||
func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
|
||||
return dnsmessage.Message{
|
||||
Header: dnsmessage.Header{
|
||||
ID: q.ID,
|
||||
Response: true,
|
||||
RCode: dnsmessage.RCodeNameError,
|
||||
RecursionAvailable: false,
|
||||
},
|
||||
Questions: q.Questions,
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
"no answers",
|
||||
func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
|
||||
return dnsmessage.Message{
|
||||
Header: dnsmessage.Header{
|
||||
ID: q.ID,
|
||||
Response: true,
|
||||
RCode: dnsmessage.RCodeSuccess,
|
||||
RecursionAvailable: false,
|
||||
Authoritative: true,
|
||||
},
|
||||
Questions: q.Questions,
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
r := Resolver{PreferGo: true, Dial: fake.DialContext}
|
||||
|
||||
resolvConf.mu.RLock()
|
||||
conf := resolvConf.dnsConfig
|
||||
resolvConf.mu.RUnlock()
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
lookups := 0
|
||||
err := lookupWithFake(fakeDNSServer{
|
||||
rh: func(n, s string, q dnsmessage.Message, d time.Time) (dnsmessage.Message, error) {
|
||||
lookups++
|
||||
return test.f(n, s, q, d)
|
||||
},
|
||||
}, ".", dnsmessage.TypeALL)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
if lookups != 1 {
|
||||
t.Errorf("got %d lookups, wanted 1", lookups)
|
||||
}
|
||||
|
||||
_, _, err := r.tryOneName(ctx, conf, ".", dnsmessage.TypeALL)
|
||||
|
||||
if lookups != 1 {
|
||||
t.Errorf("got %d lookups, wanted 1", lookups)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
de, ok := err.(*DNSError)
|
||||
if !ok {
|
||||
t.Fatalf("err = %#v; wanted a *net.DNSError", err)
|
||||
}
|
||||
if de.Err != errNoSuchHost.Error() {
|
||||
t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error())
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
de, ok := err.(*DNSError)
|
||||
if !ok {
|
||||
t.Fatalf("err = %#v; wanted a *net.DNSError", err)
|
||||
}
|
||||
if de.Err != errNoSuchHost.Error() {
|
||||
t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1535,3 +1568,56 @@ func TestDNSDialTCP(t *testing.T) {
|
||||
t.Fatal("exhange failed:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 27763: verify that two strings in one TXT record are concatenated.
|
||||
func TestTXTRecordTwoStrings(t *testing.T) {
|
||||
fake := fakeDNSServer{
|
||||
rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
|
||||
r := dnsmessage.Message{
|
||||
Header: dnsmessage.Header{
|
||||
ID: q.Header.ID,
|
||||
Response: true,
|
||||
RCode: dnsmessage.RCodeSuccess,
|
||||
},
|
||||
Questions: q.Questions,
|
||||
Answers: []dnsmessage.Resource{
|
||||
{
|
||||
Header: dnsmessage.ResourceHeader{
|
||||
Name: q.Questions[0].Name,
|
||||
Type: dnsmessage.TypeA,
|
||||
Class: dnsmessage.ClassINET,
|
||||
},
|
||||
Body: &dnsmessage.TXTResource{
|
||||
TXT: []string{"string1 ", "string2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: dnsmessage.ResourceHeader{
|
||||
Name: q.Questions[0].Name,
|
||||
Type: dnsmessage.TypeA,
|
||||
Class: dnsmessage.ClassINET,
|
||||
},
|
||||
Body: &dnsmessage.TXTResource{
|
||||
TXT: []string{"onestring"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return r, nil
|
||||
},
|
||||
}
|
||||
r := Resolver{PreferGo: true, Dial: fake.DialContext}
|
||||
txt, err := r.lookupTXT(context.Background(), "golang.org")
|
||||
if err != nil {
|
||||
t.Fatal("LookupTXT failed:", err)
|
||||
}
|
||||
if want := 2; len(txt) != want {
|
||||
t.Fatalf("len(txt), got %d, want %d", len(txt), want)
|
||||
}
|
||||
if want := "string1 string2"; txt[0] != want {
|
||||
t.Errorf("txt[0], got %q, want %q", txt[0], want)
|
||||
}
|
||||
if want := "onestring"; txt[1] != want {
|
||||
t.Errorf("txt[1], got %q, want %q", txt[1], want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
|
||||
|
||||
b := result.Get("body")
|
||||
var body io.ReadCloser
|
||||
if b != js.Undefined() {
|
||||
// The body is undefined when the browser does not support streaming response bodies (Firefox),
|
||||
// and null in certain error cases, i.e. when the request is blocked because of CORS settings.
|
||||
if b != js.Undefined() && b != js.Null() {
|
||||
body = &streamReader{stream: b.Call("getReader")}
|
||||
} else {
|
||||
// Fall back to using ArrayBuffer
|
||||
|
||||
@@ -299,11 +299,21 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error)
|
||||
Server: server,
|
||||
}
|
||||
}
|
||||
if len(txts) == 0 {
|
||||
txts = txt.TXT
|
||||
} else {
|
||||
txts = append(txts, txt.TXT...)
|
||||
// Multiple strings in one TXT record need to be
|
||||
// concatenated without separator to be consistent
|
||||
// with previous Go resolver.
|
||||
n := 0
|
||||
for _, s := range txt.TXT {
|
||||
n += len(s)
|
||||
}
|
||||
txtJoin := make([]byte, 0, n)
|
||||
for _, s := range txt.TXT {
|
||||
txtJoin = append(txtJoin, s...)
|
||||
}
|
||||
if len(txts) == 0 {
|
||||
txts = make([]string, 0, 1)
|
||||
}
|
||||
txts = append(txts, string(txtJoin))
|
||||
}
|
||||
return txts, nil
|
||||
}
|
||||
|
||||
@@ -149,3 +149,64 @@ func TestSendfileParts(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendfileSeeked(t *testing.T) {
|
||||
ln, err := newLocalListener("tcp")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
const seekTo = 65 << 10
|
||||
const sendSize = 10 << 10
|
||||
|
||||
errc := make(chan error, 1)
|
||||
go func(ln Listener) {
|
||||
// Wait for a connection.
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
errc <- err
|
||||
close(errc)
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(errc)
|
||||
defer conn.Close()
|
||||
|
||||
f, err := os.Open(twain)
|
||||
if err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err := f.Seek(seekTo, os.SEEK_SET); err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
|
||||
_, err = io.CopyN(conn, f, sendSize)
|
||||
if err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
}()
|
||||
}(ln)
|
||||
|
||||
c, err := Dial("tcp", ln.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(c)
|
||||
|
||||
if buf.Len() != sendSize {
|
||||
t.Errorf("Got %d bytes; want %d", buf.Len(), sendSize)
|
||||
}
|
||||
|
||||
for err := range errc {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ func testSpliceBig(t *testing.T) {
|
||||
func testSpliceHonorsLimitedReader(t *testing.T) {
|
||||
t.Run("stopsAfterN", testSpliceStopsAfterN)
|
||||
t.Run("updatesN", testSpliceUpdatesN)
|
||||
t.Run("readerAtLimit", testSpliceReaderAtLimit)
|
||||
}
|
||||
|
||||
func testSpliceStopsAfterN(t *testing.T) {
|
||||
@@ -208,7 +209,7 @@ func testSpliceUpdatesN(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testSpliceReaderAtEOF(t *testing.T) {
|
||||
func testSpliceReaderAtLimit(t *testing.T) {
|
||||
clientUp, serverUp, err := spliceTestSocketPair("tcp")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -222,21 +223,63 @@ func testSpliceReaderAtEOF(t *testing.T) {
|
||||
defer clientDown.Close()
|
||||
defer serverDown.Close()
|
||||
|
||||
serverUp.Close()
|
||||
_, err, handled := splice(serverDown.(*TCPConn).fd, serverUp)
|
||||
if !handled {
|
||||
t.Errorf("closed connection: got err = %v, handled = %t, want handled = true", err, handled)
|
||||
}
|
||||
lr := &io.LimitedReader{
|
||||
N: 0,
|
||||
R: serverUp,
|
||||
}
|
||||
_, err, handled = splice(serverDown.(*TCPConn).fd, lr)
|
||||
_, err, handled := splice(serverDown.(*TCPConn).fd, lr)
|
||||
if !handled {
|
||||
t.Errorf("exhausted LimitedReader: got err = %v, handled = %t, want handled = true", err, handled)
|
||||
}
|
||||
}
|
||||
|
||||
func testSpliceReaderAtEOF(t *testing.T) {
|
||||
clientUp, serverUp, err := spliceTestSocketPair("tcp")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer clientUp.Close()
|
||||
clientDown, serverDown, err := spliceTestSocketPair("tcp")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer clientDown.Close()
|
||||
|
||||
serverUp.Close()
|
||||
|
||||
// We'd like to call net.splice here and check the handled return
|
||||
// value, but we disable splice on old Linux kernels.
|
||||
//
|
||||
// In that case, poll.Splice and net.splice return a non-nil error
|
||||
// and handled == false. We'd ideally like to see handled == true
|
||||
// because the source reader is at EOF, but if we're running on an old
|
||||
// kernel, and splice is disabled, we won't see EOF from net.splice,
|
||||
// because we won't touch the reader at all.
|
||||
//
|
||||
// Trying to untangle the errors from net.splice and match them
|
||||
// against the errors created by the poll package would be brittle,
|
||||
// so this is a higher level test.
|
||||
//
|
||||
// The following ReadFrom should return immediately, regardless of
|
||||
// whether splice is disabled or not. The other side should then
|
||||
// get a goodbye signal. Test for the goodbye signal.
|
||||
msg := "bye"
|
||||
go func() {
|
||||
serverDown.(*TCPConn).ReadFrom(serverUp)
|
||||
io.WriteString(serverDown, msg)
|
||||
serverDown.Close()
|
||||
}()
|
||||
|
||||
buf := make([]byte, 3)
|
||||
_, err = io.ReadFull(clientDown, buf)
|
||||
if err != nil {
|
||||
t.Errorf("clientDown: %v", err)
|
||||
}
|
||||
if string(buf) != msg {
|
||||
t.Errorf("clientDown got %q, want %q", buf, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func testSpliceIssue25985(t *testing.T) {
|
||||
front, err := newLocalListener("tcp")
|
||||
if err != nil {
|
||||
|
||||
@@ -5844,7 +5844,7 @@ func clobber() {
|
||||
type funcLayoutTest struct {
|
||||
rcvr, t Type
|
||||
size, argsize, retOffset uintptr
|
||||
stack []byte // pointer bitmap: 1 is pointer, 0 is scalar (or uninitialized)
|
||||
stack []byte // pointer bitmap: 1 is pointer, 0 is scalar
|
||||
gc []byte
|
||||
}
|
||||
|
||||
@@ -5866,7 +5866,7 @@ func init() {
|
||||
6 * PtrSize,
|
||||
4 * PtrSize,
|
||||
4 * PtrSize,
|
||||
[]byte{1, 0, 1},
|
||||
[]byte{1, 0, 1, 0, 1},
|
||||
[]byte{1, 0, 1, 0, 1},
|
||||
})
|
||||
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No argsize here, gc generates argsize info at call site.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVL DX, 0(SP)
|
||||
LEAL argframe+0(FP), CX
|
||||
MOVL CX, 4(SP)
|
||||
MOVB $0, 12(SP)
|
||||
LEAL 12(SP), AX
|
||||
MOVL AX, 8(SP)
|
||||
CALL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No argsize here, gc generates argsize info at call site.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVL DX, 0(SP)
|
||||
LEAL argframe+0(FP), CX
|
||||
MOVL CX, 4(SP)
|
||||
MOVB $0, 12(SP)
|
||||
LEAL 12(SP), AX
|
||||
MOVL AX, 8(SP)
|
||||
CALL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
MOVQ DX, 0(SP)
|
||||
LEAQ argframe+0(FP), CX
|
||||
MOVQ CX, 8(SP)
|
||||
MOVB $0, 24(SP)
|
||||
LEAQ 24(SP), AX
|
||||
MOVQ AX, 16(SP)
|
||||
CALL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
MOVQ DX, 0(SP)
|
||||
LEAQ argframe+0(FP), CX
|
||||
MOVQ CX, 8(SP)
|
||||
MOVB $0, 24(SP)
|
||||
LEAQ 24(SP), AX
|
||||
MOVQ AX, 16(SP)
|
||||
CALL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No argsize here, gc generates argsize info at call site.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVL DX, 0(SP)
|
||||
LEAL argframe+0(FP), CX
|
||||
MOVL CX, 4(SP)
|
||||
MOVB $0, 12(SP)
|
||||
LEAL 12(SP), AX
|
||||
MOVL AX, 8(SP)
|
||||
CALL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No argsize here, gc generates argsize info at call site.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVL DX, 0(SP)
|
||||
LEAL argframe+0(FP), CX
|
||||
MOVL CX, 4(SP)
|
||||
MOVB $0, 12(SP)
|
||||
LEAL 12(SP), AX
|
||||
MOVL AX, 8(SP)
|
||||
CALL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -9,11 +9,15 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No argsize here, gc generates argsize info at call site.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVW R7, 4(R13)
|
||||
MOVW $argframe+0(FP), R1
|
||||
MOVW R1, 8(R13)
|
||||
MOVW $0, R1
|
||||
MOVB R1, 16(R13)
|
||||
ADD $16, R13, R1
|
||||
MOVW R1, 12(R13)
|
||||
BL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -21,10 +25,14 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No argsize here, gc generates argsize info at call site.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVW R7, 4(R13)
|
||||
MOVW $argframe+0(FP), R1
|
||||
MOVW R1, 8(R13)
|
||||
MOVW $0, R1
|
||||
MOVB R1, 16(R13)
|
||||
ADD $16, R13, R1
|
||||
MOVW R1, 12(R13)
|
||||
BL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here, runtime pulls arg map out of the func value.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$24
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$40
|
||||
NO_LOCAL_POINTERS
|
||||
MOVD R26, 8(RSP)
|
||||
MOVD $argframe+0(FP), R3
|
||||
MOVD R3, 16(RSP)
|
||||
MOVB $0, 32(RSP)
|
||||
ADD $32, RSP, R3
|
||||
MOVD R3, 24(RSP)
|
||||
BL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$24
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$24
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$40
|
||||
NO_LOCAL_POINTERS
|
||||
MOVD R26, 8(RSP)
|
||||
MOVD $argframe+0(FP), R3
|
||||
MOVD R3, 16(RSP)
|
||||
MOVB $0, 32(RSP)
|
||||
ADD $32, RSP, R3
|
||||
MOVD R3, 24(RSP)
|
||||
BL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -13,11 +13,14 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here, runtime pulls arg map out of the func value.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
MOVV REGCTXT, 8(R29)
|
||||
MOVV $argframe+0(FP), R1
|
||||
MOVV R1, 16(R29)
|
||||
MOVB R0, 32(R29)
|
||||
ADDV $32, R29, R1
|
||||
MOVV R1, 24(R29)
|
||||
JAL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -25,10 +28,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
MOVV REGCTXT, 8(R29)
|
||||
MOVV $argframe+0(FP), R1
|
||||
MOVV R1, 16(R29)
|
||||
MOVB R0, 32(R29)
|
||||
ADDV $32, R29, R1
|
||||
MOVV R1, 24(R29)
|
||||
JAL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -13,11 +13,14 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here, runtime pulls arg map out of the func value.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVW REGCTXT, 4(R29)
|
||||
MOVW $argframe+0(FP), R1
|
||||
MOVW R1, 8(R29)
|
||||
MOVB R0, 16(R29)
|
||||
ADD $16, R29, R1
|
||||
MOVW R1, 12(R29)
|
||||
JAL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -25,10 +28,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVW REGCTXT, 4(R29)
|
||||
MOVW $argframe+0(FP), R1
|
||||
MOVW R1, 8(R29)
|
||||
MOVB R0, 16(R29)
|
||||
ADD $16, R29, R1
|
||||
MOVW R1, 12(R29)
|
||||
JAL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -12,11 +12,14 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here, runtime pulls arg map out of the func value.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
MOVD R11, FIXED_FRAME+0(R1)
|
||||
MOVD $argframe+0(FP), R3
|
||||
MOVD R3, FIXED_FRAME+8(R1)
|
||||
MOVB R0, FIXED_FRAME+24(R1)
|
||||
ADD $FIXED_FRAME+24, R1, R3
|
||||
MOVD R3, FIXED_FRAME+16(R1)
|
||||
BL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -24,10 +27,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
MOVD R11, FIXED_FRAME+0(R1)
|
||||
MOVD $argframe+0(FP), R3
|
||||
MOVD R3, FIXED_FRAME+8(R1)
|
||||
MOVB R0, FIXED_FRAME+24(R1)
|
||||
ADD $FIXED_FRAME+24, R1, R3
|
||||
MOVD R3, FIXED_FRAME+16(R1)
|
||||
BL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here, runtime pulls arg map out of the func value.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
MOVD R12, 8(R15)
|
||||
MOVD $argframe+0(FP), R3
|
||||
MOVD R3, 16(R15)
|
||||
MOVB $0, 32(R15)
|
||||
ADD $32, R15, R3
|
||||
MOVD R3, 24(R15)
|
||||
BL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
MOVD R12, 8(R15)
|
||||
MOVD $argframe+0(FP), R3
|
||||
MOVD R3, 16(R15)
|
||||
MOVB $0, 32(R15)
|
||||
ADD $32, R15, R3
|
||||
MOVD R3, 24(R15)
|
||||
BL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
|
||||
MOVD CTXT, 0(SP)
|
||||
@@ -21,6 +21,9 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
I64Add
|
||||
I64Store $8
|
||||
|
||||
MOVB $0, 24(SP)
|
||||
MOVD $24(SP), 16(SP)
|
||||
|
||||
CALL ·callReflect(SB)
|
||||
RET
|
||||
|
||||
@@ -28,7 +31,7 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
|
||||
NO_LOCAL_POINTERS
|
||||
|
||||
MOVD CTXT, 0(SP)
|
||||
@@ -40,5 +43,8 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
I64Add
|
||||
I64Store $8
|
||||
|
||||
MOVB $0, 24(SP)
|
||||
MOVD $24(SP), 16(SP)
|
||||
|
||||
CALL ·callMethod(SB)
|
||||
RET
|
||||
|
||||
@@ -25,9 +25,9 @@ func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr,
|
||||
var ft *rtype
|
||||
var s *bitVector
|
||||
if rcvr != nil {
|
||||
ft, argSize, retOffset, s, _ = funcLayout(t.(*rtype), rcvr.(*rtype))
|
||||
ft, argSize, retOffset, s, _ = funcLayout((*funcType)(unsafe.Pointer(t.(*rtype))), rcvr.(*rtype))
|
||||
} else {
|
||||
ft, argSize, retOffset, s, _ = funcLayout(t.(*rtype), nil)
|
||||
ft, argSize, retOffset, s, _ = funcLayout((*funcType)(unsafe.Pointer(t.(*rtype))), nil)
|
||||
}
|
||||
frametype = ft
|
||||
for i := uint32(0); i < s.n; i++ {
|
||||
|
||||
@@ -12,14 +12,15 @@ import (
|
||||
|
||||
// makeFuncImpl is the closure value implementing the function
|
||||
// returned by MakeFunc.
|
||||
// The first two words of this type must be kept in sync with
|
||||
// The first three words of this type must be kept in sync with
|
||||
// methodValue and runtime.reflectMethodValue.
|
||||
// Any changes should be reflected in all three.
|
||||
type makeFuncImpl struct {
|
||||
code uintptr
|
||||
stack *bitVector
|
||||
typ *funcType
|
||||
fn func([]Value) []Value
|
||||
code uintptr
|
||||
stack *bitVector // ptrmap for both args and results
|
||||
argLen uintptr // just args
|
||||
ftyp *funcType
|
||||
fn func([]Value) []Value
|
||||
}
|
||||
|
||||
// MakeFunc returns a new function of the given Type
|
||||
@@ -59,9 +60,9 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
|
||||
code := **(**uintptr)(unsafe.Pointer(&dummy))
|
||||
|
||||
// makeFuncImpl contains a stack map for use by the runtime
|
||||
_, _, _, stack, _ := funcLayout(t, nil)
|
||||
_, argLen, _, stack, _ := funcLayout(ftyp, nil)
|
||||
|
||||
impl := &makeFuncImpl{code: code, stack: stack, typ: ftyp, fn: fn}
|
||||
impl := &makeFuncImpl{code: code, stack: stack, argLen: argLen, ftyp: ftyp, fn: fn}
|
||||
|
||||
return Value{t, unsafe.Pointer(impl), flag(Func)}
|
||||
}
|
||||
@@ -73,12 +74,13 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
|
||||
// word in the passed-in argument frame.
|
||||
func makeFuncStub()
|
||||
|
||||
// The first two words of this type must be kept in sync with
|
||||
// The first 3 words of this type must be kept in sync with
|
||||
// makeFuncImpl and runtime.reflectMethodValue.
|
||||
// Any changes should be reflected in all three.
|
||||
type methodValue struct {
|
||||
fn uintptr
|
||||
stack *bitVector
|
||||
stack *bitVector // ptrmap for both args and results
|
||||
argLen uintptr // just args
|
||||
method int
|
||||
rcvr Value
|
||||
}
|
||||
@@ -101,7 +103,7 @@ func makeMethodValue(op string, v Value) Value {
|
||||
rcvr := Value{v.typ, v.ptr, fl}
|
||||
|
||||
// v.Type returns the actual type of the method value.
|
||||
funcType := v.Type().(*rtype)
|
||||
ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype)))
|
||||
|
||||
// Indirect Go func value (dummy) to obtain
|
||||
// actual code address. (A Go func value is a pointer
|
||||
@@ -110,11 +112,12 @@ func makeMethodValue(op string, v Value) Value {
|
||||
code := **(**uintptr)(unsafe.Pointer(&dummy))
|
||||
|
||||
// methodValue contains a stack map for use by the runtime
|
||||
_, _, _, stack, _ := funcLayout(funcType, nil)
|
||||
_, argLen, _, stack, _ := funcLayout(ftyp, nil)
|
||||
|
||||
fv := &methodValue{
|
||||
fn: code,
|
||||
stack: stack,
|
||||
argLen: argLen,
|
||||
method: int(v.flag) >> flagMethodShift,
|
||||
rcvr: rcvr,
|
||||
}
|
||||
@@ -124,7 +127,7 @@ func makeMethodValue(op string, v Value) Value {
|
||||
// but we want Interface() and other operations to fail early.
|
||||
methodReceiver(op, fv.rcvr, fv.method)
|
||||
|
||||
return Value{funcType, unsafe.Pointer(fv), v.flag&flagRO | flag(Func)}
|
||||
return Value{&ftyp.rtype, unsafe.Pointer(fv), v.flag&flagRO | flag(Func)}
|
||||
}
|
||||
|
||||
// methodValueCall is an assembly function that is the code half of
|
||||
|
||||
@@ -3022,8 +3022,8 @@ func toType(t *rtype) Type {
|
||||
}
|
||||
|
||||
type layoutKey struct {
|
||||
t *rtype // function signature
|
||||
rcvr *rtype // receiver type, or nil if none
|
||||
ftyp *funcType // function signature
|
||||
rcvr *rtype // receiver type, or nil if none
|
||||
}
|
||||
|
||||
type layoutType struct {
|
||||
@@ -3042,7 +3042,7 @@ var layoutCache sync.Map // map[layoutKey]layoutType
|
||||
// The returned type exists only for GC, so we only fill out GC relevant info.
|
||||
// Currently, that's just size and the GC program. We also fill in
|
||||
// the name for possible debugging use.
|
||||
func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr, stk *bitVector, framePool *sync.Pool) {
|
||||
func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr, stk *bitVector, framePool *sync.Pool) {
|
||||
if t.Kind() != Func {
|
||||
panic("reflect: funcLayout of non-func type")
|
||||
}
|
||||
@@ -3055,8 +3055,6 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
|
||||
return lt.t, lt.argSize, lt.retOffset, lt.stack, lt.framePool
|
||||
}
|
||||
|
||||
tt := (*funcType)(unsafe.Pointer(t))
|
||||
|
||||
// compute gc program & stack bitmap for arguments
|
||||
ptrmap := new(bitVector)
|
||||
var offset uintptr
|
||||
@@ -3066,22 +3064,23 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
|
||||
// space no matter how big they actually are.
|
||||
if ifaceIndir(rcvr) || rcvr.pointers() {
|
||||
ptrmap.append(1)
|
||||
} else {
|
||||
ptrmap.append(0)
|
||||
}
|
||||
offset += ptrSize
|
||||
}
|
||||
for _, arg := range tt.in() {
|
||||
for _, arg := range t.in() {
|
||||
offset += -offset & uintptr(arg.align-1)
|
||||
addTypeBits(ptrmap, offset, arg)
|
||||
offset += arg.size
|
||||
}
|
||||
argN := ptrmap.n
|
||||
argSize = offset
|
||||
if runtime.GOARCH == "amd64p32" {
|
||||
offset += -offset & (8 - 1)
|
||||
}
|
||||
offset += -offset & (ptrSize - 1)
|
||||
retOffset = offset
|
||||
for _, res := range tt.out() {
|
||||
for _, res := range t.out() {
|
||||
offset += -offset & uintptr(res.align-1)
|
||||
addTypeBits(ptrmap, offset, res)
|
||||
offset += res.size
|
||||
@@ -3102,7 +3101,6 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
|
||||
} else {
|
||||
x.kind |= kindNoPointers
|
||||
}
|
||||
ptrmap.n = argN
|
||||
|
||||
var s string
|
||||
if rcvr != nil {
|
||||
|
||||
@@ -325,7 +325,7 @@ var callGC bool // for testing; see TestCallMethodJump
|
||||
|
||||
func (v Value) call(op string, in []Value) []Value {
|
||||
// Get function pointer, type.
|
||||
t := v.typ
|
||||
t := (*funcType)(unsafe.Pointer(v.typ))
|
||||
var (
|
||||
fn unsafe.Pointer
|
||||
rcvr Value
|
||||
@@ -453,15 +453,14 @@ func (v Value) call(op string, in []Value) []Value {
|
||||
|
||||
var ret []Value
|
||||
if nout == 0 {
|
||||
// This is untyped because the frame is really a
|
||||
// stack, even though it's a heap object.
|
||||
memclrNoHeapPointers(args, frametype.size)
|
||||
typedmemclr(frametype, args)
|
||||
framePool.Put(args)
|
||||
} else {
|
||||
// Zero the now unused input area of args,
|
||||
// because the Values returned by this function contain pointers to the args object,
|
||||
// and will thus keep the args object alive indefinitely.
|
||||
memclrNoHeapPointers(args, retOffset)
|
||||
typedmemclrpartial(frametype, args, 0, retOffset)
|
||||
|
||||
// Wrap Values around return values in args.
|
||||
ret = make([]Value, nout)
|
||||
off = retOffset
|
||||
@@ -472,6 +471,10 @@ func (v Value) call(op string, in []Value) []Value {
|
||||
if tv.Size() != 0 {
|
||||
fl := flagIndir | flag(tv.Kind())
|
||||
ret[i] = Value{tv.common(), add(args, off, "tv.Size() != 0"), fl}
|
||||
// Note: this does introduce false sharing between results -
|
||||
// if any result is live, they are all live.
|
||||
// (And the space for the args is live as well, but as we've
|
||||
// cleared that space it isn't as big a deal.)
|
||||
} else {
|
||||
// For zero-sized return value, args+off may point to the next object.
|
||||
// In this case, return the zero value instead.
|
||||
@@ -496,8 +499,13 @@ func (v Value) call(op string, in []Value) []Value {
|
||||
// NOTE: This function must be marked as a "wrapper" in the generated code,
|
||||
// so that the linker can make it work correctly for panic and recover.
|
||||
// The gc compilers know to do that for the name "reflect.callReflect".
|
||||
func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
|
||||
ftyp := ctxt.typ
|
||||
//
|
||||
// ctxt is the "closure" generated by MakeFunc.
|
||||
// frame is a pointer to the arguments to that closure on the stack.
|
||||
// retValid points to a boolean which should be set when the results
|
||||
// section of frame is set.
|
||||
func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool) {
|
||||
ftyp := ctxt.ftyp
|
||||
f := ctxt.fn
|
||||
|
||||
// Copy argument frame into Values.
|
||||
@@ -562,6 +570,16 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
|
||||
}
|
||||
}
|
||||
|
||||
// Announce that the return values are valid.
|
||||
// After this point the runtime can depend on the return values being valid.
|
||||
*retValid = true
|
||||
|
||||
// We have to make sure that the out slice lives at least until
|
||||
// the runtime knows the return values are valid. Otherwise, the
|
||||
// return values might not be scanned by anyone during a GC.
|
||||
// (out would be dead, and the return slots not yet alive.)
|
||||
runtime.KeepAlive(out)
|
||||
|
||||
// runtime.getArgInfo expects to be able to find ctxt on the
|
||||
// stack when it finds our caller, makeFuncStub. Make sure it
|
||||
// doesn't get garbage collected.
|
||||
@@ -575,7 +593,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
|
||||
// The return value rcvrtype gives the method's actual receiver type.
|
||||
// The return value t gives the method type signature (without the receiver).
|
||||
// The return value fn is a pointer to the method code.
|
||||
func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn unsafe.Pointer) {
|
||||
func methodReceiver(op string, v Value, methodIndex int) (rcvrtype *rtype, t *funcType, fn unsafe.Pointer) {
|
||||
i := methodIndex
|
||||
if v.typ.Kind() == Interface {
|
||||
tt := (*interfaceType)(unsafe.Pointer(v.typ))
|
||||
@@ -592,7 +610,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
|
||||
}
|
||||
rcvrtype = iface.itab.typ
|
||||
fn = unsafe.Pointer(&iface.itab.fun[i])
|
||||
t = tt.typeOff(m.typ)
|
||||
t = (*funcType)(unsafe.Pointer(tt.typeOff(m.typ)))
|
||||
} else {
|
||||
rcvrtype = v.typ
|
||||
ms := v.typ.exportedMethods()
|
||||
@@ -605,7 +623,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
|
||||
}
|
||||
ifn := v.typ.textOff(m.ifn)
|
||||
fn = unsafe.Pointer(&ifn)
|
||||
t = v.typ.typeOff(m.mtyp)
|
||||
t = (*funcType)(unsafe.Pointer(v.typ.typeOff(m.mtyp)))
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -644,23 +662,31 @@ func align(x, n uintptr) uintptr {
|
||||
// NOTE: This function must be marked as a "wrapper" in the generated code,
|
||||
// so that the linker can make it work correctly for panic and recover.
|
||||
// The gc compilers know to do that for the name "reflect.callMethod".
|
||||
func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
|
||||
//
|
||||
// ctxt is the "closure" generated by makeVethodValue.
|
||||
// frame is a pointer to the arguments to that closure on the stack.
|
||||
// retValid points to a boolean which should be set when the results
|
||||
// section of frame is set.
|
||||
func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool) {
|
||||
rcvr := ctxt.rcvr
|
||||
rcvrtype, t, fn := methodReceiver("call", rcvr, ctxt.method)
|
||||
frametype, argSize, retOffset, _, framePool := funcLayout(t, rcvrtype)
|
||||
|
||||
// Make a new frame that is one word bigger so we can store the receiver.
|
||||
args := framePool.Get().(unsafe.Pointer)
|
||||
// This space is used for both arguments and return values.
|
||||
scratch := framePool.Get().(unsafe.Pointer)
|
||||
|
||||
// Copy in receiver and rest of args.
|
||||
// Avoid constructing out-of-bounds pointers if there are no args.
|
||||
storeRcvr(rcvr, args)
|
||||
storeRcvr(rcvr, scratch)
|
||||
if argSize-ptrSize > 0 {
|
||||
typedmemmovepartial(frametype, add(args, ptrSize, "argSize > ptrSize"), frame, ptrSize, argSize-ptrSize)
|
||||
typedmemmovepartial(frametype, add(scratch, ptrSize, "argSize > ptrSize"), frame, ptrSize, argSize-ptrSize)
|
||||
}
|
||||
|
||||
// Call.
|
||||
call(frametype, fn, args, uint32(frametype.size), uint32(retOffset))
|
||||
// Call copies the arguments from scratch to the stack, calls fn,
|
||||
// and then copies the results back into scratch.
|
||||
call(frametype, fn, scratch, uint32(frametype.size), uint32(retOffset))
|
||||
|
||||
// Copy return values. On amd64p32, the beginning of return values
|
||||
// is 64-bit aligned, so the caller's frame layout (which doesn't have
|
||||
@@ -673,17 +699,21 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
|
||||
if runtime.GOARCH == "amd64p32" {
|
||||
callerRetOffset = align(argSize-ptrSize, 8)
|
||||
}
|
||||
typedmemmovepartial(frametype,
|
||||
add(frame, callerRetOffset, "frametype.size > retOffset"),
|
||||
add(args, retOffset, "frametype.size > retOffset"),
|
||||
retOffset,
|
||||
// This copies to the stack. Write barriers are not needed.
|
||||
memmove(add(frame, callerRetOffset, "frametype.size > retOffset"),
|
||||
add(scratch, retOffset, "frametype.size > retOffset"),
|
||||
frametype.size-retOffset)
|
||||
}
|
||||
|
||||
// This is untyped because the frame is really a stack, even
|
||||
// though it's a heap object.
|
||||
memclrNoHeapPointers(args, frametype.size)
|
||||
framePool.Put(args)
|
||||
// Tell the runtime it can now depend on the return values
|
||||
// being properly initialized.
|
||||
*retValid = true
|
||||
|
||||
// Clear the scratch space and put it back in the pool.
|
||||
// This must happen after the statement above, so that the return
|
||||
// values will always be scanned by someone.
|
||||
typedmemclr(frametype, scratch)
|
||||
framePool.Put(scratch)
|
||||
|
||||
// See the comment in callReflect.
|
||||
runtime.KeepAlive(ctxt)
|
||||
@@ -2569,6 +2599,10 @@ func call(argtype *rtype, fn, arg unsafe.Pointer, n uint32, retoffset uint32)
|
||||
|
||||
func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
|
||||
|
||||
// memmove copies size bytes to dst from src. No write barriers are used.
|
||||
//go:noescape
|
||||
func memmove(dst, src unsafe.Pointer, size uintptr)
|
||||
|
||||
// typedmemmove copies a value of type t to dst from src.
|
||||
//go:noescape
|
||||
func typedmemmove(t *rtype, dst, src unsafe.Pointer)
|
||||
@@ -2578,14 +2612,20 @@ func typedmemmove(t *rtype, dst, src unsafe.Pointer)
|
||||
//go:noescape
|
||||
func typedmemmovepartial(t *rtype, dst, src unsafe.Pointer, off, size uintptr)
|
||||
|
||||
// typedmemclr zeros the value at ptr of type t.
|
||||
//go:noescape
|
||||
func typedmemclr(t *rtype, ptr unsafe.Pointer)
|
||||
|
||||
// typedmemclrpartial is like typedmemclr but assumes that
|
||||
// dst points off bytes into the value and only clears size bytes.
|
||||
//go:noescape
|
||||
func typedmemclrpartial(t *rtype, ptr unsafe.Pointer, off, size uintptr)
|
||||
|
||||
// typedslicecopy copies a slice of elemType values from src to dst,
|
||||
// returning the number of elements copied.
|
||||
//go:noescape
|
||||
func typedslicecopy(elemType *rtype, dst, src sliceHeader) int
|
||||
|
||||
//go:noescape
|
||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
||||
// Dummy annotation marking that the value x escapes,
|
||||
// for use in cases where the reflect code is so clever that
|
||||
// the compiler cannot follow.
|
||||
|
||||
@@ -92,7 +92,7 @@ func makechan(t *chantype, size int) *hchan {
|
||||
// Queue or element size is zero.
|
||||
c = (*hchan)(mallocgc(hchanSize, nil, true))
|
||||
// Race detector uses this location for synchronization.
|
||||
c.buf = unsafe.Pointer(c)
|
||||
c.buf = c.raceaddr()
|
||||
case elem.kind&kindNoPointers != 0:
|
||||
// Elements do not contain pointers.
|
||||
// Allocate hchan and buf in one call.
|
||||
@@ -151,7 +151,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
|
||||
}
|
||||
|
||||
if raceenabled {
|
||||
racereadpc(unsafe.Pointer(c), callerpc, funcPC(chansend))
|
||||
racereadpc(c.raceaddr(), callerpc, funcPC(chansend))
|
||||
}
|
||||
|
||||
// Fast path: check for failed non-blocking operation without acquiring the lock.
|
||||
@@ -337,8 +337,8 @@ func closechan(c *hchan) {
|
||||
|
||||
if raceenabled {
|
||||
callerpc := getcallerpc()
|
||||
racewritepc(unsafe.Pointer(c), callerpc, funcPC(closechan))
|
||||
racerelease(unsafe.Pointer(c))
|
||||
racewritepc(c.raceaddr(), callerpc, funcPC(closechan))
|
||||
racerelease(c.raceaddr())
|
||||
}
|
||||
|
||||
c.closed = 1
|
||||
@@ -361,7 +361,7 @@ func closechan(c *hchan) {
|
||||
gp := sg.g
|
||||
gp.param = nil
|
||||
if raceenabled {
|
||||
raceacquireg(gp, unsafe.Pointer(c))
|
||||
raceacquireg(gp, c.raceaddr())
|
||||
}
|
||||
gp.schedlink.set(glist)
|
||||
glist = gp
|
||||
@@ -380,7 +380,7 @@ func closechan(c *hchan) {
|
||||
gp := sg.g
|
||||
gp.param = nil
|
||||
if raceenabled {
|
||||
raceacquireg(gp, unsafe.Pointer(c))
|
||||
raceacquireg(gp, c.raceaddr())
|
||||
}
|
||||
gp.schedlink.set(glist)
|
||||
glist = gp
|
||||
@@ -457,7 +457,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
|
||||
|
||||
if c.closed != 0 && c.qcount == 0 {
|
||||
if raceenabled {
|
||||
raceacquire(unsafe.Pointer(c))
|
||||
raceacquire(c.raceaddr())
|
||||
}
|
||||
unlock(&c.lock)
|
||||
if ep != nil {
|
||||
@@ -735,6 +735,15 @@ func (q *waitq) dequeue() *sudog {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *hchan) raceaddr() unsafe.Pointer {
|
||||
// Treat read-like and write-like operations on the channel to
|
||||
// happen at this address. Avoid using the address of qcount
|
||||
// or dataqsiz, because the len() and cap() builtins read
|
||||
// those addresses, and we don't want them racing with
|
||||
// operations like close().
|
||||
return unsafe.Pointer(&c.buf)
|
||||
}
|
||||
|
||||
func racesync(c *hchan, sg *sudog) {
|
||||
racerelease(chanbuf(c, 0))
|
||||
raceacquireg(sg.g, chanbuf(c, 0))
|
||||
|
||||
@@ -320,6 +320,19 @@ func typedmemclr(typ *_type, ptr unsafe.Pointer) {
|
||||
memclrNoHeapPointers(ptr, typ.size)
|
||||
}
|
||||
|
||||
//go:linkname reflect_typedmemclr reflect.typedmemclr
|
||||
func reflect_typedmemclr(typ *_type, ptr unsafe.Pointer) {
|
||||
typedmemclr(typ, ptr)
|
||||
}
|
||||
|
||||
//go:linkname reflect_typedmemclrpartial reflect.typedmemclrpartial
|
||||
func reflect_typedmemclrpartial(typ *_type, ptr unsafe.Pointer, off, size uintptr) {
|
||||
if typ.kind&kindNoPointers == 0 {
|
||||
bulkBarrierPreWrite(uintptr(ptr), 0, size)
|
||||
}
|
||||
memclrNoHeapPointers(ptr, size)
|
||||
}
|
||||
|
||||
// memclrHasPointers clears n bytes of typed memory starting at ptr.
|
||||
// The caller must ensure that the type of the object at ptr has
|
||||
// pointers, usually by checking typ.kind&kindNoPointers. However, ptr
|
||||
|
||||
@@ -34,6 +34,10 @@ func semacreate(mp *m) {
|
||||
|
||||
//go:nosplit
|
||||
func semasleep(ns int64) int32 {
|
||||
var start int64
|
||||
if ns >= 0 {
|
||||
start = nanotime()
|
||||
}
|
||||
mp := getg().m
|
||||
pthread_mutex_lock(&mp.mutex)
|
||||
for {
|
||||
@@ -43,8 +47,13 @@ func semasleep(ns int64) int32 {
|
||||
return 0
|
||||
}
|
||||
if ns >= 0 {
|
||||
spent := nanotime() - start
|
||||
if spent >= ns {
|
||||
pthread_mutex_unlock(&mp.mutex)
|
||||
return -1
|
||||
}
|
||||
var t timespec
|
||||
t.set_nsec(ns)
|
||||
t.set_nsec(ns - spent)
|
||||
err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t)
|
||||
if err == _ETIMEDOUT {
|
||||
pthread_mutex_unlock(&mp.mutex)
|
||||
|
||||
@@ -197,23 +197,23 @@ func semacreate(mp *m) {
|
||||
//go:nosplit
|
||||
func semasleep(ns int64) int32 {
|
||||
var ret int32
|
||||
|
||||
systemstack(func() {
|
||||
_g_ := getg()
|
||||
if nacl_mutex_lock(_g_.m.waitsemalock) < 0 {
|
||||
throw("semasleep")
|
||||
}
|
||||
|
||||
var ts timespec
|
||||
if ns >= 0 {
|
||||
end := ns + nanotime()
|
||||
ts.tv_sec = end / 1e9
|
||||
ts.tv_nsec = int32(end % 1e9)
|
||||
}
|
||||
for _g_.m.waitsemacount == 0 {
|
||||
if ns < 0 {
|
||||
if nacl_cond_wait(_g_.m.waitsema, _g_.m.waitsemalock) < 0 {
|
||||
throw("semasleep")
|
||||
}
|
||||
} else {
|
||||
var ts timespec
|
||||
end := ns + nanotime()
|
||||
ts.tv_sec = end / 1e9
|
||||
ts.tv_nsec = int32(end % 1e9)
|
||||
r := nacl_cond_timed_wait_abs(_g_.m.waitsema, _g_.m.waitsemalock, &ts)
|
||||
if r == -_ETIMEDOUT {
|
||||
nacl_mutex_unlock(_g_.m.waitsemalock)
|
||||
|
||||
@@ -126,15 +126,9 @@ func semacreate(mp *m) {
|
||||
//go:nosplit
|
||||
func semasleep(ns int64) int32 {
|
||||
_g_ := getg()
|
||||
|
||||
// Compute sleep deadline.
|
||||
var tsp *timespec
|
||||
var ts timespec
|
||||
var deadline int64
|
||||
if ns >= 0 {
|
||||
var nsec int32
|
||||
ts.set_sec(timediv(ns, 1000000000, &nsec))
|
||||
ts.set_nsec(nsec)
|
||||
tsp = &ts
|
||||
deadline = nanotime() + ns
|
||||
}
|
||||
|
||||
for {
|
||||
@@ -147,18 +141,21 @@ func semasleep(ns int64) int32 {
|
||||
}
|
||||
|
||||
// Sleep until unparked by semawakeup or timeout.
|
||||
var tsp *timespec
|
||||
var ts timespec
|
||||
if ns >= 0 {
|
||||
wait := deadline - nanotime()
|
||||
if wait <= 0 {
|
||||
return -1
|
||||
}
|
||||
var nsec int32
|
||||
ts.set_sec(timediv(wait, 1000000000, &nsec))
|
||||
ts.set_nsec(nsec)
|
||||
tsp = &ts
|
||||
}
|
||||
ret := lwp_park(_CLOCK_MONOTONIC, _TIMER_RELTIME, tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
|
||||
if ret == _ETIMEDOUT {
|
||||
return -1
|
||||
} else if ret == _EINTR && ns >= 0 {
|
||||
// Avoid sleeping forever if we keep getting
|
||||
// interrupted (for example by the profiling
|
||||
// timer). It would be if tsp upon return had the
|
||||
// remaining time to sleep, but this is good enough.
|
||||
var nsec int32
|
||||
ns /= 2
|
||||
ts.set_sec(timediv(ns, 1000000000, &nsec))
|
||||
ts.set_nsec(nsec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
32
src/runtime/race/testdata/chan_test.go
vendored
32
src/runtime/race/testdata/chan_test.go
vendored
@@ -577,18 +577,32 @@ func TestRaceChanItselfCap(t *testing.T) {
|
||||
<-compl
|
||||
}
|
||||
|
||||
func TestRaceChanCloseLen(t *testing.T) {
|
||||
v := 0
|
||||
_ = v
|
||||
func TestNoRaceChanCloseLen(t *testing.T) {
|
||||
c := make(chan int, 10)
|
||||
c <- 0
|
||||
r := make(chan int, 10)
|
||||
go func() {
|
||||
v = 1
|
||||
close(c)
|
||||
r <- len(c)
|
||||
}()
|
||||
time.Sleep(1e7)
|
||||
_ = len(c)
|
||||
v = 2
|
||||
go func() {
|
||||
close(c)
|
||||
r <- 0
|
||||
}()
|
||||
<-r
|
||||
<-r
|
||||
}
|
||||
|
||||
func TestNoRaceChanCloseCap(t *testing.T) {
|
||||
c := make(chan int, 10)
|
||||
r := make(chan int, 10)
|
||||
go func() {
|
||||
r <- cap(c)
|
||||
}()
|
||||
go func() {
|
||||
close(c)
|
||||
r <- 0
|
||||
}()
|
||||
<-r
|
||||
<-r
|
||||
}
|
||||
|
||||
func TestRaceChanCloseSend(t *testing.T) {
|
||||
|
||||
@@ -245,7 +245,7 @@ loop:
|
||||
|
||||
case caseSend:
|
||||
if raceenabled {
|
||||
racereadpc(unsafe.Pointer(c), cas.pc, chansendpc)
|
||||
racereadpc(c.raceaddr(), cas.pc, chansendpc)
|
||||
}
|
||||
if c.closed != 0 {
|
||||
goto sclose
|
||||
@@ -462,7 +462,7 @@ rclose:
|
||||
typedmemclr(c.elemtype, cas.elem)
|
||||
}
|
||||
if raceenabled {
|
||||
raceacquire(unsafe.Pointer(c))
|
||||
raceacquire(c.raceaddr())
|
||||
}
|
||||
goto retc
|
||||
|
||||
|
||||
@@ -237,8 +237,10 @@ func signal_ignore(s uint32) {
|
||||
atomic.Store(&sig.ignored[s/32], i)
|
||||
}
|
||||
|
||||
// sigInitIgnored marks the signal as already ignored. This is called at
|
||||
// program start by siginit.
|
||||
// sigInitIgnored marks the signal as already ignored. This is called at
|
||||
// program start by initsig. In a shared library initsig is called by
|
||||
// libpreinit, so the runtime may not be initialized yet.
|
||||
//go:nosplit
|
||||
func sigInitIgnored(s uint32) {
|
||||
i := sig.ignored[s/32]
|
||||
i |= 1 << (s & 31)
|
||||
|
||||
@@ -24,13 +24,13 @@ type traceContextKey struct{}
|
||||
// If the end function is called multiple times, only the first
|
||||
// call is used in the latency measurement.
|
||||
//
|
||||
// ctx, task := trace.NewTask(ctx, "awesome task")
|
||||
// trace.WithRegion(ctx, prepWork)
|
||||
// ctx, task := trace.NewTask(ctx, "awesomeTask")
|
||||
// trace.WithRegion(ctx, "preparation", prepWork)
|
||||
// // preparation of the task
|
||||
// go func() { // continue processing the task in a separate goroutine.
|
||||
// defer task.End()
|
||||
// trace.WithRegion(ctx, remainingWork)
|
||||
// }
|
||||
// trace.WithRegion(ctx, "remainingWork", remainingWork)
|
||||
// }()
|
||||
func NewTask(pctx context.Context, taskType string) (ctx context.Context, task *Task) {
|
||||
pid := fromContext(pctx).id
|
||||
id := newID()
|
||||
|
||||
@@ -557,8 +557,9 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
||||
// reflectMethodValue is a partial duplicate of reflect.makeFuncImpl
|
||||
// and reflect.methodValue.
|
||||
type reflectMethodValue struct {
|
||||
fn uintptr
|
||||
stack *bitvector // args bitmap
|
||||
fn uintptr
|
||||
stack *bitvector // ptrmap for both args and results
|
||||
argLen uintptr // just args
|
||||
}
|
||||
|
||||
// getArgInfoFast returns the argument frame information for a call to f.
|
||||
@@ -587,6 +588,7 @@ func getArgInfo(frame *stkframe, f funcInfo, needArgMap bool, ctxt *funcval) (ar
|
||||
// These take a *reflect.methodValue as their
|
||||
// context register.
|
||||
var mv *reflectMethodValue
|
||||
var retValid bool
|
||||
if ctxt != nil {
|
||||
// This is not an actual call, but a
|
||||
// deferred call. The function value
|
||||
@@ -600,6 +602,10 @@ func getArgInfo(frame *stkframe, f funcInfo, needArgMap bool, ctxt *funcval) (ar
|
||||
// 0(SP).
|
||||
arg0 := frame.sp + sys.MinFrameSize
|
||||
mv = *(**reflectMethodValue)(unsafe.Pointer(arg0))
|
||||
// Figure out whether the return values are valid.
|
||||
// Reflect will update this value after it copies
|
||||
// in the return values.
|
||||
retValid = *(*bool)(unsafe.Pointer(arg0 + 3*sys.PtrSize))
|
||||
}
|
||||
if mv.fn != f.entry {
|
||||
print("runtime: confused by ", funcname(f), "\n")
|
||||
@@ -607,6 +613,9 @@ func getArgInfo(frame *stkframe, f funcInfo, needArgMap bool, ctxt *funcval) (ar
|
||||
}
|
||||
bv := mv.stack
|
||||
arglen = uintptr(bv.n * sys.PtrSize)
|
||||
if !retValid {
|
||||
arglen = uintptr(mv.argLen) &^ (sys.PtrSize - 1)
|
||||
}
|
||||
argmap = bv
|
||||
}
|
||||
}
|
||||
|
||||
17
test/fixedbugs/issue27143.go
Normal file
17
test/fixedbugs/issue27143.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// compile
|
||||
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Issue 27143: cmd/compile: erroneous application of walkinrange
|
||||
// optimization for const over 2**63
|
||||
|
||||
package p
|
||||
|
||||
var c uint64
|
||||
|
||||
var b1 bool = 0x7fffffffffffffff < c && c < 0x8000000000000000
|
||||
var b2 bool = c < 0x8000000000000000 && 0x7fffffffffffffff < c
|
||||
var b3 bool = 0x8000000000000000 < c && c < 0x8000000000000001
|
||||
var b4 bool = c < 0x8000000000000001 && 0x8000000000000000 < c
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user