summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-05-02 15:44:51 +0200
committerOndřej Surý <ondrej@sury.org>2012-05-02 15:44:51 +0200
commit0003ee229fd33ff46cb5f2fe1e35f5c0284debc4 (patch)
tree08c48264fd22152f443284397517a1b2be743c34
parent505c19580e0f43fe5224431459cacb7c21edd93d (diff)
downloadgolang-0003ee229fd33ff46cb5f2fe1e35f5c0284debc4.tar.gz
Imported Upstream version 1.0.1upstream/1.0.1
-rw-r--r--AUTHORS5
-rw-r--r--CONTRIBUTORS8
-rw-r--r--VERSION2
-rw-r--r--doc/articles/image_draw.html4
-rw-r--r--doc/articles/wiki/edit.html6
-rw-r--r--doc/articles/wiki/index.html11
-rw-r--r--doc/articles/wiki/view.html6
-rw-r--r--doc/code.html13
-rw-r--r--doc/codewalk/markov.xml8
-rw-r--r--doc/devel/release.html14
-rw-r--r--doc/effective_go.html4
-rw-r--r--doc/go1.html5
-rw-r--r--doc/go_spec.html22
-rw-r--r--doc/install-source.html21
-rw-r--r--doc/play/playground.js87
-rw-r--r--doc/progs/image_draw.go4
-rw-r--r--doc/style.css5
-rw-r--r--lib/godoc/package.html4
-rw-r--r--src/cmd/dist/build.c13
-rw-r--r--src/cmd/gc/esc.c70
-rw-r--r--src/cmd/go/doc.go14
-rw-r--r--src/cmd/go/get.go78
-rw-r--r--src/cmd/go/tag_test.go71
-rw-r--r--src/cmd/go/vcs.go8
-rw-r--r--src/cmd/godoc/README.godoc-app29
-rw-r--r--src/cmd/godoc/main.go2
-rw-r--r--src/cmd/godoc/setup-godoc-app.bash10
-rw-r--r--src/pkg/crypto/tls/cipher_suites.go4
-rw-r--r--src/pkg/crypto/tls/handshake_server.go29
-rw-r--r--src/pkg/crypto/tls/handshake_server_test.go158
-rw-r--r--src/pkg/crypto/tls/key_agreement.go12
-rw-r--r--src/pkg/database/sql/sql.go3
-rw-r--r--src/pkg/encoding/ascii85/ascii85.go1
-rw-r--r--src/pkg/encoding/ascii85/ascii85_test.go5
-rw-r--r--src/pkg/encoding/asn1/asn1.go16
-rw-r--r--src/pkg/encoding/asn1/asn1_test.go6
-rw-r--r--src/pkg/encoding/base64/base64.go5
-rw-r--r--src/pkg/encoding/base64/base64_test.go3
-rw-r--r--src/pkg/encoding/json/encode.go9
-rw-r--r--src/pkg/encoding/json/tagkey_test.go5
-rw-r--r--src/pkg/encoding/pem/pem.go9
-rw-r--r--src/pkg/encoding/pem/pem_test.go22
-rw-r--r--src/pkg/flag/flag.go10
-rw-r--r--src/pkg/fmt/fmt_test.go3
-rw-r--r--src/pkg/fmt/format.go2
-rw-r--r--src/pkg/html/escape.go8
-rw-r--r--src/pkg/mime/mediatype.go2
-rw-r--r--src/pkg/mime/mediatype_test.go32
-rw-r--r--src/pkg/mime/multipart/multipart.go8
-rw-r--r--src/pkg/mime/multipart/multipart_test.go50
-rwxr-xr-xsrc/pkg/mime/multipart/testdata/nested-mime29
-rw-r--r--src/pkg/net/http/example_test.go5
-rw-r--r--src/pkg/net/http/server.go6
-rw-r--r--src/pkg/net/iprawsock_posix.go4
-rw-r--r--src/pkg/net/tcpsock_posix.go6
-rw-r--r--src/pkg/net/udpsock_posix.go4
-rw-r--r--src/pkg/net/unixsock_posix.go6
-rw-r--r--src/pkg/net/url/url.go8
-rw-r--r--src/pkg/net/url/url_test.go4
-rw-r--r--src/pkg/os/error_windows.go2
-rw-r--r--src/pkg/path/filepath/path.go3
-rw-r--r--src/pkg/path/path.go2
-rw-r--r--src/pkg/reflect/all_test.go5
-rw-r--r--src/pkg/reflect/type.go1
-rw-r--r--src/pkg/runtime/extern.go3
-rw-r--r--src/pkg/text/template/exec.go7
-rw-r--r--src/pkg/text/template/exec_test.go8
-rw-r--r--src/pkg/text/template/funcs.go2
-rw-r--r--src/pkg/time/format.go6
-rw-r--r--src/pkg/time/time.go6
-rw-r--r--src/pkg/time/time_test.go3
-rw-r--r--src/pkg/time/zoneinfo_windows.go3
-rwxr-xr-xsrc/sudo.bash7
-rw-r--r--test/escape2.go137
74 files changed, 838 insertions, 355 deletions
diff --git a/AUTHORS b/AUTHORS
index cc95a7d52..8e3fea8ba 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -10,6 +10,7 @@
Abhinav Gupta <abhinav.g90@gmail.com>
Adrian O'Grady <elpollouk@gmail.com>
+Akshat Kumar <seed@mail.nanosouffle.net>
Albert Strasheim <fullung@gmail.com>
Aleksandar Dezelin <dezelin@gmail.com>
Alex Brainman <alex.brainman@gmail.com>
@@ -32,6 +33,7 @@ Arvindh Rajesh Tamilmani <art@a-30.net>
Ben Olive <sionide21@gmail.com>
Benny Siegert <bsiegert@gmail.com>
Berengar Lehr <berengar.lehr@gmx.de>
+Bjorn Tillenius <bjorn@tillenius.me>
Bjorn Tipling <bjorn.tipling@gmail.com>
Blake Mizerany <blake.mizerany@gmail.com>
Bobby Powers <bobbypowers@gmail.com>
@@ -134,8 +136,10 @@ Mateusz Czapliński <czapkofan@gmail.com>
Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Matthew Horsnell <matthew.horsnell@gmail.com>
Micah Stetson <micah.stetson@gmail.com>
+Michael Chaten <mchaten@gmail.com>
Michael Elkins <michael.elkins@gmail.com>
Michael Hoisie <hoisie@gmail.com>
+Michael Lewis <mikelikespie@gmail.com>
Michał Derkacz <ziutek@lnet.pl>
Miek Gieben <miek@miek.nl>
Mikael Tillenius <mikti42@gmail.com>
@@ -183,6 +187,7 @@ Sergio Luis O. B. Correia <sergio@larces.uece.br>
Shenghou Ma <minux.ma@gmail.com>
Spring Mc <heresy.mc@gmail.com>
Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
+Stéphane Travostino <stephane.travostino@gmail.com>
Stephen Weinberg <stephen@q5comm.com>
Sven Almgren <sven@tras.se>
Szabolcs Nagy <nsz@port70.net>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 9b9e93a46..1cf4d1ed6 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -31,9 +31,11 @@
# Please keep the list sorted.
+Aaron Kemp <kemp.aaron@gmail.com>
Abhinav Gupta <abhinav.g90@gmail.com>
Adam Langley <agl@golang.org>
Adrian O'Grady <elpollouk@gmail.com>
+Akshat Kumar <seed@mail.nanosouffle.net>
Albert Strasheim <fullung@gmail.com>
Aleksandar Dezelin <dezelin@gmail.com>
Alex Brainman <alex.brainman@gmail.com>
@@ -65,6 +67,7 @@ Ben Olive <sionide21@gmail.com>
Benny Siegert <bsiegert@gmail.com>
Berengar Lehr <Berengar.Lehr@gmx.de>
Bill Neubauer <wcn@golang.org> <wcn@google.com>
+Bjorn Tillenius <bjorn@tillenius.me>
Bjorn Tipling <bjorn.tipling@gmail.com>
Blake Mizerany <blake.mizerany@gmail.com>
Bobby Powers <bobbypowers@gmail.com>
@@ -84,6 +87,7 @@ Christopher Nielsen <m4dh4tt3r@gmail.com>
Christopher Redden <christopher.redden@gmail.com>
Christopher Wedgwood <cw@f00f.org>
Clement Skau <clementskau@gmail.com>
+Colby Ranger <cranger@google.com>
Conrad Meyer <cemeyer@cs.washington.edu>
Corey Thomasson <cthom.lists@gmail.com>
Damian Gryski <dgryski@gmail.com>
@@ -200,8 +204,10 @@ Matthew Horsnell <matthew.horsnell@gmail.com>
Maxim Pimenov <mpimenov@google.com>
Maxim Ushakov <ushakov@google.com>
Micah Stetson <micah.stetson@gmail.com>
+Michael Chaten <mchaten@gmail.com>
Michael Elkins <michael.elkins@gmail.com>
Michael Hoisie <hoisie@gmail.com>
+Michael Lewis <mikelikespie@gmail.com>
Michael Shields <mshields@google.com>
Michael T. Jones <mtj@google.com> <michael.jones@gmail.com>
Michał Derkacz <ziutek@lnet.pl>
@@ -233,6 +239,7 @@ Peter Froehlich <peter.hans.froehlich@gmail.com>
Peter McKenzie <petermck@google.com>
Peter Mundy <go.peter.90@gmail.com>
Péter Szabó <pts@google.com>
+Peter Weinberger <pjw@golang.org>
Peter Williams <pwil3058@gmail.com>
Phil Pennock <pdp@golang.org>
Pieter Droogendijk <pieter@binky.org.uk>
@@ -264,6 +271,7 @@ Sergio Luis O. B. Correia <sergio@larces.uece.br>
Shenghou Ma <minux.ma@gmail.com>
Spring Mc <heresy.mc@gmail.com>
Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
+Stéphane Travostino <stephane.travostino@gmail.com>
Stephen Ma <stephenm@golang.org>
Stephen Weinberg <stephen@q5comm.com>
Sugu Sougoumarane <ssougou@gmail.com>
diff --git a/VERSION b/VERSION
index 0261a0348..3fabd9f78 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-release.r60 9481
+go1.0.1 \ No newline at end of file
diff --git a/doc/articles/image_draw.html b/doc/articles/image_draw.html
index ba735ad2b..71658cf92 100644
--- a/doc/articles/image_draw.html
+++ b/doc/articles/image_draw.html
@@ -89,7 +89,7 @@ interface which has a <code>Set</code> method.
<p>
To fill a rectangle with a solid color, use an <code>image.Uniform</code>
-source. The <code>ColorImage</code> type re-interprets a <code>Color</code> as a
+source. The <code>Uniform</code> type re-interprets a <code>Color</code> as a
practically infinite-sized <code>Image</code> of that color. For those
familiar with the design of Plan 9's draw library, there is no need
for an explicit "repeat bit" in Go's slice-based image types; the
@@ -189,7 +189,7 @@ To draw an image through a circular mask with center <code>p</code> and radius
<p>
To draw a font glyph in blue starting from a point <code>p</code>, draw with
-an <code>image.ColorImage</code> source and an <code>image.Alpha mask</code>. For
+an <code>image.Uniform</code> source and an <code>image.Alpha mask</code>. For
simplicity, we aren't performing any sub-pixel positioning or
rendering, or correcting for a font's height above a baseline.
</p>
diff --git a/doc/articles/wiki/edit.html b/doc/articles/wiki/edit.html
index c14953b17..044c3bede 100644
--- a/doc/articles/wiki/edit.html
+++ b/doc/articles/wiki/edit.html
@@ -1,6 +1,6 @@
-<h1>Editing {{.Title |html}}</h1>
+<h1>Editing {{.Title}}</h1>
-<form action="/save/{{.Title |html}}" method="POST">
-<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body |html}}</textarea></div>
+<form action="/save/{{.Title}}" method="POST">
+<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body}}</textarea></div>
<div><input type="submit" value="Save"></div>
</form>
diff --git a/doc/articles/wiki/index.html b/doc/articles/wiki/index.html
index 52bf7e798..6c45d7178 100644
--- a/doc/articles/wiki/index.html
+++ b/doc/articles/wiki/index.html
@@ -359,10 +359,10 @@ First, we must add <code>html/template</code> to the list of imports:
<pre>
import (
+ <b>"html/template"</b>
"http"
"io/ioutil"
"os"
- <b>"html/template"</b>
)
</pre>
@@ -397,10 +397,11 @@ Template directives are enclosed in double curly braces.
The <code>printf "%s" .Body</code> instruction is a function call
that outputs <code>.Body</code> as a string instead of a stream of bytes,
the same as a call to <code>fmt.Printf</code>.
-The <code>|html</code> part of each directive pipes the value through the
-<code>html</code> formatter before outputting it, which escapes HTML
-characters (such as replacing <code>&gt;</code> with <code>&amp;gt;</code>),
-preventing user data from corrupting the form HTML.
+The <code>html/template</code> package helps guarantee that only safe and
+correct-looking HTML is generated by template actions. For instance, it
+automatically escapes any greater than sign (<code>&gt;</code>), replacing it
+with <code>&amp;gt;</code>, to make sure user data does not corrupt the form
+HTML.
</p>
<p>
diff --git a/doc/articles/wiki/view.html b/doc/articles/wiki/view.html
index 023391577..b1e87efe8 100644
--- a/doc/articles/wiki/view.html
+++ b/doc/articles/wiki/view.html
@@ -1,5 +1,5 @@
-<h1>{{.Title |html}}</h1>
+<h1>{{.Title}}</h1>
-<p>[<a href="/edit/{{.Title |html}}">edit</a>]</p>
+<p>[<a href="/edit/{{.Title}}">edit</a>]</p>
-<div>{{printf "%s" .Body |html}}</div>
+<div>{{printf "%s" .Body}}</div>
diff --git a/doc/code.html b/doc/code.html
index 238cb0643..efbe7eed0 100644
--- a/doc/code.html
+++ b/doc/code.html
@@ -236,7 +236,7 @@ are built and installed correctly.
<p>
As a convenience, the <code>go</code> command will assume the current directory
if no import path is specified on the command line. This sequence of commands
-has the same affect as the one above:
+has the same effect as the one above:
</p>
<pre>
@@ -300,7 +300,8 @@ func main() {
<p>
Next, run <code>go install</code>, which builds and installs the binary to
-<code>$GOPATH/bin</code>:
+<code>$GOPATH/bin</code> (or <code>$GOBIN</code>, if set; to simplify
+presentation, this document assumes <code>GOBIN</code> is unset):
</p>
<pre>
@@ -384,7 +385,7 @@ package newmath
import "testing"
func TestSqrt(t *testing.T) {
- const in, out = 9, 3
+ const in, out = 4, 2
if x := Sqrt(in); x != out {
t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
}
@@ -397,7 +398,7 @@ Now run the test with <code>go test</code>:
<pre>
$ go test example/newmath
-ok example/newmath
+ok example/newmath 0.165s
</pre>
<p>
@@ -475,8 +476,8 @@ import "code.google.com/p/go.example/newmath"
<p>
This convention is the easiest way to make your Go packages available for
others to use.
-The <a href="http://godashboard.appspot.com/package">Go Package Dashboard</a>
-displays a list of packages recently installed with the <code>go</code> command.
+The <a href="http://godashboard.appspot.com">Go Project Dashboard</a>
+is a list of external Go projects including programs and libraries.
</p>
<p>
diff --git a/doc/codewalk/markov.xml b/doc/codewalk/markov.xml
index 085ead7bc..b7b711783 100644
--- a/doc/codewalk/markov.xml
+++ b/doc/codewalk/markov.xml
@@ -215,7 +215,7 @@ p[len(p)-1] = suffix
<step title="Choosing a suffix at random" src="doc/codewalk/markov.go:/next := choices/,/Shift/">
To choose a suffix we use the
- <code><a href="/pkg/rand/#Intn">rand.Intn</a></code> function.
+ <code><a href="/pkg/math/rand/#Intn">rand.Intn</a></code> function.
It returns a random integer up to (but not including) the provided
value. Passing in <code>len(choices)</code> gives us a random index
into the full length of the list.
@@ -287,11 +287,11 @@ a plan a man a plan a canal panama</pre>
Here's a transcript of generating some text using the Go distribution's
README file as source material:
<pre>
-$ ./markov -words=10 &lt $GOROOT/go/README
+$ ./markov -words=10 &lt; $GOROOT/README
This is the source code repository for the Go source
-$ ./markov -prefix=1 -words=10 &lt $GOROOT/go/README
+$ ./markov -prefix=1 -words=10 &lt; $GOROOT/README
This is the go directory (the one containing this README).
-$ ./markov -prefix=1 -words=10 &lt $GOROOT/go/README
+$ ./markov -prefix=1 -words=10 &lt; $GOROOT/README
This is the variable if you have just untarred a</pre>
</step>
diff --git a/doc/devel/release.html b/doc/devel/release.html
index 65946e31f..dda8239a6 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -35,6 +35,20 @@ The go1 release corresponds to
<code><a href="weekly.html#2012-03-27">weekly.2012-03-27</a></code>.
</p>
+<h3 id="go1.minor">Minor revisions</h3>
+
+<p>
+go1.0.1 (released 2012/04/25) was issued to
+<a href="https://code.google.com/p/go/source/detail?r=a890477d3dfb">fix</a> an
+<a href="https://code.google.com/p/go/issues/detail?id=3545">escape analysis
+bug</a> that can lead to memory corruption.
+It also includes several minor code and documentation fixes.
+</p>
+
+<p>
+See the <a href="http://code.google.com/p/go/source/list?name=release-branch.go1">go1 release branch history</a> for the complete list of changes.
+</p>
+
<h2 id="r60">r60 (released 2011/09/07)</h2>
<p>
diff --git a/doc/effective_go.html b/doc/effective_go.html
index ed777f4bb..6cacac630 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -2291,7 +2291,7 @@ This would be useful if we wanted to refine the methods of <code>Logger</code>.
</p>
<pre>
func (job *Job) Logf(format string, args ...interface{}) {
- job.Logger.Logf("%q: %s", job.Command, fmt.Sprintf(format, args))
+ job.Logger.Logf("%q: %s", job.Command, fmt.Sprintf(format, args...))
}
</pre>
<p>
@@ -2479,7 +2479,7 @@ func handle(queue chan *Request) {
}
}
-func Serve(clientRequests chan *clientRequests, quit chan bool) {
+func Serve(clientRequests chan *Request, quit chan bool) {
// Start handlers
for i := 0; i &lt; MaxOutstanding; i++ {
go handle(clientRequests)
diff --git a/doc/go1.html b/doc/go1.html
index 73d562acd..e1afe479a 100644
--- a/doc/go1.html
+++ b/doc/go1.html
@@ -1253,7 +1253,7 @@ Since the package's functionality is new, no updating is necessary.
<p>
In Go 1 the <a href="/pkg/net/http/"><code>http</code></a> package is refactored,
putting some of the utilities into a
-<a href="/pkg/net/httputil/"><code>httputil</code></a> subdirectory.
+<a href="/pkg/net/http/httputil/"><code>httputil</code></a> subdirectory.
These pieces are only rarely needed by HTTP clients.
The affected items are:
</p>
@@ -1261,7 +1261,6 @@ The affected items are:
<ul>
<li>ClientConn</li>
<li>DumpRequest</li>
-<li>DumpRequest</li>
<li>DumpRequestOut</li>
<li>DumpResponse</li>
<li>NewChunkedReader</li>
@@ -1789,7 +1788,7 @@ for full details.
<td colspan="2"><hr></td>
</tr>
<tr><td>Atoui(x)</td> <td>ParseUint(x, 10, 0)§</td></tr>
-<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
+<tr><td>Atoui64(x)</td> <td>ParseUint(x, 10, 64)</td></tr>
<tr>
<td colspan="2"><hr></td>
</tr>
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 2c905c723..8cb257a59 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1598,7 +1598,7 @@ Given a set of identifiers, an identifier is called <i>unique</i> if it is
<i>different</i> from every other in the set.
Two identifiers are different if they are spelled differently, or if they
appear in different <a href="#Packages">packages</a> and are not
-<a href="Exported_identifiers">exported</a>. Otherwise, they are the same.
+<a href="#Exported_identifiers">exported</a>. Otherwise, they are the same.
</p>
<h3 id="Constant_declarations">Constant declarations</h3>
@@ -2396,7 +2396,7 @@ type T2 struct {
func (recv *T2) M2()
-var p *T2 // with p != nil and p.T1 != nil
+var p *T2 // with p != nil and p.T0 != nil
</pre>
<p>
@@ -2659,7 +2659,7 @@ back to the calling function when the function returns.
</p>
<p>
-Calling a <code>nil</code> function value
+Calling a <code>nil</code> function value
causes a <a href="#Run_time_panics">run-time panic</a>.
</p>
@@ -3030,29 +3030,29 @@ These terms and the result of the comparisons are defined as follows:
<li>
Integer values are comparable and ordered, in the usual way.
</li>
-
+
<li>
Floating point values are comparable and ordered,
as defined by the IEEE-754 standard.
</li>
-
+
<li>
Complex values are comparable.
Two complex values <code>u</code> and <code>v</code> are
equal if both <code>real(u) == real(v)</code> and
<code>imag(u) == imag(v)</code>.
</li>
-
+
<li>
String values are comparable and ordered, lexically byte-wise.
</li>
-
+
<li>
Pointer values are comparable.
Two pointer values are equal if they point to the same variable or if both have value <code>nil</code>.
Pointers to distinct <a href="#Size_and_alignment_guarantees">zero-size</a> variables may or may not be equal.
</li>
-
+
<li>
Channel values are comparable.
Two channel values are equal if they were created by the same call to <code>make</code>
@@ -3065,7 +3065,7 @@ These terms and the result of the comparisons are defined as follows:
Two interface values are equal if they have <a href="#Type_identity">identical</a> dynamic types
and equal dynamic values or if both have value <code>nil</code>.
</li>
-
+
<li>
A value <code>x</code> of non-interface type <code>X</code> and
a value <code>t</code> of interface type <code>T</code> are comparable when values
@@ -3080,7 +3080,7 @@ These terms and the result of the comparisons are defined as follows:
Two struct values are equal if their corresponding
non-<a href="#Blank_identifier">blank</a> fields are equal.
</li>
-
+
<li>
Array values are comparable if values of the array element type are comparable.
Two array values are equal if their corresponding elements are equal.
@@ -5401,7 +5401,7 @@ type ArbitraryType int // shorthand for an arbitrary Go type; it is not a real
type Pointer *ArbitraryType
func Alignof(variable ArbitraryType) uintptr
-func Offsetof(selector ArbitraryType) uinptr
+func Offsetof(selector ArbitraryType) uintptr
func Sizeof(variable ArbitraryType) uintptr
</pre>
diff --git a/doc/install-source.html b/doc/install-source.html
index 4673850f4..080bceb4d 100644
--- a/doc/install-source.html
+++ b/doc/install-source.html
@@ -106,26 +106,13 @@ On Windows, install <code>gcc</code> with
<p>
To perform the next step you must have Mercurial installed. (Check that you
-have an <code>hg</code> command.) This suffices to install Mercurial on most
-Unix systems:
+have an <code>hg</code> command.)
</p>
-<pre>
-sudo easy_install mercurial==2.0
-</pre>
-
-<p>
-On Ubuntu/Debian, the Mercurial in your distribution's
-package repository is most likely old and broken.
-You might try this first:
-</p>
-
-<pre>apt-get install python-setuptools python-dev build-essential</pre>
-
<p>
-If that fails, or if you use Windows, install manually from the
-<a href="http://mercurial.selenic.com/wiki/Download">Mercurial Download</a>
-page.
+If you do not have a working Mercurial installation,
+follow the instructions on the
+<a href="http://mercurial.selenic.com/downloads/">Mercurial downloads</a> page.
</p>
<p>
diff --git a/doc/play/playground.js b/doc/play/playground.js
index 947f8a4ec..d7cc58d6e 100644
--- a/doc/play/playground.js
+++ b/doc/play/playground.js
@@ -6,13 +6,14 @@
// codeEl - code editor element
// outputEl - program output element
// runEl - run button element
+// fmtEl - fmt button element (optional)
// shareEl - share button element (optional)
// shareURLEl - share URL text input element (optional)
// shareRedirect - base URL to redirect to on share (optional)
-// preCompile - callback to mutate request data before compiling
-// postCompile - callback to read response data after compiling
-// simple - use plain textarea instead of CodeMirror.
-// toysEl - select element with a list of toys.
+// preCompile - callback to mutate request data before compiling (optional)
+// postCompile - callback to read response data after compiling (optional)
+// simple - use plain textarea instead of CodeMirror. (optional)
+// toysEl - select element with a list of toys. (optional)
function playground(opts) {
var simple = opts['simple'];
var code = $(opts['codeEl']);
@@ -97,7 +98,7 @@ function playground(opts) {
if (!editor) {
return;
}
- var errorRe = /[a-z]+\.go:([0-9]+): /g;
+ var errorRe = /[a-z]+\.go:([0-9]+):/g;
var result;
while ((result = errorRe.exec(text)) != null) {
var line = result[1]*1-1;
@@ -120,13 +121,23 @@ function playground(opts) {
function origin(href) {
return (""+href).split("/").slice(0, 3).join("/");
}
+ function loading() {
+ output.removeClass("error").html(
+ '<div class="loading">Waiting for remote server...</div>'
+ );
+ }
+ function setOutput(text, error) {
+ output.empty();
+ if (error) {
+ output.addClass("error");
+ }
+ $("<pre/>").text(text).appendTo(output);
+ }
var seq = 0;
function run() {
clearErrors();
- output.removeClass("error").html(
- '<div class="loading">Waiting for remote server...</div>'
- );
+ loading();
seq++;
var cur = seq;
var data = {"body": body()};
@@ -141,8 +152,6 @@ function playground(opts) {
if (seq != cur) {
return;
}
- pre = $("<pre/>");
- output.empty().append(pre);
if (opts['postCompile']) {
opts['postCompile'](data);
}
@@ -150,8 +159,7 @@ function playground(opts) {
return;
}
if (data.compile_errors != "") {
- pre.text(data.compile_errors);
- output.addClass("error");
+ setOutput(data.compile_errors, true);
highlightErrors(data.compile_errors);
return;
}
@@ -164,11 +172,10 @@ function playground(opts) {
output.empty().append(img);
return;
}
- pre.text(out);
+ setOutput(out, false);
},
error: function(xhr) {
var text = "Error communicating with remote server.";
- console.log(xhr.status);
if (xhr.status == 501) {
text = xhr.responseText;
}
@@ -178,6 +185,41 @@ function playground(opts) {
}
$(opts['runEl']).click(run);
+ $(opts['fmtEl']).click(function() {
+ loading();
+ $.ajax("/fmt", {
+ data: {"body": body()},
+ type: "POST",
+ dataType: "json",
+ success: function(data) {
+ if (data.Error) {
+ setOutput(data.Error, true);
+ highlightErrors(data.Error);
+ return;
+ }
+ setBody(data.Body);
+ setOutput("", false);
+ }
+ });
+ });
+
+ $(opts['toysEl']).bind('change', function() {
+ var toy = $(this).val();
+ loading();
+ $.ajax("/doc/play/"+toy, {
+ processData: false,
+ type: "GET",
+ complete: function(xhr) {
+ if (xhr.status != 200) {
+ setOutput("Server error; try again.", true);
+ return;
+ }
+ setBody(xhr.responseText);
+ setOutput("", false);
+ }
+ });
+ });
+
if (opts['shareEl'] != null && (opts['shareURLEl'] != null || opts['shareRedirect'] != null)) {
var shareURL;
if (opts['shareURLEl']) {
@@ -213,22 +255,5 @@ function playground(opts) {
});
}
- if (opts['toysEl'] != null) {
- $(opts['toysEl']).bind('change', function() {
- var toy = $(this).val();
- $.ajax("/doc/play/"+toy, {
- processData: false,
- type: "GET",
- complete: function(xhr) {
- if (xhr.status != 200) {
- alert("Server error; try again.")
- return;
- }
- setBody(xhr.responseText);
- }
- });
- });
- }
-
return editor;
}
diff --git a/doc/progs/image_draw.go b/doc/progs/image_draw.go
index 2cc5c632f..bb73c8a71 100644
--- a/doc/progs/image_draw.go
+++ b/doc/progs/image_draw.go
@@ -84,8 +84,8 @@ func ConvAndCircle() {
// CONV OMIT
b := src.Bounds()
- m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
- draw.Draw(m, m.Bounds(), src, b.Min, draw.Src)
+ m := image.NewRGBA(b)
+ draw.Draw(m, b, src, b.Min, draw.Src)
// STOP OMIT
p := image.Point{100, 100}
diff --git a/doc/style.css b/doc/style.css
index 95be3a17a..7f3384c6c 100644
--- a/doc/style.css
+++ b/doc/style.css
@@ -108,7 +108,9 @@ table.dir td {
word-wrap: break-word;
vertical-align: top;
}
-
+div#page.wide table.dir td.name {
+ white-space: nowrap;
+}
.alert {
color: #AA0000;
}
@@ -388,4 +390,3 @@ img.gopher {
margin-bottom: -120px;
}
h2 { clear: right; }
-
diff --git a/lib/godoc/package.html b/lib/godoc/package.html
index 41677a69d..5b7fce8d7 100644
--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -192,14 +192,14 @@
{{if $.DirFlat}}
{{if .HasPkg}}
<tr>
- <td><a href="{{html .Path}}">{{html .Path}}</a></td>
+ <td class="name"><a href="{{html .Path}}">{{html .Path}}</a></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td style="width: auto">{{html .Synopsis}}</td>
</tr>
{{end}}
{{else}}
<tr>
- <td>{{repeat `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;` .Depth}}<a href="{{html .Path}}">{{html .Name}}</a></td>
+ <td class="name">{{repeat `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;` .Depth}}<a href="{{html .Path}}">{{html .Name}}</a></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td style="width: auto">{{html .Synopsis}}</td>
</tr>
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index 567c9f336..3ef65f85d 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -19,7 +19,7 @@ char *goos;
char *goroot = GOROOT_FINAL;
char *goroot_final = GOROOT_FINAL;
char *workdir;
-char *tooldir;
+char *tooldir;
char *gochar;
char *goversion;
char *slash; // / for unix, \ for windows
@@ -1462,7 +1462,7 @@ void
cmdbanner(int argc, char **argv)
{
char *pathsep;
- Buf b, b1, search;
+ Buf b, b1, search, path;
ARGBEGIN{
case 'v':
@@ -1478,6 +1478,7 @@ cmdbanner(int argc, char **argv)
binit(&b);
binit(&b1);
binit(&search);
+ binit(&path);
xprintf("\n");
xprintf("---\n");
@@ -1495,9 +1496,10 @@ cmdbanner(int argc, char **argv)
xprintf("*** You need to add %s to your PATH.\n", gobin);
if(streq(gohostos, "darwin")) {
- xprintf("\n"
- "On OS X the debuggers must be installed setgid procmod.\n"
- "Read and run ./sudo.bash to install the debuggers.\n");
+ if(isfile(bpathf(&path, "%s/cov", tooldir)))
+ xprintf("\n"
+ "On OS X the debuggers must be installed setgid procmod.\n"
+ "Read and run ./sudo.bash to install the debuggers.\n");
}
if(!streq(goroot_final, goroot)) {
@@ -1509,6 +1511,7 @@ cmdbanner(int argc, char **argv)
bfree(&b);
bfree(&b1);
bfree(&search);
+ bfree(&path);
}
// Version prints the Go version.
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index 2614b5f35..8a265ce59 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -131,7 +131,12 @@ escfunc(Node *func)
}
// walk will take the address of cvar->closure later and assign it to cvar.
- // handle that here by linking a fake oaddr node directly to the closure.
+ // linking a fake oaddr node directly to the closure handles the case
+ // of the closure itself leaking. Following the flow of the value to th
+ // paramref is done in escflow, because if we did that here, it would look
+ // like the original is assigned out of its loop depth, whereas it's just
+ // assigned to something in an inner function. A paramref itself is never
+ // moved to the heap, only its original.
for(ll=curfn->cvars; ll; ll=ll->next) {
if(ll->n->op == OXXX) // see dcl.c:398
continue;
@@ -221,16 +226,19 @@ esc(Node *n)
if(n->op == OFOR || n->op == ORANGE)
loopdepth++;
- esc(n->left);
- esc(n->right);
- esc(n->ntest);
- esc(n->nincr);
- esclist(n->ninit);
- esclist(n->nbody);
- esclist(n->nelse);
- esclist(n->list);
- esclist(n->rlist);
-
+ if(n->op == OCLOSURE) {
+ escfunc(n);
+ } else {
+ esc(n->left);
+ esc(n->right);
+ esc(n->ntest);
+ esc(n->nincr);
+ esclist(n->ninit);
+ esclist(n->nbody);
+ esclist(n->nelse);
+ esclist(n->list);
+ esclist(n->rlist);
+ }
if(n->op == OFOR || n->op == ORANGE)
loopdepth--;
@@ -379,8 +387,8 @@ esc(Node *n)
}
break;
- case OADDR:
case OCLOSURE:
+ case OADDR:
case OMAKECHAN:
case OMAKEMAP:
case OMAKESLICE:
@@ -407,8 +415,8 @@ escassign(Node *dst, Node *src)
return;
if(debug['m'] > 1)
- print("%L:[%d] %S escassign: %hN = %hN\n", lineno, loopdepth,
- (curfn && curfn->nname) ? curfn->nname->sym : S, dst, src);
+ print("%L:[%d] %S escassign: %hN(%hJ) = %hN(%hJ)\n", lineno, loopdepth,
+ (curfn && curfn->nname) ? curfn->nname->sym : S, dst, dst, src, src);
setlineno(dst);
@@ -467,7 +475,11 @@ escassign(Node *dst, Node *src)
case OARRAYLIT:
case OMAPLIT:
case OSTRUCTLIT:
- // loopdepth was set in the defining statement or function header
+ case OMAKECHAN:
+ case OMAKEMAP:
+ case OMAKESLICE:
+ case ONEW:
+ case OCLOSURE:
escflows(dst, src);
break;
@@ -500,18 +512,6 @@ escassign(Node *dst, Node *src)
escassign(dst, src->left);
break;
- case OMAKECHAN:
- case OMAKEMAP:
- case OMAKESLICE:
- case ONEW:
- escflows(dst, src);
- break;
-
- case OCLOSURE:
- escflows(dst, src);
- escfunc(src);
- break;
-
case OADD:
case OSUB:
case OOR:
@@ -543,7 +543,7 @@ escassign(Node *dst, Node *src)
// This is a bit messier than fortunate, pulled out of escassign's big
// switch for clarity. We either have the paramnodes, which may be
// connected to other things throug flows or we have the parameter type
-// nodes, which may be marked 'n(ofloworescape)'. Navigating the ast is slightly
+// nodes, which may be marked "noescape". Navigating the ast is slightly
// different for methods vs plain functions and for imported vs
// this-package
static void
@@ -711,8 +711,8 @@ escwalk(int level, Node *dst, Node *src)
src->walkgen = walkgen;
if(debug['m']>1)
- print("escwalk: level:%d depth:%d %.*s %hN scope:%S[%d]\n",
- level, pdepth, pdepth, "\t\t\t\t\t\t\t\t\t\t", src,
+ print("escwalk: level:%d depth:%d %.*s %hN(%hJ) scope:%S[%d]\n",
+ level, pdepth, pdepth, "\t\t\t\t\t\t\t\t\t\t", src, src,
(src->curfn && src->curfn->nname) ? src->curfn->nname->sym : S, src->escloopdepth);
pdepth++;
@@ -726,6 +726,16 @@ escwalk(int level, Node *dst, Node *src)
if(debug['m'])
warnl(src->lineno, "leaking param: %hN", src);
}
+ // handle the missing flow ref <- orig
+ // a paramref is automagically dereferenced, and taking its
+ // address produces the address of the original, so all we have to do here
+ // is keep track of the value flow, so level is unchanged.
+ // alternatively, we could have substituted PPARAMREFs with their ->closure in esc/escassign/flow,
+ if(src->class == PPARAMREF) {
+ if(leaks && debug['m'])
+ warnl(src->lineno, "leaking closure reference %hN", src);
+ escwalk(level, dst, src->closure);
+ }
break;
case OPTRLIT:
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
index 4bfd5236d..32ede3964 100644
--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -227,15 +227,11 @@ The -u flag instructs get to use the network to update the named packages
and their dependencies. By default, get uses the network to check out
missing packages but does not use it to look for updates to existing packages.
-When checking out or updating a package, get looks for a branch or
-tag that matches the locally installed version of Go. If the local
-version "is release.rNN", it searches for "go.rNN". (For an
-installation using Go version "weekly.YYYY-MM-DD", it searches for a
-package version labeled "go.YYYY-MM-DD".) If the desired version
-cannot be found but others exist with labels in the correct format,
-get retrieves the most recent version before the desired label.
-Finally, if all else fails it retrieves the most recent version of
-the package.
+When checking out or updating a package, get looks for a branch or tag
+that matches the locally installed version of Go. The most important
+rule is that if the local installation is running version "go1", get
+searches for a branch or tag named "go1". If no such version exists it
+retrieves the most recent version of the package.
For more about specifying packages, see 'go help packages'.
diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go
index f70b6761d..fe45697e2 100644
--- a/src/cmd/go/get.go
+++ b/src/cmd/go/get.go
@@ -37,15 +37,11 @@ The -u flag instructs get to use the network to update the named packages
and their dependencies. By default, get uses the network to check out
missing packages but does not use it to look for updates to existing packages.
-When checking out or updating a package, get looks for a branch or
-tag that matches the locally installed version of Go. If the local
-version "is release.rNN", it searches for "go.rNN". (For an
-installation using Go version "weekly.YYYY-MM-DD", it searches for a
-package version labeled "go.YYYY-MM-DD".) If the desired version
-cannot be found but others exist with labels in the correct format,
-get retrieves the most recent version before the desired label.
-Finally, if all else fails it retrieves the most recent version of
-the package.
+When checking out or updating a package, get looks for a branch or tag
+that matches the locally installed version of Go. The most important
+rule is that if the local installation is running version "go1", get
+searches for a branch or tag named "go1". If no such version exists it
+retrieves the most recent version of the package.
For more about specifying packages, see 'go help packages'.
@@ -339,56 +335,32 @@ var goTag = regexp.MustCompile(
// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.
// Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number).
// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
+//
+// NOTE(rsc): Eventually we will need to decide on some logic here.
+// For now, there is only "go1". This matches the docs in go help get.
func selectTag(goVersion string, tags []string) (match string) {
- const rPrefix = "release.r"
- if strings.HasPrefix(goVersion, rPrefix) {
- p := "go.r"
- v, err := strconv.ParseFloat(goVersion[len(rPrefix):], 64)
- if err != nil {
- return ""
- }
- var matchf float64
- for _, t := range tags {
- if !strings.HasPrefix(t, p) {
- continue
- }
- tf, err := strconv.ParseFloat(t[len(p):], 64)
- if err != nil {
- continue
- }
- if matchf < tf && tf <= v {
- match, matchf = t, tf
- }
+ for _, t := range tags {
+ if t == "go1" {
+ return "go1"
}
}
-
- const wPrefix = "weekly."
- if strings.HasPrefix(goVersion, wPrefix) {
- p := "go.weekly."
- v := goVersion[len(wPrefix):]
- for _, t := range tags {
- if !strings.HasPrefix(t, p) {
- continue
- }
- if match < t && t[len(p):] <= v {
- match = t
- }
- }
- }
-
- if goTag.MatchString(goVersion) {
- v := goVersion
- for _, t := range tags {
- if !goTag.MatchString(t) {
- continue
- }
- if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
- match = t
+ return ""
+
+ /*
+ if goTag.MatchString(goVersion) {
+ v := goVersion
+ for _, t := range tags {
+ if !goTag.MatchString(t) {
+ continue
+ }
+ if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
+ match = t
+ }
}
}
- }
- return match
+ return match
+ */
}
// cmpGoVersion returns -1, 0, +1 reporting whether
diff --git a/src/cmd/go/tag_test.go b/src/cmd/go/tag_test.go
index 556a84a8e..ffe218c7b 100644
--- a/src/cmd/go/tag_test.go
+++ b/src/cmd/go/tag_test.go
@@ -50,41 +50,44 @@ var selectTagTests = []struct {
version string
selected string
}{
- {"release.r57", ""},
- {"release.r58.2", "go.r58.1"},
- {"release.r59", "go.r59"},
- {"release.r59.1", "go.r59.1"},
- {"release.r60", "go.r59.1"},
- {"release.r60.1", "go.r59.1"},
- {"release.r61", "go.r61"},
- {"release.r66", "go.r61.1"},
- {"weekly.2010-01-01", ""},
- {"weekly.2010-01-02", "go.weekly.2010-01-02"},
- {"weekly.2010-01-02.1", "go.weekly.2010-01-02"},
- {"weekly.2010-01-03", "go.weekly.2010-01-02"},
- {"weekly.2011-10-12", "go.weekly.2011-10-12"},
- {"weekly.2011-10-12.1", "go.weekly.2011-10-12.1"},
- {"weekly.2011-10-13", "go.weekly.2011-10-12.1"},
- {"weekly.2011-10-14", "go.weekly.2011-10-14"},
- {"weekly.2011-10-14.1", "go.weekly.2011-10-14"},
- {"weekly.2011-11-01", "go.weekly.2011-11-01"},
- {"weekly.2014-01-01", "go.weekly.2011-11-01"},
- {"weekly.3000-01-01", "go.weekly.2011-11-01"},
- {"go1", "go1"},
- {"go1.1", "go1.0.1"},
- {"go1.998", "go1.9.2"},
- {"go1.1000", "go1.999"},
- {"go6", "go5"},
+ /*
+ {"release.r57", ""},
+ {"release.r58.2", "go.r58.1"},
+ {"release.r59", "go.r59"},
+ {"release.r59.1", "go.r59.1"},
+ {"release.r60", "go.r59.1"},
+ {"release.r60.1", "go.r59.1"},
+ {"release.r61", "go.r61"},
+ {"release.r66", "go.r61.1"},
+ {"weekly.2010-01-01", ""},
+ {"weekly.2010-01-02", "go.weekly.2010-01-02"},
+ {"weekly.2010-01-02.1", "go.weekly.2010-01-02"},
+ {"weekly.2010-01-03", "go.weekly.2010-01-02"},
+ {"weekly.2011-10-12", "go.weekly.2011-10-12"},
+ {"weekly.2011-10-12.1", "go.weekly.2011-10-12.1"},
+ {"weekly.2011-10-13", "go.weekly.2011-10-12.1"},
+ {"weekly.2011-10-14", "go.weekly.2011-10-14"},
+ {"weekly.2011-10-14.1", "go.weekly.2011-10-14"},
+ {"weekly.2011-11-01", "go.weekly.2011-11-01"},
+ {"weekly.2014-01-01", "go.weekly.2011-11-01"},
+ {"weekly.3000-01-01", "go.weekly.2011-11-01"},
+ {"go1", "go1"},
+ {"go1.1", "go1.0.1"},
+ {"go1.998", "go1.9.2"},
+ {"go1.1000", "go1.999"},
+ {"go6", "go5"},
- // faulty versions:
- {"release.f00", ""},
- {"weekly.1999-01-01", ""},
- {"junk", ""},
- {"", ""},
- {"go2x", ""},
- {"go200000000000", ""},
- {"go2.", ""},
- {"go2.0", ""},
+ // faulty versions:
+ {"release.f00", ""},
+ {"weekly.1999-01-01", ""},
+ {"junk", ""},
+ {"", ""},
+ {"go2x", ""},
+ {"go200000000000", ""},
+ {"go2.", ""},
+ {"go2.0", ""},
+ */
+ {"anything", "go1"},
}
func TestSelectTag(t *testing.T) {
diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
index 5f63f8b56..1c121672f 100644
--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -422,11 +422,15 @@ func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) {
func repoRootForImportDynamic(importPath string) (*repoRoot, error) {
slash := strings.Index(importPath, "/")
if slash < 0 {
- return nil, fmt.Errorf("missing / in import %q", importPath)
+ return nil, errors.New("import path doesn't contain a slash")
+ }
+ host := importPath[:slash]
+ if !strings.Contains(host, ".") {
+ return nil, errors.New("import path doesn't contain a hostname")
}
urlStr, body, err := httpsOrHTTP(importPath)
if err != nil {
- return nil, fmt.Errorf("http/https fetch for import %q: %v", importPath, err)
+ return nil, fmt.Errorf("http/https fetch: %v", err)
}
defer body.Close()
metaImport, err := matchGoImport(parseMetaGoImports(body), importPath)
diff --git a/src/cmd/godoc/README.godoc-app b/src/cmd/godoc/README.godoc-app
index 88cfee41e..cff7d387c 100644
--- a/src/cmd/godoc/README.godoc-app
+++ b/src/cmd/godoc/README.godoc-app
@@ -8,8 +8,8 @@ godoc on appengine
Prerequisites
-------------
-* Go appengine SDK 1.5.5 - 2011-10-11
- http://code.google.com/appengine/downloads.html#Google_App_Engine_SDK_for_Go
+* Go appengine SDK
+ https://developers.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go
* Go sources at tip under $GOROOT
@@ -23,10 +23,6 @@ Directory structure
* $APPDIR contains the following entries (this may change depending on
app-engine release and version of godoc):
- alt/
- encoding/binary/
- go/*
- index/suffixarray/
app.yaml
godoc.zip
godoc/
@@ -36,31 +32,16 @@ Directory structure
For instance:
application: godoc-app
- version: 1-5-5
+ version: 1
runtime: go
- api_version: 3
+ api_version: go1
handlers:
- url: /.*
script: _go_app
* The godoc/ directory contains a copy of the files under $GOROOT/src/cmd/godoc
- with modifications:
-
- - doc.go is excluded (it belongs to pseudo-package ÒdocumentationÓ)
- - main.go is excluded (appinit.go is taking its place)
-
- Additional manual modifications are required to refer to the alt/ packages
- where the app-engine library is not up-to-date with the godoc version.
-
-* The alt/ directory contains up-to-date copies of Go packages that a tip-based
- godoc is dependent on but which do not yet exist in the current app-engine SDK.
- At the time of this writing (10/14/2011) this is the entire go directory tree
- (for the missing FileSet serialization code in go/token) as well as the
- index/suffixarray package (for the missing suffix array serialization code).
- The latest (alt/)index/suffixarray package internally requires the latest
- version of encoding/binary, which is why it also needs to be present under
- alt/.
+ with doc.go excluded (it belongs to pseudo-package "documentation")
Configuring and running godoc
diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go
index da4fc63b5..2e2889ed3 100644
--- a/src/cmd/godoc/main.go
+++ b/src/cmd/godoc/main.go
@@ -23,6 +23,8 @@
// godoc crypto/block Cipher NewCMAC
// - prints doc for Cipher and NewCMAC in package crypto/block
+// +build !appengine
+
package main
import (
diff --git a/src/cmd/godoc/setup-godoc-app.bash b/src/cmd/godoc/setup-godoc-app.bash
index 755d965d5..b8dc4dcf9 100644
--- a/src/cmd/godoc/setup-godoc-app.bash
+++ b/src/cmd/godoc/setup-godoc-app.bash
@@ -44,8 +44,8 @@ getArgs() {
if [ ! -d $GOROOT ]; then
error "$GOROOT is not a directory"
fi
- if [ ! -x $GOROOT/src/cmd/godoc/godoc ]; then
- error "$GOROOT/src/cmd/godoc/godoc does not exist or is not executable"
+ if [ ! -x $GOROOT/bin/godoc ]; then
+ error "$GOROOT/bin/godoc does not exist or is not executable"
fi
if [ ! -d $APPDIR ]; then
error "$APPDIR is not a directory"
@@ -72,15 +72,15 @@ cleanup() {
makeZipfile() {
echo "*** make $APPDIR/$ZIPFILE"
- zip -q -r $APPDIR/$ZIPFILE $GOROOT -i \*.go -i \*.html -i \*.css -i \*.js -i \*.txt -i \*.c -i \*.h -i \*.s -i \*.png -i \*.jpg -i \*.sh -i \*.ico
+ zip -q -r $APPDIR/$ZIPFILE $GOROOT -i \*.go -i \*.html -i \*.xml -i \*.css -i \*.js -i \*.txt -i \*.c -i \*.h -i \*.s -i \*.png -i \*.jpg -i \*.sh -i \*.ico
}
makeIndexfile() {
echo "*** make $APPDIR/$INDEXFILE"
OUT=/tmp/godoc.out
- $GOROOT/src/cmd/godoc/godoc -write_index -index_files=$APPDIR/$INDEXFILE -zip=$APPDIR/$ZIPFILE 2> $OUT
+ $GOROOT/bin/godoc -write_index -index_files=$APPDIR/$INDEXFILE -zip=$APPDIR/$ZIPFILE 2> $OUT
if [ $? != 0 ]; then
- error "$GOROOT/src/cmd/godoc/godoc failed - see $OUT for details"
+ error "$GOROOT/bin/godoc failed - see $OUT for details"
fi
}
diff --git a/src/pkg/crypto/tls/cipher_suites.go b/src/pkg/crypto/tls/cipher_suites.go
index 00695e7d1..5039f319f 100644
--- a/src/pkg/crypto/tls/cipher_suites.go
+++ b/src/pkg/crypto/tls/cipher_suites.go
@@ -23,8 +23,8 @@ type keyAgreement interface {
// In the case that the key agreement protocol doesn't use a
// ServerKeyExchange message, generateServerKeyExchange can return nil,
// nil.
- generateServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
- processClientKeyExchange(*Config, *clientKeyExchangeMsg, uint16) ([]byte, error)
+ generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
+ processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
// On the client side, the next two methods are called in order.
diff --git a/src/pkg/crypto/tls/handshake_server.go b/src/pkg/crypto/tls/handshake_server.go
index 77e56a754..76adc540c 100644
--- a/src/pkg/crypto/tls/handshake_server.go
+++ b/src/pkg/crypto/tls/handshake_server.go
@@ -112,37 +112,38 @@ FindCipherSuite:
hello.nextProtoNeg = true
hello.nextProtos = config.NextProtos
}
- if clientHello.ocspStapling && len(config.Certificates[0].OCSPStaple) > 0 {
- hello.ocspStapling = true
- }
-
- finishedHash.Write(hello.marshal())
- c.writeRecord(recordTypeHandshake, hello.marshal())
if len(config.Certificates) == 0 {
return c.sendAlert(alertInternalError)
}
-
- certMsg := new(certificateMsg)
+ cert := &config.Certificates[0]
if len(clientHello.serverName) > 0 {
c.serverName = clientHello.serverName
- certMsg.certificates = config.getCertificateForName(clientHello.serverName).Certificate
- } else {
- certMsg.certificates = config.Certificates[0].Certificate
+ cert = config.getCertificateForName(clientHello.serverName)
}
+
+ if clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
+ hello.ocspStapling = true
+ }
+
+ finishedHash.Write(hello.marshal())
+ c.writeRecord(recordTypeHandshake, hello.marshal())
+
+ certMsg := new(certificateMsg)
+ certMsg.certificates = cert.Certificate
finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
if hello.ocspStapling {
certStatus := new(certificateStatusMsg)
certStatus.statusType = statusTypeOCSP
- certStatus.response = config.Certificates[0].OCSPStaple
+ certStatus.response = cert.OCSPStaple
finishedHash.Write(certStatus.marshal())
c.writeRecord(recordTypeHandshake, certStatus.marshal())
}
keyAgreement := suite.ka()
- skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
+ skx, err := keyAgreement.generateServerKeyExchange(config, cert, clientHello, hello)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
@@ -288,7 +289,7 @@ FindCipherSuite:
finishedHash.Write(certVerify.marshal())
}
- preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx, c.vers)
+ preMasterSecret, err := keyAgreement.processClientKeyExchange(config, cert, ckx, c.vers)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
diff --git a/src/pkg/crypto/tls/handshake_server_test.go b/src/pkg/crypto/tls/handshake_server_test.go
index 08a0ccb09..7c1267101 100644
--- a/src/pkg/crypto/tls/handshake_server_test.go
+++ b/src/pkg/crypto/tls/handshake_server_test.go
@@ -37,9 +37,12 @@ func init() {
testConfig = new(Config)
testConfig.Time = func() time.Time { return time.Unix(0, 0) }
testConfig.Rand = zeroSource{}
- testConfig.Certificates = make([]Certificate, 1)
+ testConfig.Certificates = make([]Certificate, 2)
testConfig.Certificates[0].Certificate = [][]byte{testCertificate}
testConfig.Certificates[0].PrivateKey = testPrivateKey
+ testConfig.Certificates[1].Certificate = [][]byte{testSNICertificate}
+ testConfig.Certificates[1].PrivateKey = testPrivateKey
+ testConfig.BuildNameToCertificate()
testConfig.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
testConfig.InsecureSkipVerify = true
}
@@ -176,6 +179,13 @@ func TestHandshakeServerSSLv3(t *testing.T) {
testServerScript(t, "SSLv3", sslv3ServerScript, testConfig, nil)
}
+// TestHandshakeServerSNI involves a client sending an SNI extension of
+// "snitest.com", which happens to match the CN of testSNICertificate. The test
+// verifies that the server correctly selects that certificate.
+func TestHandshakeServerSNI(t *testing.T) {
+ testServerScript(t, "SNI", selectCertificateBySNIScript, testConfig, nil)
+}
+
type clientauthTest struct {
name string
clientauth ClientAuthType
@@ -258,6 +268,8 @@ func fromHex(s string) []byte {
var testCertificate = fromHex("308202b030820219a00302010202090085b0bba48a7fb8ca300d06092a864886f70d01010505003045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3130303432343039303933385a170d3131303432343039303933385a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819f300d06092a864886f70d010101050003818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a381a73081a4301d0603551d0e04160414b1ade2855acfcb28db69ce2369ded3268e18883930750603551d23046e306c8014b1ade2855acfcb28db69ce2369ded3268e188839a149a4473045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746482090085b0bba48a7fb8ca300c0603551d13040530030101ff300d06092a864886f70d010105050003818100086c4524c76bb159ab0c52ccf2b014d7879d7a6475b55a9566e4c52b8eae12661feb4f38b36e60d392fdf74108b52513b1187a24fb301dbaed98b917ece7d73159db95d31d78ea50565cd5825a2d5a5f33c4b6d8c97590968c0f5298b5cd981f89205ff2a01ca31b9694dda9fd57e970e8266d71999b266e3850296c90a7bdd9")
+var testSNICertificate = fromHex("308201f23082015da003020102020100300b06092a864886f70d01010530283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d301e170d3132303431313137343033355a170d3133303431313137343533355a30283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d30819d300b06092a864886f70d01010103818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a3323030300e0603551d0f0101ff0404030200a0300d0603551d0e0406040401020304300f0603551d2304083006800401020304300b06092a864886f70d0101050381810089c6455f1c1f5ef8eb1ab174ee2439059f5c4259bb1a8d86cdb1d056f56a717da40e95ab90f59e8deaf627c157995094db0802266eb34fc6842dea8a4b68d9c1389103ab84fb9e1f85d9b5d23ff2312c8670fbb540148245a4ebafe264d90c8a4cf4f85b0fac12ac2fc4a3154bad52462868af96c62c6525d652b6e31845bdcc")
+
var testPrivateKey = &rsa.PrivateKey{
PublicKey: rsa.PublicKey{
N: bigFromString("131650079503776001033793877885499001334664249354723305978524647182322416328664556247316495448366990052837680518067798333412266673813370895702118944398081598789828837447552603077848001020611640547221687072142537202428102790818451901395596882588063427854225330436740647715202971973145151161964464812406232198521"),
@@ -947,6 +959,142 @@ var sslv3ServerScript = [][]byte{
},
}
+var selectCertificateBySNIScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x6e, 0x01, 0x00, 0x00,
+ 0x6a, 0x03, 0x01, 0x4f, 0x85, 0xc4, 0xc2, 0xb9,
+ 0x39, 0x80, 0x91, 0x66, 0x65, 0x56, 0x8e, 0xdd,
+ 0x48, 0xe9, 0xca, 0x34, 0x02, 0x3c, 0xaf, 0x0d,
+ 0x73, 0xb5, 0x2a, 0x05, 0x6e, 0xbd, 0x5e, 0x8f,
+ 0x38, 0xf9, 0xe5, 0x00, 0x00, 0x28, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+ 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+ 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x0e, 0x00, 0x00, 0x0b, 0x73, 0x6e, 0x69, 0x74,
+ 0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
+ 0x23, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+ 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+ 0x03, 0x01, 0x02, 0x00, 0x0b, 0x00, 0x01, 0xfc,
+ 0x00, 0x01, 0xf9, 0x00, 0x01, 0xf6, 0x30, 0x82,
+ 0x01, 0xf2, 0x30, 0x82, 0x01, 0x5d, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0b,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x30, 0x28, 0x31, 0x10, 0x30,
+ 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07,
+ 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, 0x31,
+ 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x0b, 0x73, 0x6e, 0x69, 0x74, 0x65, 0x73,
+ 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17,
+ 0x0d, 0x31, 0x32, 0x30, 0x34, 0x31, 0x31, 0x31,
+ 0x37, 0x34, 0x30, 0x33, 0x35, 0x5a, 0x17, 0x0d,
+ 0x31, 0x33, 0x30, 0x34, 0x31, 0x31, 0x31, 0x37,
+ 0x34, 0x35, 0x33, 0x35, 0x5a, 0x30, 0x28, 0x31,
+ 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43,
+ 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x0b, 0x73, 0x6e, 0x69, 0x74,
+ 0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
+ 0x81, 0x9d, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x03,
+ 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81,
+ 0x81, 0x00, 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5,
+ 0xe5, 0xbf, 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe,
+ 0xe6, 0x2b, 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d,
+ 0x8a, 0x7a, 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7,
+ 0xa5, 0x65, 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c,
+ 0xb5, 0xb4, 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b,
+ 0x7e, 0x62, 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe,
+ 0x12, 0x5c, 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf,
+ 0xfa, 0x58, 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04,
+ 0xd3, 0xd0, 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4,
+ 0x54, 0x9f, 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00,
+ 0xfe, 0x18, 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d,
+ 0x7d, 0xf1, 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb,
+ 0x51, 0xc9, 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32,
+ 0x66, 0x01, 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71,
+ 0x9a, 0x1d, 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda,
+ 0x2d, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,
+ 0x32, 0x30, 0x30, 0x30, 0x0e, 0x06, 0x03, 0x55,
+ 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
+ 0x02, 0x00, 0xa0, 0x30, 0x0d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x06, 0x04, 0x04, 0x01, 0x02,
+ 0x03, 0x04, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x08, 0x30, 0x06, 0x80, 0x04, 0x01,
+ 0x02, 0x03, 0x04, 0x30, 0x0b, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x03, 0x81, 0x81, 0x00, 0x89, 0xc6, 0x45, 0x5f,
+ 0x1c, 0x1f, 0x5e, 0xf8, 0xeb, 0x1a, 0xb1, 0x74,
+ 0xee, 0x24, 0x39, 0x05, 0x9f, 0x5c, 0x42, 0x59,
+ 0xbb, 0x1a, 0x8d, 0x86, 0xcd, 0xb1, 0xd0, 0x56,
+ 0xf5, 0x6a, 0x71, 0x7d, 0xa4, 0x0e, 0x95, 0xab,
+ 0x90, 0xf5, 0x9e, 0x8d, 0xea, 0xf6, 0x27, 0xc1,
+ 0x57, 0x99, 0x50, 0x94, 0xdb, 0x08, 0x02, 0x26,
+ 0x6e, 0xb3, 0x4f, 0xc6, 0x84, 0x2d, 0xea, 0x8a,
+ 0x4b, 0x68, 0xd9, 0xc1, 0x38, 0x91, 0x03, 0xab,
+ 0x84, 0xfb, 0x9e, 0x1f, 0x85, 0xd9, 0xb5, 0xd2,
+ 0x3f, 0xf2, 0x31, 0x2c, 0x86, 0x70, 0xfb, 0xb5,
+ 0x40, 0x14, 0x82, 0x45, 0xa4, 0xeb, 0xaf, 0xe2,
+ 0x64, 0xd9, 0x0c, 0x8a, 0x4c, 0xf4, 0xf8, 0x5b,
+ 0x0f, 0xac, 0x12, 0xac, 0x2f, 0xc4, 0xa3, 0x15,
+ 0x4b, 0xad, 0x52, 0x46, 0x28, 0x68, 0xaf, 0x96,
+ 0xc6, 0x2c, 0x65, 0x25, 0xd6, 0x52, 0xb6, 0xe3,
+ 0x18, 0x45, 0xbd, 0xcc, 0x16, 0x03, 0x01, 0x00,
+ 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+ 0x82, 0x00, 0x80, 0x70, 0x1d, 0x34, 0x75, 0xa2,
+ 0xe7, 0xe3, 0x2f, 0x3d, 0xc1, 0x1d, 0xca, 0x0b,
+ 0xe3, 0x64, 0xb9, 0x1a, 0x00, 0x69, 0xc4, 0x14,
+ 0x05, 0x07, 0x7e, 0xc3, 0x51, 0x43, 0x52, 0x66,
+ 0xe3, 0xbd, 0xff, 0x1b, 0x1a, 0x6a, 0x84, 0xf2,
+ 0x07, 0x24, 0xd7, 0x12, 0xa8, 0x58, 0xcf, 0x8a,
+ 0x50, 0x30, 0xe8, 0xc8, 0xb2, 0xf9, 0x58, 0x1c,
+ 0x56, 0x53, 0x76, 0x21, 0xe0, 0x03, 0x7f, 0x77,
+ 0xa7, 0xf1, 0xad, 0x67, 0xd4, 0xe2, 0x8f, 0xa0,
+ 0x58, 0x6c, 0xe0, 0x28, 0x59, 0xf3, 0xd1, 0x53,
+ 0x2b, 0x21, 0xbd, 0xa3, 0x84, 0x31, 0x73, 0xbf,
+ 0x84, 0x0f, 0x83, 0xf4, 0xc4, 0xd0, 0xe5, 0x3c,
+ 0x2d, 0x3e, 0xf2, 0x8a, 0x1e, 0xe7, 0xe9, 0x1f,
+ 0x12, 0x13, 0xad, 0x29, 0xd6, 0x0c, 0xc7, 0xc6,
+ 0x05, 0x53, 0x7d, 0x5e, 0xc6, 0x92, 0x72, 0xba,
+ 0xd2, 0x93, 0x8f, 0x53, 0x84, 0x87, 0x44, 0x05,
+ 0x9f, 0x5d, 0x66, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xfc, 0x71,
+ 0xaa, 0xa8, 0x37, 0xa8, 0xbd, 0x63, 0xb7, 0xbc,
+ 0x95, 0xef, 0x0c, 0xcf, 0x39, 0x31, 0x93, 0xe6,
+ 0x86, 0xbd, 0x3f, 0x56, 0x9d, 0xf0, 0xb2, 0xb5,
+ 0xd1, 0xa7, 0xc6, 0x45, 0x89, 0x18, 0xfb, 0xa0,
+ 0x7f, 0xc1,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0xb8, 0x6d, 0x9a, 0x90, 0x3c,
+ 0x45, 0xe0, 0xff, 0x63, 0xba, 0xab, 0x3d, 0x7a,
+ 0xa6, 0x49, 0x5a, 0x13, 0xdc, 0x0e, 0xa3, 0xba,
+ 0x7f, 0x04, 0x19, 0x45, 0xfd, 0xfb, 0xbd, 0x00,
+ 0xa3, 0xa7, 0x78, 0x81, 0x38, 0x9f, 0x10, 0x17,
+ 0x03, 0x01, 0x00, 0x21, 0x43, 0xc3, 0x91, 0xb7,
+ 0xbf, 0x50, 0x0b, 0x04, 0xb4, 0x5d, 0xc6, 0x20,
+ 0x64, 0xb8, 0x01, 0x09, 0x25, 0x2c, 0x03, 0x30,
+ 0xc0, 0x77, 0xc9, 0x5e, 0xe6, 0xe0, 0x99, 0xdc,
+ 0xcd, 0x75, 0x9d, 0x51, 0x82, 0x15, 0x03, 0x01,
+ 0x00, 0x16, 0x2d, 0x7a, 0x89, 0x7b, 0x36, 0x85,
+ 0x2a, 0x93, 0xcb, 0x83, 0xa7, 0x2f, 0x9e, 0x91,
+ 0xfc, 0xad, 0x57, 0xca, 0xf5, 0xbc, 0x13, 0x2f,
+ },
+}
+
var clientauthTests = []clientauthTest{
// Server doesn't asks for cert
// go test -run "TestRunServer" -serve -clientauth 0
@@ -1285,7 +1433,7 @@ var clientauthTests = []clientauthTest{
// go test -run "TestRunServer" -serve -clientauth 1
// gnutls-cli --insecure --debug 100 -p 10443 localhost
{"RequestClientCert, client gives it", RequestClientCert,
- []*x509.Certificate{clicert},
+ []*x509.Certificate{clientCertificate},
[][]byte{{
0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
0x76, 0x03, 0x02, 0x4e, 0xe7, 0x44, 0xda, 0x58,
@@ -1528,14 +1676,16 @@ var clientauthTests = []clientauthTest{
0x00, 0x16, 0x53, 0xf5, 0xff, 0xe0, 0xa1, 0x6c,
0x33, 0xf4, 0x4e, 0x89, 0x68, 0xe1, 0xf7, 0x61,
0x13, 0xb3, 0x12, 0xa1, 0x8e, 0x5a, 0x7a, 0x02,
- }}},
+ },
+ },
+ },
}
// cert.pem and key.pem were generated with generate_cert.go
// Thus, they have no ExtKeyUsage fields and trigger an error
// when verification is turned on.
-var clicert = loadPEMCert(`
+var clientCertificate = loadPEMCert(`
-----BEGIN CERTIFICATE-----
MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4
diff --git a/src/pkg/crypto/tls/key_agreement.go b/src/pkg/crypto/tls/key_agreement.go
index a931d8fb5..b6e73fe29 100644
--- a/src/pkg/crypto/tls/key_agreement.go
+++ b/src/pkg/crypto/tls/key_agreement.go
@@ -20,11 +20,11 @@ import (
// encrypts the pre-master secret to the server's public key.
type rsaKeyAgreement struct{}
-func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
return nil, nil
}
-func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
preMasterSecret := make([]byte, 48)
_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
if err != nil {
@@ -44,7 +44,7 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKe
ciphertext = ckx.ciphertext[2:]
}
- err = rsa.DecryptPKCS1v15SessionKey(config.rand(), config.Certificates[0].PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
+ err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
if err != nil {
return nil, err
}
@@ -109,7 +109,7 @@ type ecdheRSAKeyAgreement struct {
x, y *big.Int
}
-func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
var curveid uint16
Curve:
@@ -151,7 +151,7 @@ Curve:
copy(serverECDHParams[4:], ecdhePublic)
md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
- sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1)
+ sig, err := rsa.SignPKCS1v15(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1)
if err != nil {
return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
}
@@ -167,7 +167,7 @@ Curve:
return skx, nil
}
-func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errors.New("bad ClientKeyExchange")
}
diff --git a/src/pkg/database/sql/sql.go b/src/pkg/database/sql/sql.go
index 51a357b37..89136ef6e 100644
--- a/src/pkg/database/sql/sql.go
+++ b/src/pkg/database/sql/sql.go
@@ -327,6 +327,9 @@ func (db *DB) prepare(query string) (stmt *Stmt, err error) {
// Exec executes a query without returning any rows.
func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
sargs, err := subsetTypeArgs(args)
+ if err != nil {
+ return nil, err
+ }
var res Result
for i := 0; i < 10; i++ {
res, err = db.exec(query, sargs)
diff --git a/src/pkg/encoding/ascii85/ascii85.go b/src/pkg/encoding/ascii85/ascii85.go
index 7d004b5e5..705022792 100644
--- a/src/pkg/encoding/ascii85/ascii85.go
+++ b/src/pkg/encoding/ascii85/ascii85.go
@@ -57,6 +57,7 @@ func Encode(dst, src []byte) int {
if v == 0 && len(src) >= 4 {
dst[0] = 'z'
dst = dst[1:]
+ src = src[4:]
n++
continue
}
diff --git a/src/pkg/encoding/ascii85/ascii85_test.go b/src/pkg/encoding/ascii85/ascii85_test.go
index 70e67d8b0..42cf7e80e 100644
--- a/src/pkg/encoding/ascii85/ascii85_test.go
+++ b/src/pkg/encoding/ascii85/ascii85_test.go
@@ -28,6 +28,11 @@ var pairs = []testpair{
"l(DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G\n" +
">uD.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c\n",
},
+ // Special case when shortening !!!!! to z.
+ {
+ "\000\000\000\000",
+ "z",
+ },
}
var bigtest = pairs[len(pairs)-1]
diff --git a/src/pkg/encoding/asn1/asn1.go b/src/pkg/encoding/asn1/asn1.go
index 3bf81a68c..ac2b5f8da 100644
--- a/src/pkg/encoding/asn1/asn1.go
+++ b/src/pkg/encoding/asn1/asn1.go
@@ -377,11 +377,6 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
} else {
// Bottom 7 bits give the number of length bytes to follow.
numBytes := int(b & 0x7f)
- // We risk overflowing a signed 32-bit number if we accept more than 3 bytes.
- if numBytes > 3 {
- err = StructuralError{"length too large"}
- return
- }
if numBytes == 0 {
err = SyntaxError{"indefinite length found (not DER)"}
return
@@ -394,8 +389,19 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
}
b = bytes[offset]
offset++
+ if ret.length >= 1<<23 {
+ // We can't shift ret.length up without
+ // overflowing.
+ err = StructuralError{"length too large"}
+ return
+ }
ret.length <<= 8
ret.length |= int(b)
+ if ret.length == 0 {
+ // DER requires that lengths be minimal.
+ err = StructuralError{"superfluous leading zeros in length"}
+ return
+ }
}
}
diff --git a/src/pkg/encoding/asn1/asn1_test.go b/src/pkg/encoding/asn1/asn1_test.go
index 93803f435..eb848bdb4 100644
--- a/src/pkg/encoding/asn1/asn1_test.go
+++ b/src/pkg/encoding/asn1/asn1_test.go
@@ -283,6 +283,12 @@ var tagAndLengthData = []tagAndLengthTest{
{[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}},
{[]byte{0x1f, 0x85}, false, tagAndLength{}},
{[]byte{0x30, 0x80}, false, tagAndLength{}},
+ // Superfluous zeros in the length should be an error.
+ {[]byte{0xa0, 0x82, 0x00, 0x01}, false, tagAndLength{}},
+ // Lengths up to the maximum size of an int should work.
+ {[]byte{0xa0, 0x84, 0x7f, 0xff, 0xff, 0xff}, true, tagAndLength{2, 0, 0x7fffffff, true}},
+ // Lengths that would overflow an int should be rejected.
+ {[]byte{0xa0, 0x84, 0x80, 0x00, 0x00, 0x00}, false, tagAndLength{}},
}
func TestParseTagAndLength(t *testing.T) {
diff --git a/src/pkg/encoding/base64/base64.go b/src/pkg/encoding/base64/base64.go
index 55f9f67a4..f8a51a4e7 100644
--- a/src/pkg/encoding/base64/base64.go
+++ b/src/pkg/encoding/base64/base64.go
@@ -230,7 +230,12 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
if in == '=' && j >= 2 && len(src) < 4 {
// We've reached the end and there's
// padding
+ if len(src) == 0 && j == 2 {
+ // not enough padding
+ return n, false, CorruptInputError(len(osrc))
+ }
if len(src) > 0 && src[0] != '=' {
+ // incorrect padding
return n, false, CorruptInputError(len(osrc) - len(src) - 1)
}
dlen = j
diff --git a/src/pkg/encoding/base64/base64_test.go b/src/pkg/encoding/base64/base64_test.go
index 3e9a84393..9c3537259 100644
--- a/src/pkg/encoding/base64/base64_test.go
+++ b/src/pkg/encoding/base64/base64_test.go
@@ -151,6 +151,9 @@ func TestDecodeCorrupt(t *testing.T) {
{"AAA=AAAA", 3},
{"AAAAA", 4},
{"AAAAAA", 4},
+ {"A=", 1},
+ {"AA=", 3},
+ {"AAAAAA=", 7},
}
for _, e := range examples {
diff --git a/src/pkg/encoding/json/encode.go b/src/pkg/encoding/json/encode.go
index 14957b848..842672c39 100644
--- a/src/pkg/encoding/json/encode.go
+++ b/src/pkg/encoding/json/encode.go
@@ -17,6 +17,7 @@ import (
"runtime"
"sort"
"strconv"
+ "strings"
"sync"
"unicode"
"unicode/utf8"
@@ -415,9 +416,11 @@ func isValidTag(s string) bool {
return false
}
for _, c := range s {
- switch c {
- case '$', '-', '_', '/', '%':
- // Acceptable
+ switch {
+ case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~", c):
+ // Backslash and quote chars are reserved, but
+ // otherwise any punctuation chars are allowed
+ // in a tag name.
default:
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
return false
diff --git a/src/pkg/encoding/json/tagkey_test.go b/src/pkg/encoding/json/tagkey_test.go
index bba573035..da8b12bd8 100644
--- a/src/pkg/encoding/json/tagkey_test.go
+++ b/src/pkg/encoding/json/tagkey_test.go
@@ -40,6 +40,10 @@ type percentSlashTag struct {
V string `json:"text/html%"` // http://golang.org/issue/2718
}
+type punctuationTag struct {
+ V string `json:"!#$%&()*+-./:<=>?@[]^_{|}~"` // http://golang.org/issue/3546
+}
+
type emptyTag struct {
W string
}
@@ -73,6 +77,7 @@ var structTagObjectKeyTests = []struct {
{badFormatTag{"Orfevre"}, "Orfevre", "Y"},
{badCodeTag{"Reliable Man"}, "Reliable Man", "Z"},
{percentSlashTag{"brut"}, "brut", "text/html%"},
+ {punctuationTag{"Union Rags"}, "Union Rags", "!#$%&()*+-./:<=>?@[]^_{|}~"},
}
func TestStructTagObjectKey(t *testing.T) {
diff --git a/src/pkg/encoding/pem/pem.go b/src/pkg/encoding/pem/pem.go
index 38afbb42a..3c1f5ab70 100644
--- a/src/pkg/encoding/pem/pem.go
+++ b/src/pkg/encoding/pem/pem.go
@@ -28,9 +28,10 @@ type Block struct {
}
// getLine results the first \r\n or \n delineated line from the given byte
-// array. The line does not include the \r\n or \n. The remainder of the byte
-// array (also not including the new line bytes) is also returned and this will
-// always be smaller than the original argument.
+// array. The line does not include trailing whitespace or the trailing new
+// line bytes. The remainder of the byte array (also not including the new line
+// bytes) is also returned and this will always be smaller than the original
+// argument.
func getLine(data []byte) (line, rest []byte) {
i := bytes.Index(data, []byte{'\n'})
var j int
@@ -43,7 +44,7 @@ func getLine(data []byte) (line, rest []byte) {
i--
}
}
- return data[0:i], data[j:]
+ return bytes.TrimRight(data[0:i], " \t"), data[j:]
}
// removeWhitespace returns a copy of its input with all spaces, tab and
diff --git a/src/pkg/encoding/pem/pem_test.go b/src/pkg/encoding/pem/pem_test.go
index 9ae1578a5..613353483 100644
--- a/src/pkg/encoding/pem/pem_test.go
+++ b/src/pkg/encoding/pem/pem_test.go
@@ -127,13 +127,13 @@ Certificate chain
-----BEGIN CERTIFICATE-----
testing
-----BEGIN CERTIFICATE-----
------BEGIN CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
MIID6TCCA1ICAQEwDQYJKoZIhvcNAQEFBQAwgYsxCzAJBgNVBAYTAlVTMRMwEQYD
VQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQK
-EwtHb29nbGUgSW5jLjEMMAoGA1UECxMDRW5nMQwwCgYDVQQDEwNhZ2wxHTAbBgkq
-hkiG9w0BCQEWDmFnbEBnb29nbGUuY29tMB4XDTA5MDkwOTIyMDU0M1oXDTEwMDkw
-OTIyMDU0M1owajELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAf
-BgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEjMCEGA1UEAxMaZXVyb3Bh
+EwtHb29nbGUgSW5jLjEMMAoGA1UECxMDRW5nMQwwCgYDVQQDEwNhZ2wxHTAbBgkq
+hkiG9w0BCQEWDmFnbEBnb29nbGUuY29tMB4XDTA5MDkwOTIyMDU0M1oXDTEwMDkw
+OTIyMDU0M1owajELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAf
+BgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEjMCEGA1UEAxMaZXVyb3Bh
LnNmby5jb3JwLmdvb2dsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQC6pgYt7/EibBDumASF+S0qvqdL/f+nouJw2T1Qc8GmXF/iiUcrsgzh/Fd8
pDhz/T96Qg9IyR4ztuc2MXrmPra+zAuSf5bevFReSqvpIt8Duv0HbDbcqs/XKPfB
@@ -149,15 +149,15 @@ Pomjn71GNTtDeWAXibjCgdL6iHACCF6Htbl0zGlG0OAK+bdn0QIDAQABMA0GCSqG
SIb3DQEBBQUAA4GBAOKnQDtqBV24vVqvesL5dnmyFpFPXBn3WdFfwD6DzEb21UVG
5krmJiu+ViipORJPGMkgoL6BjU21XI95VQbun5P8vvg8Z+FnFsvRFY3e1CCzAVQY
ZsUkLw2I7zI/dNlWdB8Xp7v+3w9sX5N3J/WuJ1KOO5m26kRlHQo7EzT3974g
------END CERTIFICATE-----
+-----END CERTIFICATE-----
1 s:/C=ZA/O=Ca Inc./CN=CA Inc
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,80C7C7A09690757A
-
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,80C7C7A09690757A
+
eQp5ZkH6CyHBz7BZfUPxyLCCmftsBJ7HlqGb8Ld21cSwnzWZ4/SIlhyrUtsfw7VR
-2TTwA+odo9ex7GdxOTaH8oZFumIRoiEjHsk8U7Bhntp+ekkPP79xunnN7hb7hkhr
+2TTwA+odo9ex7GdxOTaH8oZFumIRoiEjHsk8U7Bhntp+ekkPP79xunnN7hb7hkhr
yGDQZgA7s2cQHQ71v3gwT2BACAft26jCjbM1wgNzBnJ8M0Rzn68YWqaPtdBu8qb/
zVR5JB1mnqvTSbFsfF5yMc6o2WQ9jJCl6KypnMl+BpL+dlvdjYVK4l9lYsB1Hs3d
+zDBbWxos818zzhS8/y6eIfiSG27cqrbhURbmgiSfDXjncK4m/pLcQ7mmBL6mFOr
diff --git a/src/pkg/flag/flag.go b/src/pkg/flag/flag.go
index c28d0e720..f0842a18a 100644
--- a/src/pkg/flag/flag.go
+++ b/src/pkg/flag/flag.go
@@ -7,9 +7,11 @@
Usage:
- Define flags using flag.String(), Bool(), Int(), etc. Example:
+ Define flags using flag.String(), Bool(), Int(), etc.
+
+ This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
import "flag"
- var ip *int = flag.Int("flagname", 1234, "help message for flagname")
+ var ip = flag.Int("flagname", 1234, "help message for flagname")
If you like, you can bind the flag to a variable using the Var() functions.
var flagvar int
func init() {
@@ -26,8 +28,8 @@
Flags may then be used directly. If you're using the flags themselves,
they are all pointers; if you bind to variables, they're values.
- fmt.Println("ip has value ", *ip);
- fmt.Println("flagvar has value ", flagvar);
+ fmt.Println("ip has value ", *ip)
+ fmt.Println("flagvar has value ", flagvar)
After parsing, the arguments after the flag are available as the
slice flag.Args() or individually as flag.Arg(i).
diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go
index 758fc50d0..de0342967 100644
--- a/src/pkg/fmt/fmt_test.go
+++ b/src/pkg/fmt/fmt_test.go
@@ -461,6 +461,9 @@ var fmttests = []struct {
// zero reflect.Value, which formats as <nil>.
// This test is just to check that it shows the two NaNs at all.
{"%v", map[float64]int{math.NaN(): 1, math.NaN(): 2}, "map[NaN:<nil> NaN:<nil>]"},
+
+ // Used to crash because nByte didn't allow for a sign.
+ {"%b", int64(-1 << 63), "-1000000000000000000000000000000000000000000000000000000000000000"},
}
func TestSprintf(t *testing.T) {
diff --git a/src/pkg/fmt/format.go b/src/pkg/fmt/format.go
index 2186f334b..caf900d5c 100644
--- a/src/pkg/fmt/format.go
+++ b/src/pkg/fmt/format.go
@@ -10,7 +10,7 @@ import (
)
const (
- nByte = 64
+ nByte = 65 // %b of an int64, plus a sign.
ldigits = "0123456789abcdef"
udigits = "0123456789ABCDEF"
diff --git a/src/pkg/html/escape.go b/src/pkg/html/escape.go
index fee771a57..24cb7af85 100644
--- a/src/pkg/html/escape.go
+++ b/src/pkg/html/escape.go
@@ -210,13 +210,15 @@ func escape(w writer, s string) error {
case '&':
esc = "&amp;"
case '\'':
- esc = "&apos;"
+ // "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
+ esc = "&#39;"
case '<':
esc = "&lt;"
case '>':
esc = "&gt;"
case '"':
- esc = "&quot;"
+ // "&#34;" is shorter than "&quot;".
+ esc = "&#34;"
default:
panic("unrecognized escape character")
}
@@ -231,7 +233,7 @@ func escape(w writer, s string) error {
}
// EscapeString escapes special characters like "<" to become "&lt;". It
-// escapes only five such characters: amp, apos, lt, gt and quot.
+// escapes only five such characters: <, >, &, ' and ".
// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
// always true.
func EscapeString(s string) string {
diff --git a/src/pkg/mime/mediatype.go b/src/pkg/mime/mediatype.go
index 9398dece1..8396c0a15 100644
--- a/src/pkg/mime/mediatype.go
+++ b/src/pkg/mime/mediatype.go
@@ -99,7 +99,7 @@ func ParseMediaType(v string) (mediatype string, params map[string]string, err e
err = checkMediaTypeDisposition(mediatype)
if err != nil {
- return
+ return "", nil, err
}
params = make(map[string]string)
diff --git a/src/pkg/mime/mediatype_test.go b/src/pkg/mime/mediatype_test.go
index 64ab29134..e41ead237 100644
--- a/src/pkg/mime/mediatype_test.go
+++ b/src/pkg/mime/mediatype_test.go
@@ -244,13 +244,33 @@ func TestParseMediaType(t *testing.T) {
}
}
+type badMediaTypeTest struct {
+ in string
+ err string
+}
+
+var badMediaTypeTests = []badMediaTypeTest{
+ {"bogus ;=========", "mime: invalid media parameter"},
+ {"bogus/<script>alert</script>", "mime: expected token after slash"},
+ {"bogus/bogus<script>alert</script>", "mime: unexpected content after media subtype"},
+}
+
func TestParseMediaTypeBogus(t *testing.T) {
- mt, params, err := ParseMediaType("bogus ;=========")
- if err == nil {
- t.Fatalf("expected an error parsing invalid media type; got type %q, params %#v", mt, params)
- }
- if err.Error() != "mime: invalid media parameter" {
- t.Errorf("expected invalid media parameter; got error %q", err)
+ for _, tt := range badMediaTypeTests {
+ mt, params, err := ParseMediaType(tt.in)
+ if err == nil {
+ t.Errorf("ParseMediaType(%q) = nil error; want parse error", tt.in)
+ continue
+ }
+ if err.Error() != tt.err {
+ t.Errorf("ParseMediaType(%q) = err %q; want %q", tt.in, err.Error(), tt.err)
+ }
+ if params != nil {
+ t.Errorf("ParseMediaType(%q): got non-nil params on error", tt.in)
+ }
+ if mt != "" {
+ t.Errorf("ParseMediaType(%q): got non-empty media type string on error", tt.in)
+ }
}
}
diff --git a/src/pkg/mime/multipart/multipart.go b/src/pkg/mime/multipart/multipart.go
index d733130ab..6ace4be56 100644
--- a/src/pkg/mime/multipart/multipart.go
+++ b/src/pkg/mime/multipart/multipart.go
@@ -185,6 +185,14 @@ func (r *Reader) NextPart() (*Part, error) {
expectNewPart := false
for {
line, err := r.bufReader.ReadSlice('\n')
+ if err == io.EOF && bytes.Equal(line, r.dashBoundaryDash) {
+ // If the buffer ends in "--boundary--" without the
+ // trailing "\r\n", ReadSlice will return an error
+ // (since it's missing the '\n'), but this is a valid
+ // multipart EOF so we need to return io.EOF instead of
+ // a fmt-wrapped one.
+ return nil, io.EOF
+ }
if err != nil {
return nil, fmt.Errorf("multipart: NextPart: %v", err)
}
diff --git a/src/pkg/mime/multipart/multipart_test.go b/src/pkg/mime/multipart/multipart_test.go
index 89ff5e489..ca7108d7a 100644
--- a/src/pkg/mime/multipart/multipart_test.go
+++ b/src/pkg/mime/multipart/multipart_test.go
@@ -10,6 +10,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "os"
"strings"
"testing"
)
@@ -377,3 +378,52 @@ func TestLineContinuation(t *testing.T) {
}
}
}
+
+// Test parsing an image attachment from gmail, which previously failed.
+func TestNested(t *testing.T) {
+ // nested-mime is the body part of a multipart/mixed email
+ // with boundary e89a8ff1c1e83553e304be640612
+ f, err := os.Open("testdata/nested-mime")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ mr := NewReader(f, "e89a8ff1c1e83553e304be640612")
+ p, err := mr.NextPart()
+ if err != nil {
+ t.Fatalf("error reading first section (alternative): %v", err)
+ }
+
+ // Read the inner text/plain and text/html sections of the multipart/alternative.
+ mr2 := NewReader(p, "e89a8ff1c1e83553e004be640610")
+ p, err = mr2.NextPart()
+ if err != nil {
+ t.Fatalf("reading text/plain part: %v", err)
+ }
+ if b, err := ioutil.ReadAll(p); string(b) != "*body*\r\n" || err != nil {
+ t.Fatalf("reading text/plain part: got %q, %v", b, err)
+ }
+ p, err = mr2.NextPart()
+ if err != nil {
+ t.Fatalf("reading text/html part: %v", err)
+ }
+ if b, err := ioutil.ReadAll(p); string(b) != "<b>body</b>\r\n" || err != nil {
+ t.Fatalf("reading text/html part: got %q, %v", b, err)
+ }
+
+ p, err = mr2.NextPart()
+ if err != io.EOF {
+ t.Fatalf("final inner NextPart = %v; want io.EOF", err)
+ }
+
+ // Back to the outer multipart/mixed, reading the image attachment.
+ _, err = mr.NextPart()
+ if err != nil {
+ t.Fatalf("error reading the image attachment at the end: %v", err)
+ }
+
+ _, err = mr.NextPart()
+ if err != io.EOF {
+ t.Fatalf("final outer NextPart = %v; want io.EOF", err)
+ }
+}
diff --git a/src/pkg/mime/multipart/testdata/nested-mime b/src/pkg/mime/multipart/testdata/nested-mime
new file mode 100755
index 000000000..71c238e38
--- /dev/null
+++ b/src/pkg/mime/multipart/testdata/nested-mime
@@ -0,0 +1,29 @@
+--e89a8ff1c1e83553e304be640612
+Content-Type: multipart/alternative; boundary=e89a8ff1c1e83553e004be640610
+
+--e89a8ff1c1e83553e004be640610
+Content-Type: text/plain; charset=UTF-8
+
+*body*
+
+--e89a8ff1c1e83553e004be640610
+Content-Type: text/html; charset=UTF-8
+
+<b>body</b>
+
+--e89a8ff1c1e83553e004be640610--
+--e89a8ff1c1e83553e304be640612
+Content-Type: image/png; name="x.png"
+Content-Disposition: attachment;
+ filename="x.png"
+Content-Transfer-Encoding: base64
+X-Attachment-Id: f_h1edgigu0
+
+iVBORw0KGgoAAAANSUhEUgAAAagAAADrCAIAAACza5XhAAAKMWlDQ1BJQ0MgUHJvZmlsZQAASImd
+lndUU9kWh8+9N71QkhCKlNBraFICSA29SJEuKjEJEErAkAAiNkRUcERRkaYIMijggKNDkbEiioUB
+8b2kqeGaj4aTNftesu5mob4pr07ecMywRwLBvDCJOksqlUyldAZD7g9fxIZRWWPMvXRNJROJRBIG
+Y7Vx0mva1HAwYqibdKONXye3dW4iUonhWFJnqK7OaanU1gGkErFYEgaj0cg8wK+zVPh2ziwnHy07
+U8lYTNapezSzOuevRwLB7CFkqQQCwaJDiBQIBIJFhwh8AoFg0SHUqQUCASRJKkwkhMy/JfODWPEJ
+BIJFhwh8AoFg0TFnQqQ55GtPFopcJsN97e1nYtNuIBYeGBgYCmYrmE3jZ05iaGAoMX0xzxkWz6Hv
+yO7WvrlwzA0uLzrD+VkKqViwl9IfTBVNFMyc/x9alloiPPlqhQAAAABJRU5ErkJggg==
+--e89a8ff1c1e83553e304be640612--
diff --git a/src/pkg/net/http/example_test.go b/src/pkg/net/http/example_test.go
index 2584afc43..ec814407d 100644
--- a/src/pkg/net/http/example_test.go
+++ b/src/pkg/net/http/example_test.go
@@ -49,3 +49,8 @@ func ExampleGet() {
res.Body.Close()
fmt.Printf("%s", robots)
}
+
+func ExampleFileServer() {
+ // we use StripPrefix so that /tmpfiles/somefile will access /tmp/somefile
+ http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
+}
diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go
index 228ac4019..924ffd348 100644
--- a/src/pkg/net/http/server.go
+++ b/src/pkg/net/http/server.go
@@ -785,8 +785,10 @@ var htmlReplacer = strings.NewReplacer(
"&", "&amp;",
"<", "&lt;",
">", "&gt;",
- `"`, "&quot;",
- "'", "&apos;",
+ // "&#34;" is shorter than "&quot;".
+ `"`, "&#34;",
+ // "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
+ "'", "&#39;",
)
func htmlEscape(s string) string {
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go
index 6bbe67c3d..9fc7ecdb9 100644
--- a/src/pkg/net/iprawsock_posix.go
+++ b/src/pkg/net/iprawsock_posix.go
@@ -83,9 +83,7 @@ func (c *IPConn) Close() error {
if !c.ok() {
return syscall.EINVAL
}
- err := c.fd.Close()
- c.fd = nil
- return err
+ return c.fd.Close()
}
// LocalAddr returns the local network address.
diff --git a/src/pkg/net/tcpsock_posix.go b/src/pkg/net/tcpsock_posix.go
index 15f8efdd7..e6b1937fb 100644
--- a/src/pkg/net/tcpsock_posix.go
+++ b/src/pkg/net/tcpsock_posix.go
@@ -108,9 +108,7 @@ func (c *TCPConn) Close() error {
if !c.ok() {
return syscall.EINVAL
}
- err := c.fd.Close()
- c.fd = nil
- return err
+ return c.fd.Close()
}
// CloseRead shuts down the reading side of the TCP connection.
@@ -359,5 +357,5 @@ func (l *TCPListener) SetDeadline(t time.Time) error {
// File returns a copy of the underlying os.File, set to blocking mode.
// It is the caller's responsibility to close f when finished.
-// Closing c does not affect f, and closing f does not affect c.
+// Closing l does not affect f, and closing f does not affect l.
func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
diff --git a/src/pkg/net/udpsock_posix.go b/src/pkg/net/udpsock_posix.go
index 9e820e1c5..9c6b6d393 100644
--- a/src/pkg/net/udpsock_posix.go
+++ b/src/pkg/net/udpsock_posix.go
@@ -88,9 +88,7 @@ func (c *UDPConn) Close() error {
if !c.ok() {
return syscall.EINVAL
}
- err := c.fd.Close()
- c.fd = nil
- return err
+ return c.fd.Close()
}
// LocalAddr returns the local network address.
diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go
index 37a2b1e09..57d784c71 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/pkg/net/unixsock_posix.go
@@ -141,9 +141,7 @@ func (c *UnixConn) Close() error {
if !c.ok() {
return syscall.EINVAL
}
- err := c.fd.Close()
- c.fd = nil
- return err
+ return c.fd.Close()
}
// LocalAddr returns the local network address, a *UnixAddr.
@@ -406,7 +404,7 @@ func (l *UnixListener) SetDeadline(t time.Time) (err error) {
// File returns a copy of the underlying os.File, set to blocking mode.
// It is the caller's responsibility to close f when finished.
-// Closing c does not affect f, and closing f does not affect c.
+// Closing l does not affect f, and closing f does not affect l.
func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() }
// ListenUnixgram listens for incoming Unix datagram packets addressed to the
diff --git a/src/pkg/net/url/url.go b/src/pkg/net/url/url.go
index 88ff7ebfe..b6e79adc2 100644
--- a/src/pkg/net/url/url.go
+++ b/src/pkg/net/url/url.go
@@ -61,16 +61,16 @@ func (e EscapeError) Error() string {
}
// Return true if the specified character should be escaped when
-// appearing in a URL string, according to RFC 2396.
+// appearing in a URL string, according to RFC 3986.
// When 'all' is true the full range of reserved characters are matched.
func shouldEscape(c byte, mode encoding) bool {
- // RFC 2396 §2.3 Unreserved characters (alphanum)
+ // §2.3 Unreserved characters (alphanum)
if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' {
return false
}
- // TODO: Update the character sets after RFC 3986.
+
switch c {
- case '-', '_', '.', '!', '~', '*', '\'', '(', ')': // §2.3 Unreserved characters (mark)
+ case '-', '_', '.', '~': // §2.3 Unreserved characters (mark)
return false
case '$', '&', '+', ',', '/', ':', ';', '=', '?', '@': // §2.2 Reserved characters (reserved)
diff --git a/src/pkg/net/url/url_test.go b/src/pkg/net/url/url_test.go
index 2d911ed50..d8b253142 100644
--- a/src/pkg/net/url/url_test.go
+++ b/src/pkg/net/url/url_test.go
@@ -394,8 +394,8 @@ var escapeTests = []EscapeTest{
nil,
},
{
- " ?&=#+%!<>#\"{}|\\^[]`☺\t",
- "+%3F%26%3D%23%2B%25!%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09",
+ " ?&=#+%!<>#\"{}|\\^[]`☺\t:/@$'()*,;",
+ "+%3F%26%3D%23%2B%25%21%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09%3A%2F%40%24%27%28%29%2A%2C%3B",
nil,
},
}
diff --git a/src/pkg/os/error_windows.go b/src/pkg/os/error_windows.go
index 5d692b073..fbb0d4f3f 100644
--- a/src/pkg/os/error_windows.go
+++ b/src/pkg/os/error_windows.go
@@ -26,5 +26,5 @@ func isPermission(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}
- return err == ErrPermission
+ return err == syscall.ERROR_ACCESS_DENIED || err == ErrPermission
}
diff --git a/src/pkg/path/filepath/path.go b/src/pkg/path/filepath/path.go
index 1e7487263..a4e429bae 100644
--- a/src/pkg/path/filepath/path.go
+++ b/src/pkg/path/filepath/path.go
@@ -30,6 +30,9 @@ const (
// that is, replace "/.." by "/" at the beginning of a path,
// assuming Separator is '/'.
//
+// The returned path ends in a slash only if it represents a root directory,
+// such as "/" on Unix or `C:\` on Windows.
+//
// If the result of this process is an empty string, Clean
// returns the string ".".
//
diff --git a/src/pkg/path/path.go b/src/pkg/path/path.go
index 13abed0b0..a7e041568 100644
--- a/src/pkg/path/path.go
+++ b/src/pkg/path/path.go
@@ -21,6 +21,8 @@ import (
// 4. Eliminate .. elements that begin a rooted path:
// that is, replace "/.." by "/" at the beginning of a path.
//
+// The returned path ends in a slash only if it is the root "/".
+//
// If the result of this process is an empty string, Clean
// returns the string ".".
//
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
index 6bb061398..e33140563 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/pkg/reflect/all_test.go
@@ -638,6 +638,7 @@ var (
var deepEqualTests = []DeepEqualTest{
// Equalities
+ {nil, nil, true},
{1, 1, true},
{int32(1), int32(1), true},
{0.5, 0.5, true},
@@ -696,6 +697,10 @@ func TestDeepEqual(t *testing.T) {
}
func TestTypeOf(t *testing.T) {
+ // Special case for nil
+ if typ := TypeOf(nil); typ != nil {
+ t.Errorf("expected nil type for nil value; got %v", typ)
+ }
for _, test := range deepEqualTests {
v := ValueOf(test.a)
if !v.IsValid() {
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
index 64550b8f6..060bde3af 100644
--- a/src/pkg/reflect/type.go
+++ b/src/pkg/reflect/type.go
@@ -940,6 +940,7 @@ func toType(p *runtimeType) Type {
}
// TypeOf returns the reflection Type of the value in the interface{}.
+// TypeOf(nil) returns nil.
func TypeOf(i interface{}) Type {
eface := *(*emptyInterface)(unsafe.Pointer(&i))
return toType(eface.typ)
diff --git a/src/pkg/runtime/extern.go b/src/pkg/runtime/extern.go
index 5fbfe547e..f9c5b8e3d 100644
--- a/src/pkg/runtime/extern.go
+++ b/src/pkg/runtime/extern.go
@@ -20,7 +20,8 @@ func Goexit()
// Caller reports file and line number information about function invocations on
// the calling goroutine's stack. The argument skip is the number of stack frames
-// to ascend, with 0 identifying the caller of Caller. The return values report the
+// to ascend, with 1 identifying the caller of Caller. (For historical reasons the
+// meaning of skip differs between Caller and Callers.) The return values report the
// program counter, file name, and line number within the file of the corresponding
// call. The boolean ok is false if it was not possible to recover the information.
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
diff --git a/src/pkg/text/template/exec.go b/src/pkg/text/template/exec.go
index 9a720cf43..feb434a3b 100644
--- a/src/pkg/text/template/exec.go
+++ b/src/pkg/text/template/exec.go
@@ -491,7 +491,11 @@ func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node,
}
// Add final value if necessary.
if final.IsValid() {
- argv[i] = final
+ t := typ.In(typ.NumIn() - 1)
+ if typ.IsVariadic() {
+ t = t.Elem()
+ }
+ argv[i] = s.validateType(final, t)
}
result := fun.Call(argv)
// If we have an error that is not nil, stop execution and return that error to the caller.
@@ -507,6 +511,7 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
switch typ.Kind() {
case reflect.Interface, reflect.Ptr, reflect.Chan, reflect.Map, reflect.Slice, reflect.Func:
// An untyped nil interface{}. Accept as a proper nil value.
+ // TODO: Can we delete the other types in this list? Should we?
value = reflect.Zero(typ)
default:
s.errorf("invalid value; expected %s", typ)
diff --git a/src/pkg/text/template/exec_test.go b/src/pkg/text/template/exec_test.go
index 5446027ff..37d25f470 100644
--- a/src/pkg/text/template/exec_test.go
+++ b/src/pkg/text/template/exec_test.go
@@ -470,6 +470,9 @@ var execTests = []execTest{
{"bug7a", "{{3 2}}", "", tVal, false},
{"bug7b", "{{$x := 1}}{{$x 2}}", "", tVal, false},
{"bug7c", "{{$x := 1}}{{3 | $x}}", "", tVal, false},
+ // Pipelined arg was not being type-checked.
+ {"bug8a", "{{3|oneArg}}", "", tVal, false},
+ {"bug8b", "{{4|dddArg 3}}", "", tVal, false},
}
func zeroArgs() string {
@@ -480,6 +483,10 @@ func oneArg(a string) string {
return "oneArg=" + a
}
+func dddArg(a int, b ...string) string {
+ return fmt.Sprintln(a, b)
+}
+
// count returns a channel that will deliver n sequential 1-letter strings starting at "a"
func count(n int) chan string {
if n == 0 {
@@ -504,6 +511,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) {
b := new(bytes.Buffer)
funcs := FuncMap{
"count": count,
+ "dddArg": dddArg,
"oneArg": oneArg,
"typeOf": typeOf,
"vfunc": vfunc,
diff --git a/src/pkg/text/template/funcs.go b/src/pkg/text/template/funcs.go
index 525179cb4..8fbf0ef50 100644
--- a/src/pkg/text/template/funcs.go
+++ b/src/pkg/text/template/funcs.go
@@ -246,7 +246,7 @@ func not(arg interface{}) (truth bool) {
var (
htmlQuot = []byte("&#34;") // shorter than "&quot;"
- htmlApos = []byte("&#39;") // shorter than "&apos;"
+ htmlApos = []byte("&#39;") // shorter than "&apos;" and apos was not in HTML until HTML5
htmlAmp = []byte("&amp;")
htmlLt = []byte("&lt;")
htmlGt = []byte("&gt;")
diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go
index ad52bab21..efca3a926 100644
--- a/src/pkg/time/format.go
+++ b/src/pkg/time/format.go
@@ -41,8 +41,8 @@ const (
ANSIC = "Mon Jan _2 15:04:05 2006"
UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
- RFC822 = "02 Jan 06 1504 MST"
- RFC822Z = "02 Jan 06 1504 -0700" // RFC822 with numeric zone
+ RFC822 = "02 Jan 06 15:04 MST"
+ RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
@@ -714,7 +714,7 @@ func Parse(layout, value string) (Time, error) {
}
// Special case: do we have a fractional second but no
// fractional second in the format?
- if len(value) > 2 && value[0] == '.' && isDigit(value, 1) {
+ if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
_, std, _ := nextStdChunk(layout)
if len(std) > 0 && std[0] == '.' && isDigit(std, 1) {
// Fractional second in the layout; proceed normally
diff --git a/src/pkg/time/time.go b/src/pkg/time/time.go
index 473bc2a45..2461dac06 100644
--- a/src/pkg/time/time.go
+++ b/src/pkg/time/time.go
@@ -403,7 +403,7 @@ const (
Hour = 60 * Minute
)
-// Duration returns a string representing the duration in the form "72h3m0.5s".
+// String returns a string representing the duration in the form "72h3m0.5s".
// Leading zero units are omitted. As a special case, durations less than one
// second format use a smaller unit (milli-, micro-, or nanoseconds) to ensure
// that the leading digit is non-zero. The zero duration formats as 0,
@@ -763,7 +763,9 @@ func (t Time) Unix() int64 {
}
// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
-// since January 1, 1970 UTC.
+// since January 1, 1970 UTC. The result is undefined if the Unix time
+// in nanoseconds cannot be represented by an int64. Note that this
+// means the result of calling UnixNano on the zero Time is undefined.
func (t Time) UnixNano() int64 {
return (t.sec+internalToUnix)*1e9 + int64(t.nsec)
}
diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go
index 3430526b8..28047804e 100644
--- a/src/pkg/time/time_test.go
+++ b/src/pkg/time/time_test.go
@@ -223,7 +223,7 @@ var formatTests = []FormatTest{
{"ANSIC", ANSIC, "Wed Feb 4 21:00:57 2009"},
{"UnixDate", UnixDate, "Wed Feb 4 21:00:57 PST 2009"},
{"RubyDate", RubyDate, "Wed Feb 04 21:00:57 -0800 2009"},
- {"RFC822", RFC822, "04 Feb 09 2100 PST"},
+ {"RFC822", RFC822, "04 Feb 09 21:00 PST"},
{"RFC850", RFC850, "Wednesday, 04-Feb-09 21:00:57 PST"},
{"RFC1123", RFC1123, "Wed, 04 Feb 2009 21:00:57 PST"},
{"RFC1123Z", RFC1123Z, "Wed, 04 Feb 2009 21:00:57 -0800"},
@@ -310,6 +310,7 @@ var parseTests = []ParseTest{
{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57.01234 PST", true, true, 1, 5},
{"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57.01234 -0800", true, true, 1, 5},
{"RFC3339", RFC3339, "2010-02-04T21:00:57.012345678-08:00", true, false, 1, 9},
+ {"custom: \"2006-01-02 15:04:05\"", "2006-01-02 15:04:05", "2010-02-04 21:00:57.0", false, false, 1, 0},
// Amount of white space should not matter.
{"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
{"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
diff --git a/src/pkg/time/zoneinfo_windows.go b/src/pkg/time/zoneinfo_windows.go
index 754e392de..d596fab93 100644
--- a/src/pkg/time/zoneinfo_windows.go
+++ b/src/pkg/time/zoneinfo_windows.go
@@ -83,6 +83,9 @@ func initLocalFromTZI(i *syscall.Timezoneinformation) {
l.cacheStart = -1 << 63
l.cacheEnd = 1<<63 - 1
l.cacheZone = std
+ l.tx = make([]zoneTrans, 1)
+ l.tx[0].when = l.cacheStart
+ l.tx[0].index = 0
return
}
diff --git a/src/sudo.bash b/src/sudo.bash
index cccebd342..40f8d1aa1 100755
--- a/src/sudo.bash
+++ b/src/sudo.bash
@@ -12,12 +12,17 @@ Darwin)
exit 0
esac
+eval $(go env)
+if ! [ -x $GOTOOLDIR/cov -a -x $GOTOOLDIR/prof ]; then
+ echo "You don't need to run sudo.bash." >&2
+ exit 2
+fi
+
if [[ ! -d /usr/local/bin ]]; then
echo 1>&2 'sudo.bash: problem with /usr/local/bin; cannot install tools.'
exit 2
fi
-eval $(go env)
cd $(dirname $0)
for i in prof cov
do
diff --git a/test/escape2.go b/test/escape2.go
index 624ea80b5..0bf02c534 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -1051,7 +1051,7 @@ func foo122() {
goto L1
L1:
- i = new(int) // ERROR "does not escape"
+ i = new(int) // ERROR "new.int. does not escape"
_ = i
}
@@ -1060,8 +1060,141 @@ func foo123() {
var i *int
L1:
- i = new(int) // ERROR "escapes"
+ i = new(int) // ERROR "new.int. escapes to heap"
goto L1
_ = i
}
+
+func foo124(x **int) { // ERROR "x does not escape"
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes"
+ func() { // ERROR "func literal does not escape"
+ *x = p // ERROR "leaking closure reference p"
+ }()
+}
+
+func foo125(ch chan *int) { // ERROR "does not escape"
+ var i int // ERROR "moved to heap"
+ p := &i // ERROR "&i escapes to heap"
+ func() { // ERROR "func literal does not escape"
+ ch <- p // ERROR "leaking closure reference p"
+ }()
+}
+
+func foo126() {
+ var px *int // loopdepth 0
+ for {
+ // loopdepth 1
+ var i int // ERROR "moved to heap"
+ func() { // ERROR "func literal does not escape"
+ px = &i // ERROR "&i escapes"
+ }()
+ }
+}
+
+var px *int
+
+func foo127() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap"
+ q := p
+ px = q
+}
+
+func foo128() {
+ var i int
+ p := &i // ERROR "&i does not escape"
+ q := p
+ _ = q
+}
+
+func foo129() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap"
+ func() { // ERROR "func literal does not escape"
+ q := p // ERROR "leaking closure reference p"
+ func() { // ERROR "func literal does not escape"
+ r := q // ERROR "leaking closure reference q"
+ px = r
+ }()
+ }()
+}
+
+func foo130() {
+ for {
+ var i int // ERROR "moved to heap"
+ func() { // ERROR "func literal does not escape"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
+ }()
+ }
+}
+
+func foo131() {
+ var i int // ERROR "moved to heap"
+ func() { // ERROR "func literal does not escape"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
+ }()
+}
+
+func foo132() {
+ var i int // ERROR "moved to heap"
+ go func() { // ERROR "func literal escapes to heap"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
+ }()
+}
+
+func foo133() {
+ var i int // ERROR "moved to heap"
+ defer func() { // ERROR "func literal does not escape"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
+ }()
+}
+
+func foo134() {
+ var i int
+ p := &i // ERROR "&i does not escape"
+ func() { // ERROR "func literal does not escape"
+ q := p
+ func() { // ERROR "func literal does not escape"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo135() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ go func() { // ERROR "func literal escapes to heap"
+ q := p // ERROR "&p escapes to heap"
+ func() { // ERROR "func literal does not escape"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo136() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ go func() { // ERROR "func literal escapes to heap"
+ q := p // ERROR "&p escapes to heap" "leaking closure reference p"
+ func() { // ERROR "func literal does not escape"
+ r := q // ERROR "leaking closure reference q"
+ px = r
+ }()
+ }()
+}
+
+func foo137() {
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap"
+ func() { // ERROR "func literal does not escape"
+ q := p // ERROR "leaking closure reference p" "moved to heap: q"
+ go func() { // ERROR "func literal escapes to heap"
+ r := q // ERROR "&q escapes to heap"
+ _ = r
+ }()
+ }()
+}