Compare commits

...

43 Commits

Author SHA1 Message Date
Andrew Gerrand
2eb51b1ba8 go1.2rc3
R=golang-dev, nigeltao
CC=golang-dev
https://golang.org/cl/19560047
2013-11-01 12:44:30 +11:00
Andrew Gerrand
4708b76f84 [release-branch.go1.2] cmd/5l, runtime: fix divide for profiling tracebacks on ARM
««« CL 19910044 / 9eb64f5ef3a6
cmd/5l, runtime: fix divide for profiling tracebacks on ARM

Two bugs:
1. The first iteration of the traceback always uses LR when provided,
which it is (only) during a profiling signal, but in fact LR is correct
only if the stack frame has not been allocated yet. Otherwise an
intervening call may have changed LR, and the saved copy in the stack
frame should be used. Fix in traceback_arm.c.

2. The division runtime call adds 8 bytes to the stack. In order to
keep the traceback routines happy, it must copy the saved LR into
the new 0(SP). Change

        SUB $8, SP

into

        MOVW    0(SP), R11 // r11 is temporary, for use by linker
        MOVW.W  R11, -8(SP)

to update SP and 0(SP) atomically, so that the traceback always
sees a saved LR at 0(SP).

Fixes #6681.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/19910044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20170048
2013-11-01 11:34:40 +11:00
Andrew Gerrand
1d78c86897 [release-branch.go1.2] doc/go1.2.html: delete repeated word
««« CL 19840043 / 938b64b0f608
doc/go1.2.html: delete repeated word
TBR=rsc

R=golang-dev
CC=golang-dev
https://golang.org/cl/19840043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20240044
2013-11-01 11:33:51 +11:00
Andrew Gerrand
28c1081208 [release-branch.go1.2] doc/go1.2.html: stack sizes, thread limits
««« CL 19600043 / 746466b52725
doc/go1.2.html: stack sizes, thread limits

R=golang-dev, minux.ma, adg, rsc
CC=golang-dev
https://golang.org/cl/19600043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20110046
2013-11-01 11:33:03 +11:00
Andrew Gerrand
8648d26c5f [release-branch.go1.2] cmd/cgo: accept extra leading _ on __cgodebug_data for all object formats
««« CL 19780043 / 8b49cdda6ff4
cmd/cgo: accept extra leading _ on __cgodebug_data for all object formats

The current Windows build breakage appears to be because
the Windows code should be looking for __cgodebug_data
not ___cgodebug_data. Dodge the question everywhere by
accepting both.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/19780043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20660043
2013-11-01 11:32:10 +11:00
Andrew Gerrand
63ff715a55 [release-branch.go1.2] database/sql: document Result methods
««« CL 19280046 / 2ad8ac71220d
database/sql: document Result methods

Fixes #5110

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/19280046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20650043
2013-11-01 11:31:18 +11:00
Andrew Gerrand
6d10afd9e5 [release-branch.go1.2] database/sql: Fix typos in doc
««« CL 17590043 / fb5224487f1b
database/sql: Fix typos in doc

R=golang-dev
CC=bradfitz, golang-dev
https://golang.org/cl/17590043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20150046
2013-11-01 11:30:30 +11:00
Andrew Gerrand
89f0148955 [release-branch.go1.2] A+C: Jakob Borg (individual CLA).
««« CL 19510043 / ae106f792e5d
A+C: Jakob Borg (individual CLA).

R=golang-dev
CC=golang-dev
https://golang.org/cl/19510043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20570045
2013-11-01 11:29:41 +11:00
Andrew Gerrand
842a18c28f [release-branch.go1.2] time: correct path to time zone zip file on Unix
««« CL 19280043 / 9d199c7582d6
time: correct path to time zone zip file on Unix

Most Unix systems have their own time zone data,
so we almost never get far enough in the list to
discover that we cannot fall back to the zip file.
Adjust testing to exercise the final fallback.

Plan 9 and Windows were already correct
(and are the main users of the zip file).

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/19280043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20640043
2013-11-01 11:28:57 +11:00
Andrew Gerrand
6ab0f588a8 [release-branch.go1.2] encoding/xml: fix doc comment
««« CL 19300046 / 5ac568b9d67b
encoding/xml: fix doc comment

The tag is ",chardata" not "chardata".

Fixes #6631.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/19300046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20060045
2013-11-01 11:28:07 +11:00
Andrew Gerrand
71b3aca9fa [release-branch.go1.2] net/http/httputil: fix DumpRequestOut with ContentLength & false body param
««« CL 14920050 / 5ed8c82778ae
net/http/httputil: fix DumpRequestOut with ContentLength & false body param

Fixes #6471

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/14920050
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20590044
2013-11-01 11:27:19 +11:00
Andrew Gerrand
a4085fdf10 [release-branch.go1.2] os: do not return Lstat errors from Readdir
««« CL 18870043 / eca0ca43a863
os: do not return Lstat errors from Readdir

This CL restores the Go 1.1.2 semantics for os.File's Readdir method.

The code in Go 1.1.2 was rewritten mainly because it looked buggy.
This new version attempts to be clearer but still provide the 1.1.2 results.

The important diff is not this CL's version against tip but this CL's version
against Go 1.1.2.

Go 1.1.2:

        names, err := f.Readdirnames(n)
        fi = make([]FileInfo, len(names))
        for i, filename := range names {
                fip, err := Lstat(dirname + filename)
                if err == nil {
                        fi[i] = fip
                } else {
                        fi[i] = &fileStat{name: filename}
                }
        }
        return fi, err

This CL:

        names, err := f.Readdirnames(n)
        fi = make([]FileInfo, len(names))
        for i, filename := range names {
                fip, lerr := lstat(dirname + filename)
                if lerr != nil {
                        fi[i] = &fileStat{name: filename}
                        continue
                }
                fi[i] = fip
        }
        return fi, err

The changes from Go 1.1.2 are stylistic, not semantic:
1. Use lstat instead of Lstat, for testing (done before this CL).
2. Make error handling in loop body look more like an error case.
3. Use separate error variable name in loop body, to be clear
   we are not trying to influence the final return result.

Fixes #6656.
Fixes #6680.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/18870043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20110045
2013-11-01 11:26:31 +11:00
Andrew Gerrand
d4bc355c56 [release-branch.go1.2] cmd/gc: silence clang warning
««« CL 19160043 / 104d56b5d664
cmd/gc: silence clang warning

This code is only built when you run 'make' in cmd/gc,
not in all.bash.

R=golang-dev, jsing, iant
CC=golang-dev
https://golang.org/cl/19160043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20290046
2013-11-01 11:25:45 +11:00
Andrew Gerrand
2737f274f5 [release-branch.go1.2] misc/emacs: support godef-jump on import statements
««« CL 18230043 / f2b59b5163b0
misc/emacs: support godef-jump on import statements

The newest version of godef supports jumping to a package's source
directory if point is on an import statement.

R=adonovan
CC=golang-dev
https://golang.org/cl/18230043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20620043
2013-11-01 11:24:57 +11:00
Andrew Gerrand
744d53cdeb [release-branch.go1.2] debug/dwarf: add DWARF 4 form constants
««« CL 18460043 / 08e6655618f5
debug/dwarf: add DWARF 4 form constants

Some versions of clang generate DWARF 4-format attributes
even when using -gdwarf-2. We don't care much about the
values, but we do need to be able to parse past them.

This fixes a bug in Go 1.2 rc2 reported via private mail using
a near-tip version of clang.

R=golang-dev, iant, dvyukov
CC=golang-dev
https://golang.org/cl/18460043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20470045
2013-11-01 11:24:11 +11:00
Andrew Gerrand
2cce16c4a0 [release-branch.go1.2] doc: update front page summary text
««« CL 18080045 / 5ffdb9cc0bfe
doc: update front page summary text

R=rsc
CC=golang-dev
https://golang.org/cl/18080045
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20540044
2013-11-01 11:23:23 +11:00
Andrew Gerrand
153283b74b [release-branch.go1.2] cmd/cgo: stop using -fno-eliminate-unused-debug-types
««« CL 18850043 / 5ef4bf9eb256
cmd/cgo: stop using -fno-eliminate-unused-debug-types

This flag was added in January 2010, in CL 181102, to fix issue 497.
(Numbers were just shorter back then.) The fix was for OS X machines
and the llvm-gcc frontend.

In July 2011 we had to change the way we get enum values, because
there were no flags available to force Xcode's llvm-gcc to include the
enum names and values in DWARF debug output.

We now use clang, not llvm-gcc, on OS X machines.
Earlier versions of clang printed a warning about not knowing the flag.
Newer versions of clang now make that an error.

That is:
 - The flag was added for OS X machines.
 - The flag is no longer necessary on OS X machines.
 - The flag now breaks some OS X machines.

Remove it.

I have run the original program from issue 497 successfully
without the flag on both OS X and Linux machines.

Fixes #6678.

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/18850043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19850048
2013-11-01 11:22:39 +11:00
Andrew Gerrand
038ff9dca1 [release-branch.go1.2] runtime: relax preemption assertion during stack split
««« CL 18740044 / 1a8903f0a577
runtime: relax preemption assertion during stack split

The case can happen when starttheworld is calling acquirep
to get things moving again and acquirep gets preempted.
The stack trace is in golang.org/issue/6644.

It is difficult to build a short test case for this, but
the person who reported issue 6644 confirms that this
solves the problem.

Fixes #6644.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/18740044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20460044
2013-11-01 11:21:54 +11:00
Andrew Gerrand
724d28a03d [release-branch.go1.2] net: handle single-line non-\n-terminated files correctly in readLine
««« CL 15960047 / a0d4544cdb2a
net: handle single-line non-\n-terminated files correctly in readLine

Fixes #6646.

R=rsc, bradfitz
CC=golang-dev
https://golang.org/cl/15960047

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20560044
2013-11-01 11:21:05 +11:00
Andrew Gerrand
7097ed7337 [release-branch.go1.2] net/url: fix Encode doc comment
««« CL 16430043 / f9af8b83c78c
net/url: fix Encode doc comment

Encoded query strings are always sorted by key; the example wasn't.

R=golang-dev, dsymonds, minux.ma, bradfitz
CC=golang-dev
https://golang.org/cl/16430043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20480044
2013-11-01 11:20:21 +11:00
Andrew Gerrand
5962673984 [release-branch.go1.2] misc/linkcheck: better redirect handling, use meaningful exit code
««« CL 14425049 / 093d299d669e
misc/linkcheck: better redirect handling, use meaningful exit code

Prevent linkcheck from following redirects that lead beyond the outside
the root URL.

Return a non-zero exit code when there are problems.

Some minor refactoring for clarity.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/14425049
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20360044
2013-11-01 11:19:34 +11:00
Andrew Gerrand
efb3af3d5c [release-branch.go1.2] strings: fix Replacer bug with prefix matches
««« CL 16880043 / 0eb6508d3e88
strings: fix Replacer bug with prefix matches

singleStringReplacer had a bug where if a string was replaced
at the beginning and no output had yet been produced into the
temp buffer before matching ended, an invalid nil check (used
as a proxy for having matched anything) meant it always
returned its input.

Fixes #6659

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/16880043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20570044
2013-11-01 11:18:49 +11:00
Andrew Gerrand
7191e08599 [release-branch.go1.2] database/sql: link to wiki in package docs
««« CL 14087043 / 7ebbddd21330
database/sql: link to wiki in package docs

Update #5886

R=golang-dev, kamil.kisiel, adg, r, rsc, dave, arnehormann, bradfitz
CC=golang-dev
https://golang.org/cl/14087043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20610043
2013-11-01 11:18:03 +11:00
Andrew Gerrand
0911539937 [release-branch.go1.2] C+A: add Matthew Cottingham (Individual CLA)
««« CL 16650043 / afb8e00de04a
C+A: add Matthew Cottingham (Individual CLA)

Done by addca, but codereview failed with a Python stacktrace,
so submitting by hand.

R=golang-dev
CC=golang-dev
https://golang.org/cl/16650043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19560046
2013-11-01 11:17:17 +11:00
Andrew Gerrand
ce1a9fcbf5 [release-branch.go1.2] plan9: correct create permissions with union directory
««« CL 15360045 / f257b02e7ffe
plan9: correct create permissions with union directory

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/15360045

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19960046
2013-11-01 11:16:32 +11:00
Andrew Gerrand
cc10ac750d [release-branch.go1.2] misc/dist: use go.tools release branch
««« CL 15450047 / 1f81a19c2ee2
misc/dist: use go.tools release branch

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/15450047
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19850047
2013-11-01 11:15:47 +11:00
Andrew Gerrand
df3e05d37c [release-branch.go1.2] test/mapnan: use time.Now instead of syscall.Getrusage
««« CL 15570046 / 9169cb38c3e8
test/mapnan: use time.Now instead of syscall.Getrusage

Avoids a dependency on a somewhat nonstandard part of package syscall.

R=golang-dev, dave, r
CC=golang-dev
https://golang.org/cl/15570046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19960045
2013-11-01 11:15:02 +11:00
Andrew Gerrand
407b1130cd [release-branch.go1.2] cmd/cgo: use __typeof__, -w instead of typeof, -Wno-all
««« CL 14920052 / 98840b3349f4
cmd/cgo: use __typeof__, -w instead of typeof, -Wno-all

Suggested by iant in earlier CL.

R=golang-dev, bradfitz, iant
CC=golang-dev
https://golang.org/cl/14920052
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20600043
2013-11-01 11:14:19 +11:00
Andrew Gerrand
194b6a4bf2 [release-branch.go1.2] time: fix ParseDuration overflow when given more than 9 digits on 32-bit arch
««« CL 15080043 / fbf3b853e00b
time: fix ParseDuration overflow when given more than 9 digits on 32-bit arch
Fixes #6617.

R=golang-dev, rsc, r
CC=golang-dev
https://golang.org/cl/15080043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20050045
2013-11-01 11:13:30 +11:00
Andrew Gerrand
f17adc0765 [release-branch.go1.2] misc/emacs: handle empty "import ()" in go-goto-imports
««« CL 14454058 / 6b8f33ab7ca4
misc/emacs: handle empty "import ()" in go-goto-imports

R=adonovan
CC=golang-dev
https://golang.org/cl/14454058

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20590043
2013-11-01 11:12:28 +11:00
Andrew Gerrand
645a023474 [release-branch.go1.2] math: remove unnecessary source file
««« CL 15750046 / 2d1e1adf8ece
math: remove unnecessary source file

The routines in this file are dregs from a very early copy of the math API.
There are no Go prototypes and no non-amd64 implementations.

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/15750046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19560045
2013-11-01 11:11:36 +11:00
Andrew Gerrand
77ac7fdcc8 [release-branch.go1.2] go/build: document the go1.2 build tag
««« CL 14930046 / d4f6533fad0b
go/build: document the go1.2 build tag

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/14930046

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19960044
2013-11-01 11:10:46 +11:00
Andrew Gerrand
bf5d7c6713 [release-branch.go1.2] crypto/x509: name constraints should be a disjunction.
««« CL 15570044 / b4c37131e846
crypto/x509: name constraints should be a disjunction.

The code was requiring that all constraints be met, but it should be
satisfied by meeting *any* of them.

R=golang-dev, bradfitz, r
CC=golang-dev
https://golang.org/cl/15570044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20580043
2013-11-01 11:09:56 +11:00
Andrew Gerrand
6cbfe8df5c [release-branch.go1.2] crypto/tls: advertise support for RSA+SHA1 in TLS 1.2 handshake.
««« CL 15650043 / 29d3ab5ced5a
crypto/tls: advertise support for RSA+SHA1 in TLS 1.2 handshake.

Despite SHA256 support being required for TLS 1.2 handshakes, some
servers are aborting handshakes that don't offer SHA1 support.

This change adds support for signing TLS 1.2 ServerKeyExchange messages
with SHA1. It does not add support for signing TLS 1.2 client
certificates with SHA1 as that would require the handshake to be
buffered.

Fixes #6618.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/15650043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20570043
2013-11-01 11:09:06 +11:00
Andrew Gerrand
34250ab212 [release-branch.go1.2] net/mail: fix minor doc typo.
««« CL 15510043 / 6752a7aad603
net/mail: fix minor doc typo.

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/15510043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20560043
2013-11-01 11:08:05 +11:00
Andrew Gerrand
11f1f82b30 [release-branch.go1.2] cmd/yacc: fix stderr on Windows.
««« CL 15330043 / 69bf31787310
cmd/yacc: fix stderr on Windows.
Fixes #6620.

R=golang-dev, dave, r
CC=golang-dev
https://golang.org/cl/15330043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20550043
2013-11-01 11:07:06 +11:00
Andrew Gerrand
e3597e3920 [release-branch.go1.2] cmd/cgo: fix line number in an error message
««« CL 14870046 / b508daf6dae6
cmd/cgo: fix line number in an error message

Fixes #6563.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/14870046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20150045
2013-11-01 11:06:07 +11:00
Andrew Gerrand
265ff83af6 [release-branch.go1.2] cmd/cgo: stop using compiler error message text to analyze C names
««« CL 15070043 / 90a628ac54ed
cmd/cgo: stop using compiler error message text to analyze C names

The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program

        name;

and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.

The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:

        // error if and only if name is undeclared
        void f1(void) { typeof(name) *x; }

        // error if and only if name is not a type
        void f2(void) { name *x; }

        // error if and only if name is not an integer constant
        void f3(void) { enum { x = (name)*1 }; }

I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.

Fixes #6596.
Fixes #6612.

R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20060044
2013-11-01 11:05:17 +11:00
Andrew Gerrand
c57029d43d [release-branch.go1.2] cmd/gc: shorten name used for map bucket type
««« CL 15110044 / 95336afd420c
cmd/gc: shorten name used for map bucket type

Before:
type.struct { buckets *struct { overflow *struct { overflow *struct { overflow *struct { overflow *struct { overflow *<...>; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; oldbuckets *struct { overflow *struct { overflow *struct { overflow *struct { overflow *struct { overflow *<...>; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable } }

After:
type.map.bucket[string]*"".RangeTable

This makes debugging maps a little nicer, and it takes up less space in the binary.

R=golang-dev, r
CC=golang-dev, khr
https://golang.org/cl/15110044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20050044
2013-11-01 11:00:12 +11:00
Andrew Gerrand
287fa600ed [release-branch.go1.2] net: make sure failed Dial returns nil Conn
««« CL 14950045 / 1e60ffd5933d
net: make sure failed Dial returns nil Conn

Fixes #6614.

R=golang-dev, bradfitz, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/14950045
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20170047
2013-11-01 10:58:25 +11:00
Andrew Gerrand
000c1c5127 [release-branch.go1.2] runtime: remove nomemprof
««« CL 14695044 / 35d5bae6aac8
runtime: remove nomemprof
Nomemprof seems to be unneeded now, there is no recursion.
If the recursion will be re-introduced, it will break loudly by deadlocking.
Fixes #6566.

R=golang-dev, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/14695044
»»»

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/20540043
2013-11-01 10:51:42 +11:00
Andrew Gerrand
c1792398d4 [release-branch.go1.2] misc/dist: build race packages when os suffix present
««« CL 14930043 / 5746e3a5443b
misc/dist: build race packages when os suffix present

The "darwin-amd64-osx10.8" target was not matching "darwin-amd64".

R=golang-dev
CC=golang-dev
https://golang.org/cl/14930043
»»»

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/20290045
2013-11-01 10:50:00 +11:00
Andrew Gerrand
309e16554a go1.2rc2 2013-10-18 13:53:33 +09:00
65 changed files with 1133 additions and 1480 deletions

View File

@@ -149,6 +149,7 @@ Hong Ruiqi <hongruiqi@gmail.com>
Icarus Sparry <golang@icarus.freeuk.com>
Ingo Oeser <nightlyone@googlemail.com>
Isaac Wagner <ibw@isaacwagner.me>
Jakob Borg <jakob@nym.se>
James David Chalfant <james.chalfant@gmail.com>
James Fysh <james.fysh@gmail.com>
James Gray <james@james4k.com>
@@ -218,6 +219,7 @@ Mats Lidell <mats.lidell@cag.se>
Matt Jibson <matt.jibson@gmail.com>
Matt Joiner <anacrolix@gmail.com>
Matt Reiferson <mreiferson@gmail.com>
Matthew Cottingham <mattcottingham@gmail.com>
Matthew Horsnell <matthew.horsnell@gmail.com>
Micah Stetson <micah.stetson@gmail.com>
Michael Chaten <mchaten@gmail.com>

View File

@@ -220,6 +220,7 @@ Ingo Oeser <nightlyone@googlemail.com> <nightlyone@gmail.com>
Isaac Wagner <ibw@isaacwagner.me>
Ivan Krasin <krasin@golang.org>
Jacob Baskin <jbaskin@google.com>
Jakob Borg <jakob@nym.se>
James Aguilar <jaguilar@google.com>
James David Chalfant <james.chalfant@gmail.com>
James Fysh <james.fysh@gmail.com>
@@ -322,6 +323,7 @@ Matt Jibson <matt.jibson@gmail.com>
Matt Joiner <anacrolix@gmail.com>
Matt Jones <mrjones@google.com>
Matt Reiferson <mreiferson@gmail.com>
Matthew Cottingham <mattcottingham@gmail.com>
Matthew Dempsky <mdempsky@google.com>
Matthew Horsnell <matthew.horsnell@gmail.com>
Maxim Pimenov <mpimenov@google.com>

1
VERSION Normal file
View File

@@ -0,0 +1 @@
go1.2rc3

View File

@@ -137,6 +137,55 @@ This means that any loop that includes a (non-inlined) function call can
be pre-empted, allowing other goroutines to run on the same thread.
</p>
<h3 id="thread_limit">Limit on the number of threads</h3>
<p>
Go 1.2 introduces a configurable limit (default 10,000) to the total number of threads
a single program may have in its address space, to avoid resource starvation
issues in some environments.
Note that goroutines are multiplexed onto threads so this limit does not directly
limit the number of goroutines, only the number that may be simultaneously blocked
in a system call.
In practice, the limit is hard to reach.
</p>
<p>
The new <a href="/pkg/runtime/debug/#SetMaxThreads"><code>SetMaxThreads</code></a> function in the
<a href="/pkg/runtime/debug/"><code>runtime/debug</code></a> package controls the thread count limit.
</p>
<p>
<em>Updating</em>:
Few functions will be affected by the limit, but if a program dies because it hits the
limit, it could be modified to call <code>SetMaxThreads</code> to set a higher count.
Even better would be to refactor the program to need fewer threads, reducing consumption
of kernel resources.
</p>
<h3 id="stack_size">Stack size</h3>
<p>
In Go 1.2, the minimum size of the stack when a goroutine is created has been lifted from 4KB to 8KB.
Many programs were suffering performance problems with the old size, which had a tendency
to introduce expensive stack-segment switching in performance-critical sections.
The new number was determined by empirical testing.
</p>
<p>
At the other end, the new function <a href="/pkg/runtime/debug/#SetMaxStack"><code>SetMaxStack</code></a>
in the <a href="/pkg/runtime/debug"><code>runtime/debug</code></a> package controls
the <em>maximum</em> size of a single goroutine's stack.
The default is 1GB on 64-bit systems and 250MB on 32-bit systems.
Before Go 1.2, it was too easy for a runaway recursion to consume all the memory on a machine.
</p>
<p>
<em>Updating</em>:
The increased minimum stack size may cause programs with many goroutines to use
more memory. There is no workaround, but plans for future releases
include new stack management technology that should address the problem better.
</p>
<h3 id="cgo_and_cpp">Cgo and C++</h3>
<p>

View File

@@ -47,7 +47,7 @@ Hello, 世界
<div class="right">
<div id="about">
Go is an open source programming environment that makes it easy to build
Go is an open source programming language that makes it easy to build
simple, reliable, and efficient software.
</div>

View File

@@ -65,7 +65,7 @@ from mercurial import util as hg_util
if os.sys.platform == 'plan9':
try:
import plan9
n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE)
n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE|plan9.MCREATE)
except ImportError:
pass

View File

@@ -1,10 +1,14 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
/*
#cgo LDFLAGS: -c
void test() {
xxx; // This is line 7.
xxx; // ERROR HERE
}
*/
import "C"

13
misc/cgo/errors/err2.go Normal file
View File

@@ -0,0 +1,13 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "C"
func main() {
s := ""
_ = s
C.malloc(s) // ERROR HERE
}

View File

@@ -2,18 +2,30 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
if go tool cgo err1.go >errs 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail but it succeeded
exit 1
fi
if ! test -s errs; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output but saw none
exit 1
fi
if ! fgrep err1.go:7 errs >/dev/null 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error on line 7 but saw:
cat 1>&2 errs
exit 1
fi
check() {
file=$1
line=$(grep -n 'ERROR HERE' $file | sed 's/:.*//')
if [ "$line" = "" ]; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: cannot find ERROR HERE in $file
exit 1
fi
if go build $file >errs 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail but it succeeded
exit 1
fi
if ! test -s errs; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output but saw none
exit 1
fi
if ! fgrep $file:$line: errs >/dev/null 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error on line $line but saw:
cat 1>&2 errs
exit 1
fi
}
check err1.go
check err2.go
rm -rf errs _obj
exit 0

View File

@@ -49,5 +49,6 @@ func TestFpVar(t *testing.T) { testFpVar(t) }
func Test4339(t *testing.T) { test4339(t) }
func Test6390(t *testing.T) { test6390(t) }
func Test5986(t *testing.T) { test5986(t) }
func TestNaming(t *testing.T) { testNaming(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }

View File

@@ -0,0 +1,93 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// golang.org/issue/6612
// Test new scheme for deciding whether C.name is an expression, type, constant.
// Clang silences some warnings when the name is a #defined macro, so test those too
// (even though we now use errors exclusively, not warnings).
package cgotest
/*
void myfunc(void) {}
int myvar = 5;
const char *mytext = "abcdef";
typedef int mytype;
enum {
myenum = 1234,
};
#define myfunc_def myfunc
#define myvar_def myvar
#define mytext_def mytext
#define mytype_def mytype
#define myenum_def myenum
#define myint_def 12345
#define myfloat_def 1.5
#define mystring_def "hello"
*/
import "C"
import "testing"
func testNaming(t *testing.T) {
C.myfunc()
C.myfunc_def()
if v := C.myvar; v != 5 {
t.Errorf("C.myvar = %d, want 5", v)
}
if v := C.myvar_def; v != 5 {
t.Errorf("C.myvar_def = %d, want 5", v)
}
if s := C.GoString(C.mytext); s != "abcdef" {
t.Errorf("C.mytext = %q, want %q", s, "abcdef")
}
if s := C.GoString(C.mytext_def); s != "abcdef" {
t.Errorf("C.mytext_def = %q, want %q", s, "abcdef")
}
if c := C.myenum; c != 1234 {
t.Errorf("C.myenum = %v, want 1234", c)
}
if c := C.myenum_def; c != 1234 {
t.Errorf("C.myenum_def = %v, want 1234", c)
}
{
const c = C.myenum
if c != 1234 {
t.Errorf("C.myenum as const = %v, want 1234", c)
}
}
{
const c = C.myenum_def
if c != 1234 {
t.Errorf("C.myenum as const = %v, want 1234", c)
}
}
if c := C.myint_def; c != 12345 {
t.Errorf("C.myint_def = %v, want 12345", c)
}
{
const c = C.myint_def
if c != 12345 {
t.Errorf("C.myint as const = %v, want 12345", c)
}
}
// This would be nice, but it has never worked.
/*
if c := C.myfloat_def; c != 1.5 {
t.Errorf("C.myint_def = %v, want 1.5", c)
}
{
const c = C.myfloat_def
if c != 1.5 {
t.Errorf("C.myint as const = %v, want 1.5", c)
}
}
*/
if s := C.mystring_def; s != "hello" {
t.Errorf("C.mystring_def = %q, want %q", s, "hello")
}
}

View File

@@ -49,7 +49,7 @@ const (
blogPath = "code.google.com/p/go.blog"
toolPath = "code.google.com/p/go.tools"
tourPath = "code.google.com/p/go-tour"
defaultToolTag = "9e246fa49449" // go.tools as of 2013-10-18, for go1.2
defaultToolTag = "release-branch.go1.2"
)
// Import paths for tool commands.
@@ -175,7 +175,7 @@ func main() {
}
if *includeRace {
for _, t := range raceAvailable {
if t == targ {
if t == targ || strings.HasPrefix(targ, t+"-") {
b.Race = true
}
}

View File

@@ -749,6 +749,9 @@ declaration."
(let ((old-point (point)))
(goto-char (point-min))
(cond
((re-search-forward "^import ()" nil t)
(backward-char 1)
'block-empty)
((re-search-forward "^import ([^)]+)" nil t)
(backward-char 2)
'block)
@@ -843,6 +846,8 @@ uncommented, otherwise a new import will be added."
(uncomment-region (line-beginning-position) (line-end-position))
(case (go-goto-imports)
('fail (message "Could not find a place to add import."))
('block-empty
(insert "\n\t" line "\n"))
('block
(save-excursion
(re-search-backward "^import (")
@@ -945,11 +950,12 @@ will be commented, otherwise they will be removed completely."
"Given a file name in the format of `filename:line:column',
visit FILENAME and go to line LINE and column COLUMN."
(if (not (string-match "\\(.+\\):\\([0-9]+\\):\\([0-9]+\\)" specifier))
(error "Unexpected godef output: %s" specifier)
;; We've only been given a directory name
(funcall (if other-window #'find-file-other-window #'find-file) specifier)
(let ((filename (match-string 1 specifier))
(line (string-to-number (match-string 2 specifier)))
(column (string-to-number (match-string 3 specifier))))
(with-current-buffer (funcall (if other-window 'find-file-other-window 'find-file) filename)
(with-current-buffer (funcall (if other-window #'find-file-other-window #'find-file) filename)
(go--goto-line line)
(beginning-of-line)
(forward-char (1- column))
@@ -1003,6 +1009,8 @@ description at POINT."
(message "%s" file))
((go--string-prefix-p "godef: no declaration found for " file)
(message "%s" file))
((go--string-prefix-p "error finding import path for " file)
(message "%s" file))
(t
(push-mark)
(ring-insert find-tag-marker-ring (point-marker))

View File

@@ -8,11 +8,13 @@
package main
import (
"errors"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"regexp"
"strings"
"sync"
@@ -101,57 +103,78 @@ func crawl(url string, sourceURL string) {
func addProblem(url, errmsg string) {
msg := fmt.Sprintf("Error on %s: %s (from %s)", url, errmsg, linkSources[url])
log.Print(msg)
if *verbose {
log.Print(msg)
}
problems = append(problems, msg)
}
func crawlLoop() {
for url := range urlq {
res, err := http.Get(url)
if err != nil {
addProblem(url, fmt.Sprintf("Error fetching: %v", err))
wg.Done()
continue
if err := doCrawl(url); err != nil {
addProblem(url, err.Error())
}
if res.StatusCode != 200 {
addProblem(url, fmt.Sprintf("Status code = %d", res.StatusCode))
wg.Done()
continue
}
slurp, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatalf("Error reading %s body: %v", url, err)
}
if *verbose {
log.Printf("Len of %s: %d", url, len(slurp))
}
body := string(slurp)
for _, ref := range localLinks(body) {
if *verbose {
log.Printf(" links to %s", ref)
}
dest := *root + ref
linkSources[dest] = append(linkSources[dest], url)
crawl(dest, url)
}
for _, id := range pageIDs(body) {
if *verbose {
log.Printf(" url %s has #%s", url, id)
}
fragExists[urlFrag{url, id}] = true
}
wg.Done()
}
}
func doCrawl(url string) error {
defer wg.Done()
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}
res, err := http.DefaultTransport.RoundTrip(req)
if err != nil {
return err
}
// Handle redirects.
if res.StatusCode/100 == 3 {
newURL, err := res.Location()
if err != nil {
return fmt.Errorf("resolving redirect: %v", err)
}
if !strings.HasPrefix(newURL.String(), *root) {
// Skip off-site redirects.
return nil
}
crawl(newURL.String(), url)
return nil
}
if res.StatusCode != 200 {
return errors.New(res.Status)
}
slurp, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatalf("Error reading %s body: %v", url, err)
}
if *verbose {
log.Printf("Len of %s: %d", url, len(slurp))
}
body := string(slurp)
for _, ref := range localLinks(body) {
if *verbose {
log.Printf(" links to %s", ref)
}
dest := *root + ref
linkSources[dest] = append(linkSources[dest], url)
crawl(dest, url)
}
for _, id := range pageIDs(body) {
if *verbose {
log.Printf(" url %s has #%s", url, id)
}
fragExists[urlFrag{url, id}] = true
}
return nil
}
func main() {
flag.Parse()
go crawlLoop()
crawl(*root, "")
crawl(*root+"/doc/go1.1.html", "")
wg.Wait()
close(urlq)
@@ -164,4 +187,7 @@ func main() {
for _, s := range problems {
fmt.Println(s)
}
if len(problems) > 0 {
os.Exit(1)
}
}

View File

@@ -472,14 +472,27 @@ noops(void)
p->to.reg = REGSP;
p->spadj = -8;
/* SUB $8,SP */
q1->as = ASUB;
q1->from.type = D_CONST;
q1->from.offset = 8;
q1->from.reg = NREG;
/* Keep saved LR at 0(SP) after SP change. */
/* MOVW 0(SP), REGTMP; MOVW REGTMP, -8!(SP) */
/* TODO: Remove SP adjustments; see issue 6699. */
q1->as = AMOVW;
q1->from.type = D_OREG;
q1->from.reg = REGSP;
q1->from.offset = 0;
q1->reg = NREG;
q1->to.type = D_REG;
q1->to.reg = REGTMP;
/* SUB $8,SP */
q1 = appendp(q1);
q1->as = AMOVW;
q1->from.type = D_REG;
q1->from.reg = REGTMP;
q1->reg = NREG;
q1->to.type = D_OREG;
q1->to.reg = REGSP;
q1->to.offset = -8;
q1->scond |= C_WBIT;
q1->spadj = 8;
break;

View File

@@ -269,29 +269,30 @@ Next, cgo needs to identify the kinds for each identifier. For the
identifiers C.foo and C.bar, cgo generates this C program:
<preamble>
void __cgo__f__(void) {
#line 1 "cgo-test"
foo;
enum { _cgo_enum_0 = foo };
bar;
enum { _cgo_enum_1 = bar };
}
#line 1 "not-declared"
void __cgo_f_xxx_1(void) { __typeof__(foo) *__cgo_undefined__; }
#line 1 "not-type"
void __cgo_f_xxx_2(void) { foo *__cgo_undefined__; }
#line 1 "not-const"
void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (foo)*1 }; }
#line 2 "not-declared"
void __cgo_f_xxx_1(void) { __typeof__(bar) *__cgo_undefined__; }
#line 2 "not-type"
void __cgo_f_xxx_2(void) { bar *__cgo_undefined__; }
#line 2 "not-const"
void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (bar)*1 }; }
This program will not compile, but cgo can look at the error messages
to infer the kind of each identifier. The line number given in the
error tells cgo which identifier is involved.
This program will not compile, but cgo can use the presence or absence
of an error message on a given line to deduce the information it
needs. The program is syntactically valid regardless of whether each
name is a type or an ordinary identifier, so there will be no syntax
errors that might stop parsing early.
An error like "unexpected type name" or "useless type name in empty
declaration" or "declaration does not declare anything" tells cgo that
the identifier is a type.
An error on not-declared:1 indicates that foo is undeclared.
An error on not-type:1 indicates that foo is not a type (if declared at all, it is an identifier).
An error on not-const:1 indicates that foo is not an integer constant.
An error like "statement with no effect" or "expression result unused"
tells cgo that the identifier is not a type, but not whether it is a
constant, function, or global variable.
An error like "not an integer constant" tells cgo that the identifier
is not a constant. If it is also not a type, it must be a function or
global variable. For now, those can be treated the same.
The line number specifies the name involved. In the example, 1 is foo and 2 is bar.
Next, cgo must learn the details of each type, variable, function, or
constant. It can do this by reading object files. If cgo has decided
@@ -299,14 +300,14 @@ that t1 is a type, v2 and v3 are variables or functions, and c4, c5,
and c6 are constants, it generates:
<preamble>
typeof(t1) *__cgo__1;
typeof(v2) *__cgo__2;
typeof(v3) *__cgo__3;
typeof(c4) *__cgo__4;
__typeof__(t1) *__cgo__1;
__typeof__(v2) *__cgo__2;
__typeof__(v3) *__cgo__3;
__typeof__(c4) *__cgo__4;
enum { __cgo_enum__4 = c4 };
typeof(c5) *__cgo__5;
__typeof__(c5) *__cgo__5;
enum { __cgo_enum__5 = c5 };
typeof(c6) *__cgo__6;
__typeof__(c6) *__cgo__6;
enum { __cgo_enum__6 = c6 };
long long __cgo_debug_data[] = {

View File

@@ -226,42 +226,22 @@ func (p *Package) loadDefines(f *File) {
// name xxx for the references C.xxx in the Go input.
// The kind is either a constant, type, or variable.
func (p *Package) guessKinds(f *File) []*Name {
// Coerce gcc into telling us whether each name is
// a type, a value, or undeclared. We compile a function
// containing the line:
// name;
// If name is a type, gcc will print:
// cgo-test:2: warning: useless type name in empty declaration
// If name is a value, gcc will print
// cgo-test:2: warning: statement with no effect
// If name is undeclared, gcc will print
// cgo-test:2: error: 'name' undeclared (first use in this function)
// A line number directive causes the line number to
// correspond to the index in the names array.
//
// The line also has an enum declaration:
// name; enum { _cgo_enum_1 = name };
// If name is not a constant, gcc will print:
// cgo-test:4: error: enumerator value for '_cgo_enum_4' is not an integer constant
// we assume lines without that error are constants.
// Make list of names that need sniffing, type lookup.
toSniff := make([]*Name, 0, len(f.Name))
needType := make([]*Name, 0, len(f.Name))
// Determine kinds for names we already know about,
// like #defines or 'struct foo', before bothering with gcc.
var names, needType []*Name
for _, n := range f.Name {
// If we've already found this name as a #define
// and we can translate it as a constant value, do so.
if n.Define != "" {
ok := false
isConst := false
if _, err := strconv.Atoi(n.Define); err == nil {
ok = true
isConst = true
} else if n.Define[0] == '"' || n.Define[0] == '\'' {
if _, err := parser.ParseExpr(n.Define); err == nil {
ok = true
isConst = true
}
}
if ok {
if isConst {
n.Kind = "const"
// Turn decimal into hex, just for consistency
// with enum-derived constants. Otherwise
@@ -281,126 +261,139 @@ func (p *Package) guessKinds(f *File) []*Name {
}
}
// If this is a struct, union, or enum type name,
// record the kind but also that we need type information.
needType = append(needType, n)
// If this is a struct, union, or enum type name, no need to guess the kind.
if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
n.Kind = "type"
i := len(needType)
needType = needType[0 : i+1]
needType[i] = n
continue
}
i := len(toSniff)
toSniff = toSniff[0 : i+1]
toSniff[i] = n
// Otherwise, we'll need to find out from gcc.
names = append(names, n)
}
if len(toSniff) == 0 {
// Bypass gcc if there's nothing left to find out.
if len(names) == 0 {
return needType
}
// Coerce gcc into telling us whether each name is a type, a value, or undeclared.
// For names, find out whether they are integer constants.
// We used to look at specific warning or error messages here, but that tied the
// behavior too closely to specific versions of the compilers.
// Instead, arrange that we can infer what we need from only the presence or absence
// of an error on a specific line.
//
// For each name, we generate these lines, where xxx is the index in toSniff plus one.
//
// #line xxx "not-declared"
// void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
// #line xxx "not-type"
// void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
// #line xxx "not-const"
// void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
//
// If we see an error at not-declared:xxx, the corresponding name is not declared.
// If we see an error at not-type:xxx, the corresponding name is a type.
// If we see an error at not-const:xxx, the corresponding name is not an integer constant.
// If we see no errors, we assume the name is an expression but not a constant
// (so a variable or a function).
//
// The specific input forms are chosen so that they are valid C syntax regardless of
// whether name denotes a type or an expression.
var b bytes.Buffer
b.WriteString(f.Preamble)
b.WriteString(builtinProlog)
b.WriteString("void __cgo__f__(void) {\n")
// For a #defined expression, clang silences the warning about "unused expression".
// http://llvm.org/viewvc/llvm-project?view=revision&revision=172696
// Silencing the warning is not a big deal, because our default assumption is that
// (in the absence of other evidence) names are expressions.
// However, if all the C names we are investigating are #defined expressions,
// clang will print no warnings at all and then exit successfully.
// We want clang to print warnings, so seed the code with a function
// that is guaranteed to provoke a warning (that we will ignore).
// This way, if clang becomes even more broken, we'll find out.
// See golang.org/issue/6128.
fmt.Fprintf(&b, "1;\n")
b.WriteString("#line 1 \"cgo-test\"\n")
for i, n := range toSniff {
fmt.Fprintf(&b, "%s; /* #%d */\nenum { _cgo_enum_%d = %s }; /* #%d */\n", n.C, i, i, n.C, i)
for i, n := range names {
fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
"void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
"#line %d \"not-type\"\n"+
"void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
"#line %d \"not-const\"\n"+
"void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n",
i+1, i+1, n.C,
i+1, i+1, n.C,
i+1, i+1, n.C)
}
b.WriteString("}\n")
fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
"int __cgo__1 = __cgo__2;\n")
stderr := p.gccErrors(b.Bytes())
if stderr == "" {
fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
}
names := make([]*Name, len(toSniff))
copy(names, toSniff)
isConst := make([]bool, len(toSniff))
for i := range isConst {
isConst[i] = true // until proven otherwise
}
completed := false
sniff := make([]int, len(names))
const (
notType = 1 << iota
notConst
)
for _, line := range strings.Split(stderr, "\n") {
if len(line) < 9 || line[0:9] != "cgo-test:" {
// the user will see any compiler errors when the code is compiled later.
if !strings.Contains(line, ": error:") {
// we only care about errors.
// we tried to turn off warnings on the command line, but one never knows.
continue
}
line = line[9:]
colon := strings.Index(line, ":")
if colon < 0 {
continue
}
i, err := strconv.Atoi(line[0:colon])
if err != nil {
continue
}
i = (i - 1) / 2
what := ""
switch {
default:
continue
case strings.Contains(line, ": useless type name in empty declaration"),
strings.Contains(line, ": declaration does not declare anything"),
strings.Contains(line, ": unexpected type name"):
what = "type"
isConst[i] = false
case strings.Contains(line, ": statement with no effect"),
strings.Contains(line, ": expression result unused"):
what = "not-type" // const or func or var
case strings.Contains(line, "undeclared"):
error_(token.NoPos, "%s", strings.TrimSpace(line[colon+1:]))
case strings.Contains(line, "is not an integer constant"):
isConst[i] = false
continue
}
n := toSniff[i]
if n == nil {
continue
}
toSniff[i] = nil
n.Kind = what
j := len(needType)
needType = needType[0 : j+1]
needType[j] = n
}
for i, b := range isConst {
if b {
names[i].Kind = "const"
if toSniff[i] != nil && names[i].Const == "" {
j := len(needType)
needType = needType[0 : j+1]
needType[j] = names[i]
}
}
}
for _, n := range toSniff {
if n == nil {
c1 := strings.Index(line, ":")
if c1 < 0 {
continue
}
if n.Kind != "" {
c2 := strings.Index(line[c1+1:], ":")
if c2 < 0 {
continue
}
error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
c2 += c1 + 1
filename := line[:c1]
i, _ := strconv.Atoi(line[c1+1 : c2])
i--
if i < 0 || i >= len(names) {
continue
}
switch filename {
case "completed":
// Strictly speaking, there is no guarantee that seeing the error at completed:1
// (at the end of the file) means we've seen all the errors from earlier in the file,
// but usually it does. Certainly if we don't see the completed:1 error, we did
// not get all the errors we expected.
completed = true
case "not-declared":
error_(token.NoPos, "%s", strings.TrimSpace(line[c2+1:]))
case "not-type":
sniff[i] |= notType
case "not-const":
sniff[i] |= notConst
}
}
if !completed {
fatalf("%s did not produce error at completed:1\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
}
for i, n := range names {
switch sniff[i] {
case 0:
error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
case notType:
n.Kind = "const"
case notConst:
n.Kind = "type"
case notConst | notType:
n.Kind = "not-type"
}
}
if nerrors > 0 {
fatalf("unresolved names")
}
needType = append(needType, names...)
return needType
}
@@ -413,14 +406,14 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
// for symbols in the object file, so it is not enough to print the
// preamble and hope the symbols we care about will be there.
// Instead, emit
// typeof(names[i]) *__cgo__i;
// __typeof__(names[i]) *__cgo__i;
// for each entry in names and then dereference the type we
// learn for __cgo__i.
var b bytes.Buffer
b.WriteString(f.Preamble)
b.WriteString(builtinProlog)
for i, n := range names {
fmt.Fprintf(&b, "typeof(%s) *__cgo__%d;\n", n.C, i)
fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
if n.Kind == "const" {
fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
}
@@ -661,7 +654,7 @@ func (p *Package) rewriteRef(f *File) {
// Okay - might be new(T)
expr = r.Name.Type.Go
} else if r.Name.Kind == "var" {
expr = &ast.StarExpr{X: expr}
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
}
case "type":
@@ -690,6 +683,16 @@ func (p *Package) rewriteRef(f *File) {
}
}
}
// Copy position information from old expr into new expr,
// in case expression being replaced is first on line.
// See golang.org/issue/6563.
pos := (*r.Expr).Pos()
switch x := expr.(type) {
case *ast.Ident:
expr = &ast.Ident{NamePos: pos, Name: x.Name}
}
*r.Expr = expr
}
@@ -739,13 +742,12 @@ func gccTmp() string {
// the input.
func (p *Package) gccCmd() []string {
c := append(p.gccBaseCmd(),
"-Wall", // many warnings
"-Werror", // warnings are errors
"-o"+gccTmp(), // write object to tmp
"-gdwarf-2", // generate DWARF v2 debugging symbols
"-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise
"-c", // do not link
"-xc", // input language is C
"-w", // no warnings
"-Wno-error", // warnings are not errors
"-o"+gccTmp(), // write object to tmp
"-gdwarf-2", // generate DWARF v2 debugging symbols
"-c", // do not link
"-xc", // input language is C
)
if strings.Contains(c[0], "clang") {
c = append(c,
@@ -778,6 +780,11 @@ func (p *Package) gccCmd() []string {
func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
runGcc(stdin, p.gccCmd())
isDebugData := func(s string) bool {
// Some systems use leading _ to denote non-assembly symbols.
return s == "__cgodebug_data" || s == "___cgodebug_data"
}
if f, err := macho.Open(gccTmp()); err == nil {
defer f.Close()
d, err := f.DWARF()
@@ -788,8 +795,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
if f.Symtab != nil {
for i := range f.Symtab.Syms {
s := &f.Symtab.Syms[i]
// Mach-O still uses a leading _ to denote non-assembly symbols.
if s.Name == "_"+"__cgodebug_data" {
if isDebugData(s.Name) {
// Found it. Now find data section.
if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
@@ -816,7 +822,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
if err == nil {
for i := range symtab {
s := &symtab[i]
if s.Name == "__cgodebug_data" {
if isDebugData(s.Name) {
// Found it. Now find data section.
if i := int(s.Section); 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
@@ -840,7 +846,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
}
var data []byte
for _, s := range f.Symbols {
if s.Name == "_"+"__cgodebug_data" {
if isDebugData(s.Name) {
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
if s.Value < sect.Size {
@@ -876,14 +882,6 @@ func (p *Package) gccErrors(stdin []byte) string {
// TODO(rsc): require failure
args := p.gccCmd()
// GCC 4.8.0 has a bug: it sometimes does not apply
// -Wunused-value to values that are macros defined in system
// headers. See issue 5118. Adding -Wsystem-headers avoids
// that problem. This will produce additional errors, but it
// doesn't matter because we will ignore all errors that are
// not marked for the cgo-test file.
args = append(args, "-Wsystem-headers")
if *debugGcc {
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
os.Stderr.Write(stdin)
@@ -1087,7 +1085,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
sub := c.Type(dt.Type, pos)
t.Align = sub.Align
gt.Elt = sub.Go
t.C.Set("typeof(%s[%d])", sub.C, dt.Count)
t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
case *dwarf.BoolType:
t.Go = c.bool
@@ -1225,7 +1223,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
case "class", "union":
t.Go = c.Opaque(t.Size)
if t.C.Empty() {
t.C.Set("typeof(unsigned char[%d])", t.Size)
t.C.Set("__typeof__(unsigned char[%d])", t.Size)
}
t.Align = 1 // TODO: should probably base this on field alignment.
typedef[name.Name] = t

View File

@@ -700,6 +700,13 @@ typefmt(Fmt *fp, Type *t)
return 0;
case TSTRUCT:
// Format the bucket struct for map[x]y as map.bucket[x]y.
// This avoids a recursive print that generates very long names.
if(t->hmap != T) {
t = t->hmap;
return fmtprint(fp, "map.bucket[%T]%T", t->down, t->type);
}
if(t->funarg) {
fmtstrcpy(fp, "(");
if(fmtmode == FTypeId || fmtmode == FErr) { // no argument names on function signature, and no "noescape" tags

View File

@@ -62,7 +62,7 @@ begin:
// sys.go claims to be in package PACKAGE to avoid
// conflicts during "6g sys.go". rename PACKAGE to $2.
printf("\t\"");
while(q = strstr(p, "PACKAGE")) {
while((q = strstr(p, "PACKAGE")) != NULL) {
*q = 0;
esc(p); // up to the substitution
printf("%s", name); // the sub name

View File

@@ -229,6 +229,7 @@ hmap(Type *t)
h->width = offset;
h->local = t->local;
t->hmap = h;
h->hmap = t;
return h;
}

View File

@@ -1,5 +0,0 @@
# Copyright 2012 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include ../../Make.dist

View File

@@ -1,49 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
Prof is a rudimentary real-time profiler.
Given a command to run or the process id (pid) of a command already
running, it samples the program's state at regular intervals and reports
on its behavior. With no options, it prints a histogram of the locations
in the code that were sampled during execution.
Since it is a real-time profiler, unlike a traditional profiler it samples
the program's state even when it is not running, such as when it is
asleep or waiting for I/O. Each thread contributes equally to the
statistics.
Usage:
go tool prof -p pid [-t total_secs] [-d delta_msec] [6.out args ...]
The output modes (default -h) are:
-P file.prof:
Write the profile information to file.prof, in the format used by pprof.
At the moment, this only works on Linux amd64 binaries and requires that the
binary be written using 6l -e to produce ELF debug info.
See http://code.google.com/p/google-perftools for details.
-h: histograms
How many times a sample occurred at each location.
-f: dynamic functions
At each sample period, print the name of the executing function.
-l: dynamic file and line numbers
At each sample period, print the file and line number of the executing instruction.
-r: dynamic registers
At each sample period, print the register contents.
-s: dynamic function stack traces
At each sample period, print the symbolic stack trace.
Flag -t sets the maximum real time to sample, in seconds, and -d
sets the sampling interval in milliseconds. The default is to sample
every 100ms until the program completes.
It is installed as go tool prof and is architecture-independent.
*/
package main

View File

@@ -1,910 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !plan9
#include <u.h>
#include <time.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#define Ureg Ureg_amd64
#include <ureg_amd64.h>
#undef Ureg
#define Ureg Ureg_x86
#include <ureg_x86.h>
#undef Ureg
#include <mach.h>
char* file = "6.out";
static Fhdr fhdr;
int have_syms;
int fd;
struct Ureg_amd64 ureg_amd64;
struct Ureg_x86 ureg_x86;
int total_sec = 0;
int delta_msec = 100;
int nsample;
int nsamplethread;
// pprof data, stored as sequences of N followed by N PC values.
// See http://code.google.com/p/google-perftools .
uvlong *ppdata; // traces
Biobuf* pproffd; // file descriptor to write trace info
long ppstart; // start position of current trace
long nppdata; // length of data
long ppalloc; // size of allocated data
char ppmapdata[10*1024]; // the map information for the output file
// output formats
int pprof; // print pprof output to named file
int functions; // print functions
int histograms; // print histograms
int linenums; // print file and line numbers rather than function names
int registers; // print registers
int stacks; // print stack traces
int pid; // main process pid
int nthread; // number of threads
int thread[32]; // thread pids
Map *map[32]; // thread maps
void
Usage(void)
{
fprint(2, "Usage: prof -p pid [-t total_secs] [-d delta_msec]\n");
fprint(2, " prof [-t total_secs] [-d delta_msec] 6.out args ...\n");
fprint(2, "\tformats (default -h):\n");
fprint(2, "\t\t-P file.prof: write [c]pprof output to file.prof\n");
fprint(2, "\t\t-h: histograms\n");
fprint(2, "\t\t-f: dynamic functions\n");
fprint(2, "\t\t-l: dynamic file and line numbers\n");
fprint(2, "\t\t-r: dynamic registers\n");
fprint(2, "\t\t-s: dynamic function stack traces\n");
fprint(2, "\t\t-hs: include stack info in histograms\n");
exit(2);
}
typedef struct PC PC;
struct PC {
uvlong pc;
uvlong callerpc;
unsigned int count;
PC* next;
};
enum {
Ncounters = 256
};
PC *counters[Ncounters];
// Set up by setarch() to make most of the code architecture-independent.
typedef struct Arch Arch;
struct Arch {
char* name;
void (*regprint)(void);
int (*getregs)(Map*);
int (*getPC)(Map*);
int (*getSP)(Map*);
uvlong (*uregPC)(void);
uvlong (*uregSP)(void);
void (*ppword)(uvlong w);
};
void
amd64_regprint(void)
{
fprint(2, "ax\t0x%llux\n", ureg_amd64.ax);
fprint(2, "bx\t0x%llux\n", ureg_amd64.bx);
fprint(2, "cx\t0x%llux\n", ureg_amd64.cx);
fprint(2, "dx\t0x%llux\n", ureg_amd64.dx);
fprint(2, "si\t0x%llux\n", ureg_amd64.si);
fprint(2, "di\t0x%llux\n", ureg_amd64.di);
fprint(2, "bp\t0x%llux\n", ureg_amd64.bp);
fprint(2, "r8\t0x%llux\n", ureg_amd64.r8);
fprint(2, "r9\t0x%llux\n", ureg_amd64.r9);
fprint(2, "r10\t0x%llux\n", ureg_amd64.r10);
fprint(2, "r11\t0x%llux\n", ureg_amd64.r11);
fprint(2, "r12\t0x%llux\n", ureg_amd64.r12);
fprint(2, "r13\t0x%llux\n", ureg_amd64.r13);
fprint(2, "r14\t0x%llux\n", ureg_amd64.r14);
fprint(2, "r15\t0x%llux\n", ureg_amd64.r15);
fprint(2, "ds\t0x%llux\n", ureg_amd64.ds);
fprint(2, "es\t0x%llux\n", ureg_amd64.es);
fprint(2, "fs\t0x%llux\n", ureg_amd64.fs);
fprint(2, "gs\t0x%llux\n", ureg_amd64.gs);
fprint(2, "type\t0x%llux\n", ureg_amd64.type);
fprint(2, "error\t0x%llux\n", ureg_amd64.error);
fprint(2, "pc\t0x%llux\n", ureg_amd64.ip);
fprint(2, "cs\t0x%llux\n", ureg_amd64.cs);
fprint(2, "flags\t0x%llux\n", ureg_amd64.flags);
fprint(2, "sp\t0x%llux\n", ureg_amd64.sp);
fprint(2, "ss\t0x%llux\n", ureg_amd64.ss);
}
int
amd64_getregs(Map *map)
{
int i;
union {
uvlong regs[1];
struct Ureg_amd64 ureg;
} u;
for(i = 0; i < sizeof ureg_amd64; i+=8) {
if(get8(map, (uvlong)i, &u.regs[i/8]) < 0)
return -1;
}
ureg_amd64 = u.ureg;
return 0;
}
int
amd64_getPC(Map *map)
{
uvlong x;
int r;
r = get8(map, offsetof(struct Ureg_amd64, ip), &x);
ureg_amd64.ip = x;
return r;
}
int
amd64_getSP(Map *map)
{
uvlong x;
int r;
r = get8(map, offsetof(struct Ureg_amd64, sp), &x);
ureg_amd64.sp = x;
return r;
}
uvlong
amd64_uregPC(void)
{
return ureg_amd64.ip;
}
uvlong
amd64_uregSP(void)
{
return ureg_amd64.sp;
}
void
amd64_ppword(uvlong w)
{
uchar buf[8];
buf[0] = w;
buf[1] = w >> 8;
buf[2] = w >> 16;
buf[3] = w >> 24;
buf[4] = w >> 32;
buf[5] = w >> 40;
buf[6] = w >> 48;
buf[7] = w >> 56;
Bwrite(pproffd, buf, 8);
}
void
x86_regprint(void)
{
fprint(2, "ax\t0x%ux\n", ureg_x86.ax);
fprint(2, "bx\t0x%ux\n", ureg_x86.bx);
fprint(2, "cx\t0x%ux\n", ureg_x86.cx);
fprint(2, "dx\t0x%ux\n", ureg_x86.dx);
fprint(2, "si\t0x%ux\n", ureg_x86.si);
fprint(2, "di\t0x%ux\n", ureg_x86.di);
fprint(2, "bp\t0x%ux\n", ureg_x86.bp);
fprint(2, "ds\t0x%ux\n", ureg_x86.ds);
fprint(2, "es\t0x%ux\n", ureg_x86.es);
fprint(2, "fs\t0x%ux\n", ureg_x86.fs);
fprint(2, "gs\t0x%ux\n", ureg_x86.gs);
fprint(2, "cs\t0x%ux\n", ureg_x86.cs);
fprint(2, "flags\t0x%ux\n", ureg_x86.flags);
fprint(2, "pc\t0x%ux\n", ureg_x86.pc);
fprint(2, "sp\t0x%ux\n", ureg_x86.sp);
fprint(2, "ss\t0x%ux\n", ureg_x86.ss);
}
int
x86_getregs(Map *map)
{
int i;
for(i = 0; i < sizeof ureg_x86; i+=4) {
if(get4(map, (uvlong)i, &((uint32*)&ureg_x86)[i/4]) < 0)
return -1;
}
return 0;
}
int
x86_getPC(Map* map)
{
return get4(map, offsetof(struct Ureg_x86, pc), &ureg_x86.pc);
}
int
x86_getSP(Map* map)
{
return get4(map, offsetof(struct Ureg_x86, sp), &ureg_x86.sp);
}
uvlong
x86_uregPC(void)
{
return (uvlong)ureg_x86.pc;
}
uvlong
x86_uregSP(void)
{
return (uvlong)ureg_x86.sp;
}
void
x86_ppword(uvlong w)
{
uchar buf[4];
buf[0] = w;
buf[1] = w >> 8;
buf[2] = w >> 16;
buf[3] = w >> 24;
Bwrite(pproffd, buf, 4);
}
Arch archtab[] = {
{
"amd64",
amd64_regprint,
amd64_getregs,
amd64_getPC,
amd64_getSP,
amd64_uregPC,
amd64_uregSP,
amd64_ppword,
},
{
"386",
x86_regprint,
x86_getregs,
x86_getPC,
x86_getSP,
x86_uregPC,
x86_uregSP,
x86_ppword,
},
{
nil
}
};
Arch *arch;
int
setarch(void)
{
int i;
if(mach != nil) {
for(i = 0; archtab[i].name != nil; i++) {
if (strcmp(mach->name, archtab[i].name) == 0) {
arch = &archtab[i];
return 0;
}
}
}
return -1;
}
int
getthreads(void)
{
int i, j, curn, found;
Map *curmap[nelem(map)];
int curthread[nelem(map)];
static int complained = 0;
curn = procthreadpids(pid, curthread, nelem(curthread));
if(curn <= 0)
return curn;
if(curn > nelem(map)) {
if(complained == 0) {
fprint(2, "prof: too many threads; limiting to %d\n", nthread, nelem(map));
complained = 1;
}
curn = nelem(map);
}
if(curn == nthread && memcmp(thread, curthread, curn*sizeof(*thread)) == 0)
return curn; // no changes
// Number of threads has changed (might be the init case).
// A bit expensive but rare enough not to bother being clever.
for(i = 0; i < curn; i++) {
found = 0;
for(j = 0; j < nthread; j++) {
if(curthread[i] == thread[j]) {
found = 1;
curmap[i] = map[j];
map[j] = nil;
break;
}
}
if(found)
continue;
// map new thread
curmap[i] = attachproc(curthread[i], &fhdr);
if(curmap[i] == nil) {
fprint(2, "prof: can't attach to %d: %r\n", curthread[i]);
return -1;
}
}
for(j = 0; j < nthread; j++)
if(map[j] != nil)
detachproc(map[j]);
nthread = curn;
memmove(thread, curthread, nthread*sizeof thread[0]);
memmove(map, curmap, sizeof map);
return nthread;
}
int
sample(Map *map)
{
static int n;
n++;
if(registers) {
if(arch->getregs(map) < 0)
goto bad;
} else {
// we need only two registers
if(arch->getPC(map) < 0)
goto bad;
if(arch->getSP(map) < 0)
goto bad;
}
return 1;
bad:
if(n == 1)
fprint(2, "prof: can't read registers: %r\n");
return 0;
}
void
addtohistogram(uvlong pc, uvlong callerpc, uvlong sp)
{
int h;
PC *x;
USED(sp);
h = (pc + callerpc*101) % Ncounters;
for(x = counters[h]; x != NULL; x = x->next) {
if(x->pc == pc && x->callerpc == callerpc) {
x->count++;
return;
}
}
x = malloc(sizeof(PC));
if(x == nil)
sysfatal("out of memory");
x->pc = pc;
x->callerpc = callerpc;
x->count = 1;
x->next = counters[h];
counters[h] = x;
}
void
addppword(uvlong pc)
{
if(pc == 0) {
return;
}
if(nppdata == ppalloc) {
ppalloc = (1000+nppdata)*2;
ppdata = realloc(ppdata, ppalloc * sizeof ppdata[0]);
if(ppdata == nil) {
fprint(2, "prof: realloc failed: %r\n");
exit(2);
}
}
ppdata[nppdata++] = pc;
}
void
startpptrace(void)
{
ppstart = nppdata;
addppword(~0);
}
void
endpptrace(void)
{
ppdata[ppstart] = nppdata-ppstart-1;
}
uvlong nextpc;
void
xptrace(Map *map, uvlong pc, uvlong sp, Symbol *sym)
{
USED(map);
char buf[1024];
if(sym == nil){
fprint(2, "syms\n");
return;
}
if(histograms)
addtohistogram(nextpc, pc, sp);
if(!histograms || stacks > 1 || pprof) {
if(nextpc == 0)
nextpc = sym->value;
if(stacks){
fprint(2, "%s(", sym->name);
fprint(2, ")");
if(nextpc != sym->value)
fprint(2, "+%#llux ", nextpc - sym->value);
if(have_syms && linenums && fileline(buf, sizeof buf, pc)) {
fprint(2, " %s", buf);
}
fprint(2, "\n");
}
if (pprof) {
addppword(nextpc);
}
}
nextpc = pc;
}
void
stacktracepcsp(Map *map, uvlong pc, uvlong sp)
{
nextpc = pc;
if(pprof){
startpptrace();
}
if(machdata->ctrace==nil)
fprint(2, "no machdata->ctrace\n");
else if(machdata->ctrace(map, pc, sp, 0, xptrace) <= 0)
fprint(2, "no stack frame: pc=%#p sp=%#p\n", pc, sp);
else {
addtohistogram(nextpc, 0, sp);
if(stacks)
fprint(2, "\n");
}
if(pprof){
endpptrace();
}
}
void
printpc(Map *map, uvlong pc, uvlong sp)
{
char buf[1024];
if(registers)
arch->regprint();
if(have_syms > 0 && linenums && fileline(buf, sizeof buf, pc))
fprint(2, "%s\n", buf);
if(have_syms > 0 && functions) {
symoff(buf, sizeof(buf), pc, CANY);
fprint(2, "%s\n", buf);
}
if(stacks || pprof){
stacktracepcsp(map, pc, sp);
}
else if(histograms){
addtohistogram(pc, 0, sp);
}
}
void
ppmaps(void)
{
int fd, n;
char tmp[100];
Seg *seg;
// If it's Linux, the info is in /proc/$pid/maps
snprint(tmp, sizeof tmp, "/proc/%d/maps", pid);
fd = open(tmp, 0);
if(fd >= 0) {
n = read(fd, ppmapdata, sizeof ppmapdata - 1);
close(fd);
if(n < 0) {
fprint(2, "prof: can't read %s: %r\n", tmp);
exit(2);
}
ppmapdata[n] = 0;
return;
}
// It's probably a mac. Synthesize an entry for the text file.
// The register segment may come first but it has a zero offset, so grab the first non-zero offset segment.
for(n = 0; n < 3; n++){
seg = &map[0]->seg[n];
if(seg->b == 0) {
continue;
}
snprint(ppmapdata, sizeof ppmapdata,
"%.16x-%.16x r-xp %d 00:00 34968549 %s\n",
seg->b, seg->e, seg->f, "/home/r/6.out"
);
return;
}
fprint(2, "prof: no text segment in maps for %s\n", file);
exit(2);
}
void
samples(void)
{
int i, pid, msec;
struct timespec req;
int getmaps;
req.tv_sec = delta_msec/1000;
req.tv_nsec = 1000000*(delta_msec % 1000);
getmaps = 0;
if(pprof)
getmaps= 1;
for(msec = 0; total_sec <= 0 || msec < 1000*total_sec; msec += delta_msec) {
nsample++;
nsamplethread += nthread;
for(i = 0; i < nthread; i++) {
pid = thread[i];
if(ctlproc(pid, "stop") < 0)
return;
if(!sample(map[i])) {
ctlproc(pid, "start");
return;
}
printpc(map[i], arch->uregPC(), arch->uregSP());
ctlproc(pid, "start");
}
nanosleep(&req, NULL);
getthreads();
if(nthread == 0)
break;
if(getmaps) {
getmaps = 0;
ppmaps();
}
}
}
typedef struct Func Func;
struct Func
{
Func *next;
Symbol s;
uint onstack;
uint leaf;
};
Func *func[257];
int nfunc;
Func*
findfunc(uvlong pc)
{
Func *f;
uint h;
Symbol s;
if(pc == 0)
return nil;
if(!findsym(pc, CTEXT, &s))
return nil;
h = s.value % nelem(func);
for(f = func[h]; f != NULL; f = f->next)
if(f->s.value == s.value)
return f;
f = malloc(sizeof *f);
if(f == nil)
sysfatal("out of memory");
memset(f, 0, sizeof *f);
f->s = s;
f->next = func[h];
func[h] = f;
nfunc++;
return f;
}
int
compareleaf(const void *va, const void *vb)
{
Func *a, *b;
a = *(Func**)va;
b = *(Func**)vb;
if(a->leaf != b->leaf)
return b->leaf - a->leaf;
if(a->onstack != b->onstack)
return b->onstack - a->onstack;
return strcmp(a->s.name, b->s.name);
}
void
dumphistogram(void)
{
int i, h, n;
PC *x;
Func *f, **ff;
if(!histograms)
return;
// assign counts to functions.
for(h = 0; h < Ncounters; h++) {
for(x = counters[h]; x != NULL; x = x->next) {
f = findfunc(x->pc);
if(f) {
f->onstack += x->count;
f->leaf += x->count;
}
f = findfunc(x->callerpc);
if(f)
f->leaf -= x->count;
}
}
// build array
ff = malloc(nfunc*sizeof ff[0]);
if(ff == nil)
sysfatal("out of memory");
n = 0;
for(h = 0; h < nelem(func); h++)
for(f = func[h]; f != NULL; f = f->next)
ff[n++] = f;
// sort by leaf counts
qsort(ff, nfunc, sizeof ff[0], compareleaf);
// print.
fprint(2, "%d samples (avg %.1g threads)\n", nsample, (double)nsamplethread/nsample);
for(i = 0; i < nfunc; i++) {
f = ff[i];
fprint(2, "%6.2f%%\t", 100.0*(double)f->leaf/nsample);
if(stacks)
fprint(2, "%6.2f%%\t", 100.0*(double)f->onstack/nsample);
fprint(2, "%s\n", f->s.name);
}
}
typedef struct Trace Trace;
struct Trace {
int count;
int npc;
uvlong *pc;
Trace *next;
};
void
dumppprof(void)
{
uvlong i, n, *p, *e;
int ntrace;
Trace *trace, *tp, *up, *prev;
if(!pprof)
return;
e = ppdata + nppdata;
// Create list of traces. First, count the traces
ntrace = 0;
for(p = ppdata; p < e;) {
n = *p++;
p += n;
if(n == 0)
continue;
ntrace++;
}
if(ntrace <= 0)
return;
// Allocate and link the traces together.
trace = malloc(ntrace * sizeof(Trace));
if(trace == nil)
sysfatal("out of memory");
tp = trace;
for(p = ppdata; p < e;) {
n = *p++;
if(n == 0)
continue;
tp->count = 1;
tp->npc = n;
tp->pc = p;
tp->next = tp+1;
tp++;
p += n;
}
trace[ntrace-1].next = nil;
// Eliminate duplicates. Lousy algorithm, although not as bad as it looks because
// the list collapses fast.
for(tp = trace; tp != nil; tp = tp->next) {
prev = tp;
for(up = tp->next; up != nil; up = up->next) {
if(up->npc == tp->npc && memcmp(up->pc, tp->pc, up->npc*sizeof up->pc[0]) == 0) {
tp->count++;
prev->next = up->next;
} else {
prev = up;
}
}
}
// Write file.
// See http://code.google.com/p/google-perftools/source/browse/trunk/doc/cpuprofile-fileformat.html
// 1) Header
arch->ppword(0); // must be zero
arch->ppword(3); // 3 words follow in header
arch->ppword(0); // must be zero
arch->ppword(delta_msec * 1000); // sampling period in microseconds
arch->ppword(0); // must be zero (padding)
// 2) One record for each trace.
for(tp = trace; tp != nil; tp = tp->next) {
arch->ppword(tp->count);
arch->ppword(tp->npc);
for(i = 0; i < tp->npc; i++) {
arch->ppword(tp->pc[i]);
}
}
// 3) Binary trailer
arch->ppword(0); // must be zero
arch->ppword(1); // must be one
arch->ppword(0); // must be zero
// 4) Mapped objects.
Bwrite(pproffd, ppmapdata, strlen(ppmapdata));
// 5) That's it.
Bterm(pproffd);
}
int
startprocess(char **argv)
{
int pid;
if((pid = fork()) == 0) {
pid = getpid();
if(ctlproc(pid, "hang") < 0){
fprint(2, "prof: child process could not hang\n");
exits(0);
}
execv(argv[0], argv);
fprint(2, "prof: could not exec %s: %r\n", argv[0]);
exits(0);
}
if(pid == -1) {
fprint(2, "prof: could not fork\n");
exit(1);
}
if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0) {
fprint(2, "prof: could not attach to child process: %r\n");
exit(1);
}
return pid;
}
void
detach(void)
{
int i;
for(i = 0; i < nthread; i++)
detachproc(map[i]);
}
int
main(int argc, char *argv[])
{
int i;
char *ppfile;
ARGBEGIN{
case 'P':
pprof =1;
ppfile = EARGF(Usage());
pproffd = Bopen(ppfile, OWRITE);
if(pproffd == nil) {
fprint(2, "prof: cannot open %s: %r\n", ppfile);
exit(2);
}
break;
case 'd':
delta_msec = atoi(EARGF(Usage()));
break;
case 't':
total_sec = atoi(EARGF(Usage()));
break;
case 'p':
pid = atoi(EARGF(Usage()));
break;
case 'f':
functions = 1;
break;
case 'h':
histograms = 1;
break;
case 'l':
linenums = 1;
break;
case 'r':
registers = 1;
break;
case 's':
stacks++;
break;
default:
Usage();
}ARGEND
if(pid <= 0 && argc == 0)
Usage();
if(functions+linenums+registers+stacks+pprof == 0)
histograms = 1;
if(!machbyname("amd64")) {
fprint(2, "prof: no amd64 support\n", pid);
exit(1);
}
if(argc > 0)
file = argv[0];
else if(pid) {
file = proctextfile(pid);
if (file == NULL) {
fprint(2, "prof: can't find file for pid %d: %r\n", pid);
fprint(2, "prof: on Darwin, need to provide file name explicitly\n");
exit(1);
}
}
fd = open(file, 0);
if(fd < 0) {
fprint(2, "prof: can't open %s: %r\n", file);
exit(1);
}
if(crackhdr(fd, &fhdr)) {
have_syms = syminit(fd, &fhdr);
if(!have_syms) {
fprint(2, "prof: no symbols for %s: %r\n", file);
}
} else {
fprint(2, "prof: crack header for %s: %r\n", file);
exit(1);
}
if(pid <= 0)
pid = startprocess(argv);
attachproc(pid, &fhdr); // initializes thread list
if(setarch() < 0) {
detach();
fprint(2, "prof: can't identify binary architecture for pid %d\n", pid);
exit(1);
}
if(getthreads() <= 0) {
detach();
fprint(2, "prof: can't find threads for pid %d\n", pid);
exit(1);
}
for(i = 0; i < nthread; i++)
ctlproc(thread[i], "start");
samples();
detach();
dumphistogram();
dumppprof();
exit(0);
}

View File

@@ -357,7 +357,7 @@ func main() {
func setup() {
var j, ty int
stderr = bufio.NewWriter(os.NewFile(2, "stderr"))
stderr = bufio.NewWriter(os.Stderr)
foutput = nil
flag.Parse()

View File

@@ -126,10 +126,19 @@ type signatureAndHash struct {
hash, signature uint8
}
// supportedSignatureAlgorithms contains the signature and hash algorithms that
// the code can advertise as supported both in a TLS 1.2 ClientHello and
// supportedSKXSignatureAlgorithms contains the signature and hash algorithms
// that the code advertises as supported in a TLS 1.2 ClientHello.
var supportedSKXSignatureAlgorithms = []signatureAndHash{
{hashSHA256, signatureRSA},
{hashSHA256, signatureECDSA},
{hashSHA1, signatureRSA},
{hashSHA1, signatureECDSA},
}
// supportedClientCertSignatureAlgorithms contains the signature and hash
// algorithms that the code advertises as supported in a TLS 1.2
// CertificateRequest.
var supportedSignatureAlgorithms = []signatureAndHash{
var supportedClientCertSignatureAlgorithms = []signatureAndHash{
{hashSHA256, signatureRSA},
{hashSHA256, signatureECDSA},
}

View File

@@ -63,7 +63,7 @@ NextCipherSuite:
}
if hello.vers >= VersionTLS12 {
hello.signatureAndHashes = supportedSignatureAlgorithms
hello.signatureAndHashes = supportedSKXSignatureAlgorithms
}
c.writeRecord(recordTypeHandshake, hello.marshal())

View File

@@ -1834,30 +1834,30 @@ var clientChainCertificateScript = [][]byte{
// -minversion=0x0303 -maxversion=0x0303
var clientTLS12Script = [][]byte{
{
0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
0x50, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x16, 0x03, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00,
0x54, 0x03, 0x03, 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, 0x02, 0xc0, 0x13,
0x01, 0x00, 0x00, 0x25, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x29, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x04,
0x03,
0x0d, 0x00, 0x0a, 0x00, 0x08, 0x04, 0x01, 0x04,
0x03, 0x02, 0x01, 0x02, 0x03,
},
{
0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00,
0x50, 0x03, 0x03, 0x51, 0xe5, 0x78, 0x4c, 0x64,
0x66, 0xd0, 0xee, 0x0b, 0x8b, 0xfd, 0x9b, 0xe0,
0x54, 0x3c, 0x6e, 0x05, 0x04, 0x2f, 0x77, 0x07,
0x8c, 0x04, 0xb9, 0xf6, 0xdd, 0xea, 0x1a, 0x7c,
0xdf, 0x65, 0x39, 0x20, 0xea, 0xa2, 0xef, 0x53,
0x96, 0xf5, 0x0b, 0x8a, 0x47, 0xa0, 0x7c, 0x20,
0x53, 0x75, 0xee, 0x87, 0xb9, 0xd3, 0xe2, 0xa6,
0x97, 0x64, 0xb9, 0xa6, 0xcc, 0xc0, 0xe5, 0xbf,
0x92, 0x1d, 0xee, 0x4d, 0xc0, 0x13, 0x00, 0x00,
0x50, 0x03, 0x03, 0x52, 0x65, 0x67, 0xbd, 0xe8,
0x72, 0x03, 0x6a, 0x52, 0x8d, 0x28, 0x2c, 0x9a,
0x53, 0xff, 0xc2, 0xa1, 0x62, 0x5f, 0x54, 0xfb,
0x73, 0x00, 0xcf, 0x4d, 0x28, 0x36, 0xc2, 0xee,
0xfd, 0x78, 0xf0, 0x20, 0x6f, 0xbe, 0x49, 0xec,
0x5b, 0x6f, 0xf9, 0x53, 0x42, 0x69, 0x0d, 0x6d,
0x8b, 0x68, 0x2e, 0xca, 0x3c, 0x3c, 0x88, 0x9e,
0x8b, 0xf9, 0x32, 0x65, 0x09, 0xd6, 0xa0, 0x7d,
0xea, 0xc6, 0xd5, 0xc4, 0xc0, 0x13, 0x00, 0x00,
0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
0x02, 0x16, 0x03, 0x03, 0x02, 0x39, 0x0b, 0x00,
0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f,
@@ -1932,24 +1932,24 @@ var clientTLS12Script = [][]byte{
0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8,
0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16,
0x03, 0x03, 0x00, 0x8d, 0x0c, 0x00, 0x00, 0x89,
0x03, 0x00, 0x17, 0x41, 0x04, 0x39, 0xe9, 0x59,
0x24, 0x76, 0xf0, 0x1a, 0xd6, 0x21, 0xa5, 0xbc,
0x28, 0xb9, 0xd5, 0x3d, 0xf7, 0xf3, 0xbe, 0x09,
0xff, 0xc1, 0x79, 0x33, 0x82, 0xf8, 0xe1, 0x5f,
0x1c, 0x34, 0x96, 0x3a, 0x10, 0xf2, 0x2c, 0x69,
0xab, 0x57, 0xf6, 0x20, 0xb6, 0x59, 0x1f, 0x8c,
0x3e, 0xa2, 0xac, 0x4d, 0xf2, 0x10, 0x58, 0x0b,
0x61, 0x27, 0x6c, 0x47, 0xa0, 0x52, 0xc7, 0xe6,
0x36, 0xfd, 0xb1, 0xa2, 0x49, 0x04, 0x01, 0x00,
0x40, 0x99, 0x7e, 0xf9, 0xed, 0x8b, 0x62, 0x82,
0x00, 0xde, 0x5f, 0x2f, 0xb9, 0xf9, 0x9d, 0xa1,
0xb0, 0x14, 0x05, 0xc1, 0xdd, 0xa3, 0xb9, 0x08,
0xa5, 0x36, 0xb6, 0xfe, 0x8a, 0x5b, 0x2d, 0x6e,
0xd8, 0x5a, 0x5c, 0x89, 0x84, 0x85, 0x56, 0x01,
0xaf, 0x43, 0xd3, 0x0f, 0x85, 0xd0, 0xb2, 0x35,
0x3d, 0x1d, 0xd6, 0x67, 0x52, 0x48, 0xe8, 0x82,
0x47, 0xbb, 0x2a, 0x54, 0x4a, 0x55, 0xcd, 0x10,
0x54, 0x16, 0x03, 0x03, 0x00, 0x04, 0x0e, 0x00,
0x03, 0x00, 0x17, 0x41, 0x04, 0x48, 0x93, 0x62,
0x6a, 0xf8, 0x7c, 0x94, 0xcc, 0xcc, 0x0a, 0x9b,
0x5e, 0x11, 0xad, 0x0b, 0x30, 0xc4, 0x5d, 0xf7,
0x63, 0x24, 0xc1, 0xb0, 0x40, 0x5f, 0xff, 0x9f,
0x0d, 0x7e, 0xd5, 0xa5, 0xd0, 0x4f, 0x80, 0x16,
0xa8, 0x66, 0x18, 0x31, 0x1f, 0x81, 0xb2, 0x9a,
0x41, 0x62, 0x5b, 0xcf, 0x73, 0xac, 0x4a, 0x64,
0xb5, 0xc1, 0x46, 0x4d, 0x8a, 0xac, 0x25, 0xba,
0x81, 0x7f, 0xbe, 0x64, 0x68, 0x04, 0x01, 0x00,
0x40, 0x4e, 0x3f, 0x1e, 0x04, 0x4c, 0xef, 0xd2,
0xa6, 0x82, 0xe6, 0x7c, 0x76, 0x23, 0x17, 0xb9,
0xe7, 0x52, 0x15, 0x6b, 0x3d, 0xb2, 0xb1, 0x17,
0x7d, 0xe6, 0xde, 0x06, 0x87, 0x30, 0xb0, 0xb5,
0x57, 0xae, 0xdf, 0xb2, 0xdc, 0x8d, 0xab, 0x76,
0x9c, 0xaa, 0x45, 0x6d, 0x23, 0x5d, 0xc1, 0xa8,
0x7b, 0x79, 0x79, 0xb1, 0x3c, 0xdc, 0xf5, 0x33,
0x2c, 0xa1, 0x62, 0x3e, 0xbd, 0xf5, 0x5d, 0x6c,
0x87, 0x16, 0x03, 0x03, 0x00, 0x04, 0x0e, 0x00,
0x00, 0x00,
},
{
@@ -1965,74 +1965,74 @@ var clientTLS12Script = [][]byte{
0xdc, 0x5a, 0x89, 0x14, 0x03, 0x03, 0x00, 0x01,
0x01, 0x16, 0x03, 0x03, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xcb,
0x97, 0x41, 0x63, 0x39, 0xeb, 0xda, 0x04, 0x39,
0xfb, 0x67, 0x1d, 0x6d, 0xf8, 0x58, 0xd1, 0x22,
0x35, 0xe3, 0xc3, 0x9d, 0xfc, 0x4e, 0xcc, 0x71,
0x93, 0x78, 0x64, 0x39, 0x04, 0xa0, 0xa9, 0x41,
0xcf, 0x4c, 0xd6, 0x34, 0xad, 0x5c, 0xc9, 0x7a,
0x44, 0xb1, 0x1d, 0x77, 0x52, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x17,
0x54, 0x51, 0xb6, 0x1d, 0x8e, 0xe4, 0x6b, 0xed,
0x5b, 0xa1, 0x27, 0x7f, 0xdc, 0xa9, 0xa5, 0xcf,
0x38, 0xe6, 0x5d, 0x17, 0x34, 0xf9, 0xc0, 0x07,
0xb8, 0xbe, 0x56, 0xe6, 0xd6, 0x6a, 0xb6, 0x26,
0x4e, 0x45, 0x8d, 0x48, 0xe9, 0xc6, 0xb1, 0xa1,
0xea, 0xdc, 0xb1, 0x37, 0xd9, 0xf6,
},
{
0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
0x03, 0x00, 0x40, 0x55, 0x75, 0x8a, 0x57, 0xb4,
0x53, 0xa2, 0x8f, 0xbf, 0xd3, 0x79, 0x72, 0x1e,
0x94, 0x53, 0xb3, 0x03, 0x9d, 0x4d, 0x8a, 0x1f,
0xbd, 0x25, 0x79, 0x69, 0x61, 0x65, 0xd7, 0x26,
0xad, 0xa6, 0x0e, 0x89, 0x83, 0xc0, 0xbe, 0x46,
0x51, 0xe4, 0x38, 0x7b, 0x65, 0x74, 0x6d, 0x24,
0xff, 0xd4, 0x9f, 0xcb, 0xfc, 0xd7, 0x03, 0xaa,
0x7b, 0x8e, 0x30, 0x09, 0xdb, 0xaa, 0x9d, 0xad,
0xcd, 0x56, 0xcf,
0x03, 0x00, 0x40, 0x00, 0x68, 0xc5, 0x27, 0xd5,
0x3d, 0xba, 0x04, 0xde, 0x63, 0xf1, 0x5b, 0xc3,
0x86, 0xb9, 0x82, 0xc7, 0xb3, 0x90, 0x31, 0xea,
0x15, 0xe1, 0x42, 0x76, 0x7d, 0x90, 0xcb, 0xc9,
0xd1, 0x05, 0xe6, 0x8c, 0x76, 0xc7, 0x9a, 0x35,
0x67, 0xa2, 0x70, 0x9a, 0x8a, 0x6c, 0xb5, 0x6b,
0xc7, 0x87, 0xf3, 0x65, 0x0a, 0xa0, 0x98, 0xba,
0x57, 0xbb, 0x31, 0x7b, 0x1f, 0x1a, 0xf7, 0x2a,
0xf3, 0x12, 0xf6,
},
{
0x17, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x01, 0x46,
0xa8, 0xdd, 0x62, 0x73, 0x67, 0x99, 0x01, 0x42,
0xb2, 0x9e, 0x22, 0x18, 0xf5, 0x8f, 0x10, 0x97,
0xde, 0x58, 0x24, 0x34, 0x36, 0xa2, 0x5d, 0xf4,
0x96, 0x2a, 0xed, 0x6c, 0x06, 0x15, 0x03, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x80,
0x54, 0x1e, 0x72, 0xd3, 0x1a, 0x86, 0x1c, 0xc4,
0x4a, 0x9b, 0xd4, 0x80, 0xd2, 0x03, 0x35, 0x0d,
0xe4, 0x12, 0xc2, 0x3d, 0x79, 0x4a, 0x2c, 0xba,
0xc2, 0xad, 0xf3, 0xd2, 0x16, 0x15, 0x03, 0x03,
0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x9f, 0x7a, 0x9f, 0xab, 0xf5, 0x4e,
0x1c, 0x4e, 0xf4, 0xcb, 0x1a, 0x39, 0xae, 0x21,
0x85, 0x39, 0xc4, 0x51, 0xac, 0x14, 0xde, 0xa0,
0xe7, 0x70, 0x7c, 0x6a, 0x53, 0x54, 0x19, 0xbc,
0x2f, 0x32,
0x00, 0x00, 0x04, 0x9b, 0x68, 0x78, 0x92, 0x28,
0x62, 0x02, 0x65, 0x87, 0x90, 0xe4, 0x32, 0xd7,
0x72, 0x08, 0x70, 0xb8, 0x52, 0x32, 0x1f, 0x97,
0xd4, 0x6a, 0xc6, 0x28, 0x83, 0xb0, 0x1d, 0x6e,
0x16, 0xd5,
},
}
// $ openssl s_server -tls1_2 -cert server.crt -key server.key \
// -port 10443
// -port 10443 -verify 0
// $ go test -test.run "TestRunClient" -connect -ciphersuites=0xc02f \
// -maxversion=0x0303
var clientTLS12ClientCertScript = [][]byte{
{
0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
0x50, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x16, 0x03, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00,
0x54, 0x03, 0x03, 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, 0x02, 0xc0, 0x2f,
0x01, 0x00, 0x00, 0x25, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x29, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x04,
0x03,
0x0d, 0x00, 0x0a, 0x00, 0x08, 0x04, 0x01, 0x04,
0x03, 0x02, 0x01, 0x02, 0x03,
},
{
0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00,
0x50, 0x03, 0x03, 0x52, 0x37, 0x21, 0x96, 0x1c,
0x0a, 0x59, 0xc7, 0x16, 0x6d, 0x44, 0x76, 0xda,
0x3f, 0x36, 0x12, 0x0c, 0x9d, 0xe1, 0xf7, 0xeb,
0x45, 0x53, 0x89, 0xd6, 0x88, 0xc0, 0xe9, 0xce,
0x8b, 0x40, 0xf5, 0x20, 0x13, 0x61, 0xd9, 0x3b,
0x29, 0x74, 0x3c, 0x4b, 0x9c, 0x7b, 0x3d, 0xfa,
0x7a, 0x8e, 0x5b, 0xf2, 0x27, 0x62, 0xc5, 0xdf,
0xe4, 0x61, 0x7d, 0xe3, 0x8f, 0x03, 0x0c, 0x2b,
0x38, 0x6c, 0xfe, 0x31, 0xc0, 0x2f, 0x00, 0x00,
0x50, 0x03, 0x03, 0x52, 0x65, 0x67, 0xe0, 0xe8,
0xf1, 0x13, 0x2a, 0x83, 0x28, 0xa8, 0x2e, 0x76,
0x69, 0xe6, 0x89, 0x55, 0x6c, 0x48, 0x49, 0x2e,
0x00, 0xf6, 0x87, 0x6c, 0x13, 0xa1, 0xd4, 0xaa,
0xd0, 0x76, 0x3b, 0x20, 0xe4, 0xd6, 0x5b, 0x1d,
0x11, 0xf2, 0x42, 0xf2, 0x82, 0x0c, 0x0d, 0x66,
0x6d, 0xec, 0x52, 0xf8, 0x4a, 0xd9, 0x45, 0xcf,
0xe4, 0x4a, 0xba, 0x8b, 0xf1, 0xab, 0x55, 0xe4,
0x57, 0x18, 0xa9, 0x36, 0xc0, 0x2f, 0x00, 0x00,
0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
0x02, 0x16, 0x03, 0x03, 0x02, 0x39, 0x0b, 0x00,
0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f,
@@ -2107,24 +2107,24 @@ var clientTLS12ClientCertScript = [][]byte{
0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8,
0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16,
0x03, 0x03, 0x00, 0x8d, 0x0c, 0x00, 0x00, 0x89,
0x03, 0x00, 0x17, 0x41, 0x04, 0xdf, 0xc4, 0x75,
0x20, 0x7f, 0xc1, 0x8f, 0x92, 0x2d, 0xab, 0x2d,
0x65, 0x19, 0x40, 0xf6, 0x26, 0x19, 0x90, 0x84,
0x40, 0x55, 0xd3, 0x50, 0xe5, 0x63, 0x9e, 0x4b,
0x7a, 0x95, 0xdc, 0xb7, 0x2b, 0xa7, 0xa3, 0x5a,
0x5e, 0x01, 0xa0, 0x3e, 0xc2, 0x3c, 0x5d, 0xf6,
0x9a, 0xc8, 0xbe, 0x22, 0x23, 0x38, 0x31, 0x7c,
0x51, 0x83, 0x5d, 0x4f, 0xfb, 0x08, 0x66, 0x5f,
0xfe, 0xf5, 0x97, 0x9a, 0x93, 0x04, 0x01, 0x00,
0x40, 0x81, 0x52, 0x86, 0xe6, 0x20, 0x49, 0x65,
0x1b, 0x27, 0x46, 0x88, 0xd8, 0x0c, 0x44, 0x47,
0xae, 0xbd, 0xc6, 0xe4, 0x4a, 0x2c, 0x10, 0xf4,
0x3a, 0xd5, 0xbe, 0x5c, 0xfb, 0x5a, 0xe9, 0x85,
0x57, 0xda, 0xf9, 0xb1, 0x8e, 0xce, 0x01, 0x43,
0x84, 0x91, 0x68, 0x58, 0xa0, 0xbf, 0xd0, 0x24,
0xaa, 0x86, 0xfa, 0x19, 0x59, 0x06, 0x16, 0xe8,
0x82, 0x99, 0x90, 0x60, 0x02, 0x82, 0xaf, 0x7e,
0x0e, 0x16, 0x03, 0x03, 0x00, 0x30, 0x0d, 0x00,
0x03, 0x00, 0x17, 0x41, 0x04, 0xaa, 0xf0, 0x0c,
0xa3, 0x60, 0xcf, 0x69, 0x1e, 0xad, 0x16, 0x9a,
0x01, 0x40, 0xc6, 0x22, 0xc4, 0xbb, 0x06, 0x3b,
0x84, 0x65, 0xea, 0xc7, 0xa2, 0x96, 0x79, 0x17,
0x2f, 0xc7, 0xbe, 0x56, 0x39, 0xe4, 0x79, 0xf3,
0xad, 0x17, 0xf3, 0x7e, 0xe2, 0x7b, 0xa2, 0x6f,
0x3f, 0x96, 0xea, 0xe5, 0x0e, 0xea, 0x39, 0x79,
0x77, 0xeb, 0x14, 0x18, 0xbb, 0x7c, 0x95, 0xda,
0xa7, 0x51, 0x09, 0xba, 0xd7, 0x04, 0x01, 0x00,
0x40, 0x82, 0x3e, 0xce, 0xee, 0x7e, 0xba, 0x3b,
0x51, 0xb1, 0xba, 0x71, 0x2e, 0x54, 0xa9, 0xb9,
0xe2, 0xb1, 0x59, 0x17, 0xa1, 0xac, 0x76, 0xb4,
0x4e, 0xf1, 0xae, 0x65, 0x17, 0x2b, 0x43, 0x06,
0x31, 0x29, 0x0b, 0xa0, 0x1e, 0xb6, 0xfa, 0x35,
0xe8, 0x63, 0x06, 0xde, 0x13, 0x89, 0x83, 0x69,
0x3b, 0xc2, 0x15, 0x73, 0x1c, 0xc5, 0x07, 0xe9,
0x38, 0x9b, 0x06, 0x81, 0x1b, 0x97, 0x7c, 0xa6,
0x89, 0x16, 0x03, 0x03, 0x00, 0x30, 0x0d, 0x00,
0x00, 0x28, 0x03, 0x01, 0x02, 0x40, 0x00, 0x20,
0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01,
0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02,
@@ -2496,65 +2496,65 @@ var clientTLS12ClientCertScript = [][]byte{
0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
0xdc, 0x5a, 0x89, 0x16, 0x03, 0x03, 0x01, 0x08,
0x0f, 0x00, 0x01, 0x04, 0x04, 0x01, 0x01, 0x00,
0x78, 0x13, 0xba, 0x6a, 0xc6, 0xec, 0xd8, 0x03,
0x7f, 0x66, 0x83, 0xbd, 0xa6, 0xd0, 0x60, 0x05,
0x20, 0xf7, 0x2b, 0xa3, 0xe3, 0x8c, 0xbf, 0xab,
0x40, 0x95, 0x47, 0x31, 0xd0, 0xb6, 0x9e, 0x3c,
0x82, 0xf1, 0xd9, 0x25, 0x89, 0x6b, 0x12, 0xf4,
0xb4, 0xf4, 0x50, 0x44, 0xad, 0xa1, 0x96, 0x5a,
0x2e, 0x2a, 0x75, 0xb5, 0x61, 0x71, 0x08, 0xa0,
0x73, 0xc0, 0xdf, 0xa6, 0xd6, 0x34, 0x0f, 0xc8,
0x3d, 0x8e, 0x67, 0x73, 0x15, 0x7d, 0x6e, 0xe7,
0xe8, 0xf9, 0x79, 0xd2, 0x26, 0x28, 0xef, 0x94,
0x06, 0x68, 0xf4, 0x41, 0xc9, 0x06, 0x3c, 0x38,
0x27, 0xb9, 0xbe, 0xf3, 0x03, 0x9f, 0x3f, 0x17,
0xa9, 0xf8, 0x3f, 0x2b, 0x98, 0x09, 0x69, 0xd2,
0x98, 0x71, 0xa8, 0xec, 0xe6, 0xdc, 0xf3, 0x38,
0xbc, 0x2f, 0x4a, 0x91, 0xe5, 0x4e, 0x1d, 0x83,
0x49, 0xb4, 0xdb, 0x1c, 0x88, 0x6f, 0x0c, 0x5d,
0xbd, 0xf4, 0x9a, 0xd3, 0xd1, 0x32, 0xd0, 0xa6,
0xf1, 0xe9, 0xb8, 0xf6, 0xfe, 0x3c, 0x09, 0x67,
0x40, 0xb5, 0x13, 0xe6, 0xd4, 0x82, 0xda, 0x67,
0x27, 0x31, 0xc6, 0xac, 0xc8, 0xf4, 0x17, 0x99,
0x2c, 0x1d, 0xf1, 0x6f, 0x1d, 0x25, 0x5f, 0x83,
0x60, 0xa9, 0xaf, 0xf1, 0x24, 0x85, 0xd8, 0x01,
0x2f, 0x61, 0x21, 0x64, 0xeb, 0xa3, 0x43, 0xb7,
0x8f, 0x55, 0x1e, 0xb6, 0xda, 0x47, 0x30, 0xb2,
0x30, 0x40, 0xd9, 0x35, 0xb7, 0x6f, 0x5e, 0x7b,
0x6f, 0x00, 0x5a, 0x08, 0xa9, 0x67, 0xa4, 0xe5,
0xe7, 0xe9, 0xe1, 0xa7, 0x5b, 0x9e, 0xbd, 0xdb,
0xd1, 0x2a, 0x48, 0xb2, 0x4f, 0xf6, 0xd5, 0xe4,
0x44, 0x4a, 0xb8, 0xd3, 0x68, 0x25, 0xf9, 0xe9,
0xb2, 0xf5, 0xcc, 0xcd, 0x81, 0xe0, 0x01, 0x0e,
0xb6, 0x1a, 0xe4, 0x23, 0xe9, 0xee, 0xb1, 0x7b,
0xca, 0xa8, 0xaa, 0x45, 0xf4, 0x14, 0xeb, 0x2d,
0x7e, 0xe4, 0x65, 0x02, 0x8e, 0xb3, 0x34, 0x6a,
0x47, 0x71, 0xd1, 0xb0, 0x8d, 0x3c, 0x0c, 0xe1,
0xde, 0x7e, 0x5f, 0xb4, 0x15, 0x2d, 0x32, 0x0a,
0x2a, 0xdb, 0x9b, 0x40, 0xba, 0xce, 0x8b, 0xf5,
0x74, 0xc1, 0x68, 0x20, 0x7c, 0x87, 0x23, 0x13,
0xc3, 0x13, 0xa7, 0xdb, 0xec, 0x59, 0xa0, 0x40,
0x9e, 0x64, 0x03, 0x60, 0xac, 0x76, 0xff, 0x01,
0x34, 0x7b, 0x32, 0x26, 0xd9, 0x41, 0x31, 0x93,
0xaa, 0x30, 0x51, 0x83, 0x85, 0x40, 0xeb, 0x4e,
0x66, 0x39, 0x83, 0xb1, 0x30, 0x0d, 0x96, 0x01,
0xee, 0x81, 0x53, 0x5e, 0xec, 0xa9, 0xc9, 0xdf,
0x7e, 0xc1, 0x09, 0x47, 0x8b, 0x35, 0xdb, 0x10,
0x15, 0xd4, 0xc7, 0x5a, 0x39, 0xe3, 0xc0, 0xf3,
0x93, 0x38, 0x11, 0xdc, 0x71, 0xbb, 0xc7, 0x62,
0x2b, 0x85, 0xad, 0x6b, 0x4f, 0x09, 0xb3, 0x31,
0xa8, 0xe5, 0xd1, 0xb3, 0xa9, 0x21, 0x37, 0x50,
0xc8, 0x7d, 0xc3, 0xd2, 0xf7, 0x00, 0xd3, 0xdb,
0x0f, 0x82, 0xf2, 0x43, 0xcf, 0x36, 0x6c, 0x98,
0x63, 0xd8, 0x1d, 0xb3, 0xf3, 0xde, 0x63, 0x79,
0x64, 0xf0, 0xdb, 0x46, 0x04, 0xe1, 0x1c, 0x57,
0x0f, 0x9e, 0x96, 0xb9, 0x93, 0x45, 0x71, 0x1c,
0x8b, 0x65, 0x7d, 0x1e, 0xad, 0xbd, 0x03, 0x51,
0xae, 0x44, 0xef, 0x97, 0x45, 0x0d, 0x8d, 0x41,
0x5c, 0x80, 0x7b, 0xe6, 0xe0, 0xbc, 0xa6, 0x72,
0x95, 0xa0, 0x97, 0xe1, 0xbb, 0xc0, 0xcc, 0xe5,
0x1e, 0xc3, 0xbe, 0xd7, 0x42, 0x2a, 0xf3, 0x75,
0x8a, 0x44, 0x67, 0x3c, 0xe5, 0x68, 0x78, 0xe5,
0x40, 0x1f, 0xf0, 0x89, 0x57, 0xda, 0xee, 0x45,
0xf4, 0x44, 0x81, 0x01, 0x77, 0xf0, 0x4a, 0x14,
0xb1, 0x3f, 0x60, 0x2b, 0xeb, 0x42, 0x38, 0xa6,
0xfb, 0xe5, 0x4d, 0x71, 0xdc, 0x7d, 0x0a, 0x72,
0x56, 0x28, 0x9d, 0xa6, 0x8e, 0x74, 0x2d, 0xbd,
0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x56, 0x37, 0x62, 0x42, 0xb3,
0xdc, 0xa4, 0x01, 0x64, 0x7f, 0xa7, 0xcf, 0xb1,
0xa4, 0x03, 0x4c, 0xf2, 0x4c, 0xe1, 0xee, 0xd6,
0x29, 0x45, 0x71, 0x67, 0xeb, 0x3f, 0x82, 0x77,
0x65, 0x0c, 0x13,
0x00, 0x00, 0x00, 0x31, 0x4d, 0x58, 0x94, 0x0b,
0x0b, 0x06, 0x5f, 0xae, 0x57, 0x17, 0x98, 0x86,
0xaa, 0x49, 0x17, 0x7f, 0xbd, 0x41, 0x05, 0xa5,
0x74, 0x1c, 0x58, 0xc8, 0x38, 0x2d, 0x99, 0x5d,
0xe5, 0x12, 0x43,
},
{
0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
0x03, 0x00, 0x28, 0xd3, 0x6b, 0x15, 0x0f, 0x23,
0xd3, 0x5b, 0x93, 0x1d, 0x39, 0x6a, 0x74, 0xd9,
0x78, 0x39, 0xf6, 0x76, 0x6d, 0x5d, 0x21, 0x98,
0x7e, 0x10, 0xa4, 0x12, 0x11, 0x55, 0x25, 0xf7,
0x6f, 0x12, 0xf1, 0x9b, 0x9f, 0xe1, 0xc0, 0xe6,
0xbd, 0x93, 0xde,
0x03, 0x00, 0x28, 0xf2, 0x60, 0xc2, 0x75, 0x27,
0x64, 0xf4, 0x05, 0x98, 0xc9, 0xd3, 0xa8, 0x00,
0x4c, 0xa0, 0x49, 0x82, 0x68, 0xf1, 0x21, 0x05,
0x7b, 0x4b, 0x25, 0x3e, 0xe1, 0x5f, 0x0f, 0x84,
0x26, 0x2d, 0x16, 0x2e, 0xc0, 0xfd, 0xdf, 0x0a,
0xf4, 0xba, 0x19,
},
{
0x17, 0x03, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0xc8, 0x95, 0x86,
0xc0, 0xd0, 0xc2, 0x24, 0x1d, 0xf4, 0x20, 0xca,
0x2b, 0x30, 0x08, 0xf1, 0xb7, 0xe3, 0x5d, 0xcf,
0x86, 0xc3, 0xc5, 0x15, 0x03, 0x03, 0x00, 0x1a,
0x00, 0x00, 0x00, 0x00, 0x01, 0x35, 0xef, 0x9d,
0x6a, 0x86, 0x98, 0xc5, 0xca, 0x55, 0xca, 0x89,
0x29, 0xb4, 0x55, 0xd4, 0x41, 0x08, 0x96, 0xe0,
0xf3, 0x39, 0xfc, 0x15, 0x03, 0x03, 0x00, 0x1a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x20, 0x13, 0xac, 0xc4, 0x6a, 0x48, 0x36, 0x04,
0xdb, 0xae, 0x52, 0xc5, 0xc1, 0x6f, 0x4c, 0xc4,
0x0a, 0x77,
0x02, 0x63, 0x1b, 0xaa, 0xc6, 0xc9, 0x6d, 0x72,
0x24, 0x10, 0x55, 0xa9, 0x8c, 0x3b, 0x23, 0xce,
0xd8, 0x4a,
},
}

View File

@@ -136,7 +136,7 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
}
if rand.Intn(10) > 5 {
m.signatureAndHashes = supportedSignatureAlgorithms
m.signatureAndHashes = supportedSKXSignatureAlgorithms
}
return reflect.ValueOf(m)

View File

@@ -318,7 +318,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
if c.vers >= VersionTLS12 {
certReq.hasSignatureAndHash = true
certReq.signatureAndHashes = supportedSignatureAlgorithms
certReq.signatureAndHashes = supportedClientCertSignatureAlgorithms
}
// An empty list of certificateAuthorities signals to

View File

@@ -117,15 +117,47 @@ func sha256Hash(slices [][]byte) []byte {
}
// hashForServerKeyExchange hashes the given slices and returns their digest
// and the identifier of the hash function used.
func hashForServerKeyExchange(sigType uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash) {
// and the identifier of the hash function used. The hashFunc argument is only
// used for >= TLS 1.2 and precisely identifies the hash function to use.
func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
if version >= VersionTLS12 {
return sha256Hash(slices), crypto.SHA256
switch hashFunc {
case hashSHA256:
return sha256Hash(slices), crypto.SHA256, nil
case hashSHA1:
return sha1Hash(slices), crypto.SHA1, nil
default:
return nil, crypto.Hash(0), errors.New("tls: unknown hash function used by peer")
}
}
if sigType == signatureECDSA {
return sha1Hash(slices), crypto.SHA1
return sha1Hash(slices), crypto.SHA1, nil
}
return md5SHA1Hash(slices), crypto.MD5SHA1
return md5SHA1Hash(slices), crypto.MD5SHA1, nil
}
// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
// ServerKeyExchange given the signature type being used and the client's
// advertized list of supported signature and hash combinations.
func pickTLS12HashForSignature(sigType uint8, clientSignatureAndHashes []signatureAndHash) (uint8, error) {
if len(clientSignatureAndHashes) == 0 {
// If the client didn't specify any signature_algorithms
// extension then we can assume that it supports SHA1. See
// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
return hashSHA1, nil
}
for _, sigAndHash := range clientSignatureAndHashes {
if sigAndHash.signature != sigType {
continue
}
switch sigAndHash.hash {
case hashSHA1, hashSHA256:
return sigAndHash.hash, nil
}
}
return 0, errors.New("tls: client doesn't support any common hash functions")
}
// ecdheRSAKeyAgreement implements a TLS key agreement where the server
@@ -181,7 +213,17 @@ Curve:
serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic)
digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, hello.random, serverECDHParams)
var tls12HashId uint8
if ka.version >= VersionTLS12 {
if tls12HashId, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
return nil, err
}
}
digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, hello.random, serverECDHParams)
if err != nil {
return nil, err
}
var sig []byte
switch ka.sigType {
case signatureECDSA:
@@ -216,7 +258,7 @@ Curve:
copy(skx.key, serverECDHParams)
k := skx.key[len(serverECDHParams):]
if ka.version >= VersionTLS12 {
k[0] = hashSHA256
k[0] = tls12HashId
k[1] = ka.sigType
k = k[2:]
}
@@ -279,9 +321,16 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
if len(sig) < 2 {
return errServerKeyExchange
}
var tls12HashId uint8
if ka.version >= VersionTLS12 {
// ignore SignatureAndHashAlgorithm
sig = sig[2:]
// handle SignatureAndHashAlgorithm
var sigAndHash []uint8
sigAndHash, sig = sig[:2], sig[2:]
if sigAndHash[1] != ka.sigType {
return errServerKeyExchange
}
tls12HashId = sigAndHash[0]
if len(sig) < 2 {
return errServerKeyExchange
}
@@ -292,7 +341,10 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
}
sig = sig[2:]
digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, serverHello.random, serverECDHParams)
digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, serverHello.random, serverECDHParams)
if err != nil {
return err
}
switch ka.sigType {
case signatureECDSA:
pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)

View File

@@ -154,14 +154,18 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
}
if len(c.PermittedDNSDomains) > 0 {
ok := false
for _, domain := range c.PermittedDNSDomains {
if opts.DNSName == domain ||
(strings.HasSuffix(opts.DNSName, domain) &&
len(opts.DNSName) >= 1+len(domain) &&
opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
continue
ok = true
break
}
}
if !ok {
return CertificateInvalidError{c, CANotAuthorizedForThisName}
}
}

View File

@@ -183,6 +183,24 @@ var verifyTests = []verifyTest{
{"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"},
},
},
{
// Check that a name constrained intermediate works even when
// it lists multiple constraints.
leaf: nameConstraintsLeaf,
intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2},
roots: []string{globalSignRoot},
currentTime: 1382387896,
dnsName: "secure.iddl.vt.edu",
expectedChains: [][]string{
{
"Technology-enhanced Learning and Online Strategies",
"Virginia Tech Global Qualified Server CA",
"Trusted Root CA G2",
"GlobalSign Root CA",
},
},
},
}
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
@@ -753,3 +771,168 @@ zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
ZQ==
-----END CERTIFICATE-----`
var nameConstraintsLeaf = `-----BEGIN CERTIFICATE-----
MIIHMTCCBRmgAwIBAgIIIZaV/3ezOJkwDQYJKoZIhvcNAQEFBQAwgcsxCzAJBgNV
BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEj
MCEGA1UECxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zp
cmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0
eTExMC8GA1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZl
ciBDQTAeFw0xMzA5MTkxNDM2NTVaFw0xNTA5MTkxNDM2NTVaMIHNMQswCQYDVQQG
EwJVUzERMA8GA1UECAwIVmlyZ2luaWExEzARBgNVBAcMCkJsYWNrc2J1cmcxPDA6
BgNVBAoMM1ZpcmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUg
VW5pdmVyc2l0eTE7MDkGA1UECwwyVGVjaG5vbG9neS1lbmhhbmNlZCBMZWFybmlu
ZyBhbmQgT25saW5lIFN0cmF0ZWdpZXMxGzAZBgNVBAMMEnNlY3VyZS5pZGRsLnZ0
LmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkOyPpsOK/6IuPG
WnIBlVwlHzeYf+cUlggqkLq0b0+vZbiTXgio9/VCuNQ8opSoss7J7o3ygV9to+9Y
YwJKVC5WDT/y5JWpQey0CWILymViJnpNSwnxBc8A+Q8w5NUGDd/UhtPx/U8/hqbd
WPDYj2hbOqyq8UlRhfS5pwtnv6BbCTaY11I6FhCLK7zttISyTuWCf9p9o/ggiipP
ii/5oh4dkl+r5SfuSp5GPNHlYO8lWqys5NAPoDD4fc/kuflcK7Exx7XJ+Oqu0W0/
psjEY/tES1ZgDWU/ParcxxFpFmKHbD5DXsfPOObzkVWXIY6tGMutSlE1Froy/Nn0
OZsAOrcCAwEAAaOCAhMwggIPMIG4BggrBgEFBQcBAQSBqzCBqDBYBggrBgEFBQcw
AoZMaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbHF1YWxpZmllZHNlcnZlci9j
YWNlcnQvZ2xvYmFscXVhbGlmaWVkc2VydmVyLmNydDBMBggrBgEFBQcwAYZAaHR0
cDovL3Z0Y2EtcC5lcHJvdi5zZXRpLnZ0LmVkdTo4MDgwL2VqYmNhL3B1YmxpY3dl
Yi9zdGF0dXMvb2NzcDAdBgNVHQ4EFgQUp7xbO6iHkvtZbPE4jmndmnAbSEcwDAYD
VR0TAQH/BAIwADAfBgNVHSMEGDAWgBS8YmAn1eM1SBfpS6tFatDIqHdxjDBqBgNV
HSAEYzBhMA4GDCsGAQQBtGgFAgICATAOBgwrBgEEAbRoBQICAQEwPwYMKwYBBAG0
aAUCAgMBMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9i
YWwvY3BzLzBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vd3d3LnBraS52dC5lZHUv
Z2xvYmFscXVhbGlmaWVkc2VydmVyL2NybC9jYWNybC5jcmwwDgYDVR0PAQH/BAQD
AgTwMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHREEFjAUghJz
ZWN1cmUuaWRkbC52dC5lZHUwDQYJKoZIhvcNAQEFBQADggIBAEgoYo4aUtatY3gI
OyyKp7QlIOaLbTJZywESHqy+L5EGDdJW2DJV+mcE0LDGvqa2/1Lo+AR1ntsZwfOi
Y718JwgVVaX/RCd5+QKP25c5/x72xI8hb/L1bgS0ED9b0YAhd7Qm1K1ot82+6mqX
DW6WiGeDr8Z07MQ3143qQe2rBlq+QI69DYzm2GOqAIAnUIWv7tCyLUm31b4DwmrJ
TeudVreTKUbBNB1TWRFHEPkWhjjXKZnNGRO11wHXcyBu6YekIvVZ+vmx8ePee4jJ
3GFOi7lMuWOeq57jTVL7KOKaKLVXBb6gqo5aq+Wwt8RUD5MakrCAEeQZj7DKaFmZ
oQCO0Pxrsl3InCGvxnGzT+bFVO9nJ/BAMj7hknFdm9Jr6Bg5q33Z+gnf909AD9QF
ESqUSykaHu2LVdJx2MaCH1CyKnRgMw5tEwE15EXpUjCm24m8FMOYC+rNtf18pgrz
5D8Jhh+oxK9PjcBYqXNtnioIxiMCYcV0q5d4w4BYFEh71tk7/bYB0R55CsBUVPmp
timWNOdRd57Tfpk3USaVsumWZAf9MP3wPiC7gb4d5tYEEAG5BuDT8ruFw838wU8G
1VvAVutSiYBg7k3NYO7AUqZ+Ax4klQX3aM9lgonmJ78Qt94UPtbptrfZ4/lSqEf8
GBUwDrQNTb+gsXsDkjd5lcYxNx6l
-----END CERTIFICATE-----`
var nameConstraintsIntermediate1 = `-----BEGIN CERTIFICATE-----
MIINLjCCDBagAwIBAgIRIqpyf/YoGgvHc8HiDAxAI8owDQYJKoZIhvcNAQEFBQAw
XDELMAkGA1UEBhMCQkUxFTATBgNVBAsTDFRydXN0ZWQgUm9vdDEZMBcGA1UEChMQ
R2xvYmFsU2lnbiBudi1zYTEbMBkGA1UEAxMSVHJ1c3RlZCBSb290IENBIEcyMB4X
DTEyMTIxMzAwMDAwMFoXDTE3MTIxMzAwMDAwMFowgcsxCzAJBgNVBAYTAlVTMREw
DwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UECxMa
R2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1ZpcmdpbmlhIFBv
bHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8GA1UE
AxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFGzMXa
GHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3RhgV+r
ihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmjv7fm
5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t4lA9
pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP0YmM
R3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnbELhz
qyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyqG66W
ZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYrheq+
9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3JWqnV
HNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wUin3y
cnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX0071s3
Z2a2fio5c8m3JkdrAgMBAAGjggh5MIIIdTAOBgNVHQ8BAf8EBAMCAQYwTAYDVR0g
BEUwQzBBBgkrBgEEAaAyATwwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv
YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wEgYDVR0TAQH/BAgwBgEB/wIBADCCBtAG
A1UdHgSCBscwggbDoIIGvzASghAzZGJsYWNrc2J1cmcub3JnMBiCFmFjY2VsZXJh
dGV2aXJnaW5pYS5jb20wGIIWYWNjZWxlcmF0ZXZpcmdpbmlhLm9yZzALgglhY3Zj
cC5vcmcwCYIHYmV2Lm5ldDAJggdiZXYub3JnMAuCCWNsaWdzLm9yZzAMggpjbWl3
ZWIub3JnMBeCFWVhc3Rlcm5icm9va3Ryb3V0Lm5ldDAXghVlYXN0ZXJuYnJvb2t0
cm91dC5vcmcwEYIPZWNvcnJpZG9ycy5pbmZvMBOCEWVkZ2FycmVzZWFyY2gub3Jn
MBKCEGdldC1lZHVjYXRlZC5jb20wE4IRZ2V0LWVkdWNhdGVkLmluZm8wEYIPZ2V0
ZWR1Y2F0ZWQubmV0MBKCEGdldC1lZHVjYXRlZC5uZXQwEYIPZ2V0ZWR1Y2F0ZWQu
b3JnMBKCEGdldC1lZHVjYXRlZC5vcmcwD4INaG9raWVjbHViLmNvbTAQgg5ob2tp
ZXBob3RvLmNvbTAPgg1ob2tpZXNob3AuY29tMBGCD2hva2llc3BvcnRzLmNvbTAS
ghBob2tpZXRpY2tldHMuY29tMBKCEGhvdGVscm9hbm9rZS5jb20wE4IRaHVtYW53
aWxkbGlmZS5vcmcwF4IVaW5uYXR2aXJnaW5pYXRlY2guY29tMA+CDWlzY2hwMjAx
MS5vcmcwD4INbGFuZHJlaGFiLm9yZzAggh5uYXRpb25hbHRpcmVyZXNlYXJjaGNl
bnRlci5jb20wFYITbmV0d29ya3ZpcmdpbmlhLm5ldDAMggpwZHJjdnQuY29tMBiC
FnBldGVkeWVyaXZlcmNvdXJzZS5jb20wDYILcmFkaW9pcS5vcmcwFYITcml2ZXJj
b3Vyc2Vnb2xmLmNvbTALgglzZGltaS5vcmcwEIIOc292YW1vdGlvbi5jb20wHoIc
c3VzdGFpbmFibGUtYmlvbWF0ZXJpYWxzLmNvbTAeghxzdXN0YWluYWJsZS1iaW9t
YXRlcmlhbHMub3JnMBWCE3RoaXNpc3RoZWZ1dHVyZS5jb20wGIIWdGhpcy1pcy10
aGUtZnV0dXJlLmNvbTAVghN0aGlzaXN0aGVmdXR1cmUubmV0MBiCFnRoaXMtaXMt
dGhlLWZ1dHVyZS5uZXQwCoIIdmFkcy5vcmcwDIIKdmFsZWFmLm9yZzANggt2YXRl
Y2guaW5mbzANggt2YXRlY2gubW9iaTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5n
LmNvbTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5nLm5ldDAcghp2YXRlY2hsaWZl
bG9uZ2xlYXJuaW5nLm9yZzAKggh2Y29tLmVkdTASghB2aXJnaW5pYXZpZXcubmV0
MDSCMnZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVuaXZlcnNp
dHkuY29tMDWCM3ZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVu
aXZlcnNpdHkuaW5mbzA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0dXRlYW5k
c3RhdGV1bml2ZXJzaXR5Lm5ldDA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0
dXRlYW5kc3RhdGV1bml2ZXJzaXR5Lm9yZzAZghd2aXJnaW5pYXB1YmxpY3JhZGlv
Lm9yZzASghB2aXJnaW5pYXRlY2guZWR1MBOCEXZpcmdpbmlhdGVjaC5tb2JpMByC
GnZpcmdpbmlhdGVjaGZvdW5kYXRpb24ub3JnMAiCBnZ0LmVkdTALggl2dGFyYy5v
cmcwDIIKdnQtYXJjLm9yZzALggl2dGNyYy5jb20wCoIIdnRpcC5vcmcwDIIKdnRs
ZWFuLm9yZzAWghR2dGtub3dsZWRnZXdvcmtzLmNvbTAYghZ2dGxpZmVsb25nbGVh
cm5pbmcuY29tMBiCFnZ0bGlmZWxvbmdsZWFybmluZy5uZXQwGIIWdnRsaWZlbG9u
Z2xlYXJuaW5nLm9yZzATghF2dHNwb3J0c21lZGlhLmNvbTALggl2dHdlaS5jb20w
D4INd2l3YXR3ZXJjLmNvbTAKggh3dnRmLm9yZzAIgQZ2dC5lZHUwd6R1MHMxCzAJ
BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVy
ZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBT
dGF0ZSBVbml2ZXJzaXR5MCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDAQYI
KwYBBQUHAwkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2NybC5nbG9iYWxzaWdu
LmNvbS9ncy90cnVzdHJvb3RnMi5jcmwwgYQGCCsGAQUFBwEBBHgwdjAzBggrBgEF
BQcwAYYnaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3RydXN0cm9vdGcyMD8G
CCsGAQUFBzAChjNodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90
cnVzdHJvb3RnMi5jcnQwHQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8G
A1UdIwQYMBaAFBT25YsxtkWASkxt/MKHico2w5BiMA0GCSqGSIb3DQEBBQUAA4IB
AQAyJm/lOB2Er4tHXhc/+fSufSzgjohJgYfMkvG4LknkvnZ1BjliefR8tTXX49d2
SCDFWfGjqyJZwavavkl/4p3oXPG/nAMDMvxh4YAT+CfEK9HH+6ICV087kD4BLegi
+aFJMj8MMdReWCzn5sLnSR1rdse2mo2arX3Uod14SW+PGrbUmTuWNyvRbz3fVmxp
UdbGmj3laknO9YPsBGgHfv73pVVsTJkW4ZfY/7KdD/yaVv6ophpOB3coXfjl2+kd
Z4ypn2zK+cx9IL/LSewqd/7W9cD55PCUy4X9OTbEmAccwiz3LB66mQoUGfdHdkoB
jUY+v9vLQXmaVwI0AYL7g9LN
-----END CERTIFICATE-----`
var nameConstraintsIntermediate2 = `-----BEGIN CERTIFICATE-----
MIIEXTCCA0WgAwIBAgILBAAAAAABNuk6OrMwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMjA0MjUxMTAw
MDBaFw0yNzA0MjUxMTAwMDBaMFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVz
dGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRy
dXN0ZWQgUm9vdCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AKyuvqrtcMr7g7EuNbu4sKwxM127UsCmx1RxbxxgcArGS7rjiefpBH/w4LYrymjf
vcw1ueyMNoqLo9nJMz/ORXupb35NNfE667prQYHa+tTjl1IiKpB7QUwt3wXPuTMF
Ja1tXtjKzkqJyuJlNuPKT76HcjgNqgV1s9qG44MD5I2JvI12du8zI1bgdQ+l/KsX
kTfbGjUvhOLOlVNWVQDpL+YMIrGqgBYxy5TUNgrAcRtwpNdS2KkF5otSmMweVb5k
hoUVv3u8UxQH/WWbNhHq1RrIlg/0rBUfi/ziShYFSB7U+aLx5DxPphTFBiDquQGp
tB+FC4JvnukDStFihZCZ1R8CAwEAAaOCASMwggEfMA4GA1UdDwEB/wQEAwIBBjAP
BgNVHRMBAf8EBTADAQH/MEcGA1UdIARAMD4wPAYEVR0gADA0MDIGCCsGAQUFBwIB
FiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAdBgNVHQ4E
FgQUFPblizG2RYBKTG38woeJyjbDkGIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDov
L2NybC5nbG9iYWxzaWduLm5ldC9yb290LmNybDA+BggrBgEFBQcBAQQyMDAwLgYI
KwYBBQUHMAGGImh0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9yb290cjEwHwYD
VR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZIhvcNAQEFBQADggEB
AL7IG0l+k4LkcpI+a/kvZsSRwSM4uA6zGX34e78A2oytr8RG8bJwVb8+AHMUD+Xe
2kYdh/Uj/waQXfqR0OgxQXL9Ct4ZM+JlR1avsNKXWL5AwYXAXCOB3J5PW2XOck7H
Zw0vRbGQhjWjQx+B4KOUFg1b3ov/z6Xkr3yaCfRQhXh7KC0Bc0RXPPG5Nv5lCW+z
tbbg0zMm3kyfQITRusMSg6IBsDJqOnjaiaKQRcXiD0Sk43ZXb2bUKMxC7+Td3QL4
RyHcWJbQ7YylLTS/x+jxWIcOQ0oO5/54t5PTQ14neYhOz9x4gUk2AYAW6d1vePwb
hcC8roQwkHT7HvfYBoc74FM=
-----END CERTIFICATE-----`
var globalSignRoot = `-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----`

View File

@@ -140,8 +140,8 @@ type Stmt interface {
}
// ColumnConverter may be optionally implemented by Stmt if the
// the statement is aware of its own columns' types and can
// convert from any type to a driver Value.
// statement is aware of its own columns' types and can convert from
// any type to a driver Value.
type ColumnConverter interface {
// ColumnConverter returns a ValueConverter for the provided
// column index. If the type of a specific column isn't known

View File

@@ -7,6 +7,9 @@
//
// The sql package must be used in conjunction with a database driver.
// See http://golang.org/s/sqldrivers for a list of drivers.
//
// For more usage examples, see the wiki page at
// http://golang.org/s/sqlwiki.
package sql
import (
@@ -198,7 +201,7 @@ type DB struct {
connRequests *list.List // of connRequest
numOpen int
pendingOpens int
// Used to sygnal the need for new connections
// Used to signal the need for new connections
// a goroutine running connectionOpener() reads on this chan and
// maybeOpenNewConnections sends on the chan (one send per needed connection)
// It is closed during db.Close(). The close tells the connectionOpener
@@ -1634,7 +1637,16 @@ func (r *Row) Scan(dest ...interface{}) error {
// A Result summarizes an executed SQL command.
type Result interface {
// LastInsertId returns the integer generated by the database
// in response to a command. Typically this will be from an
// "auto increment" column when inserting a new row. Not all
// databases support this feature, and the syntax of such
// statements varies.
LastInsertId() (int64, error)
// RowsAffected returns the number of rows affected by an
// update, insert, or delete. Not every database or database
// driver may support this.
RowsAffected() (int64, error)
}

View File

@@ -207,7 +207,10 @@ const (
formRef8 format = 0x14
formRefUdata format = 0x15
formIndirect format = 0x16
formSecOffset format = 0x17
formExprloc format = 0x18
formFlagPresent format = 0x19
formRefSig8 format = 0x20
)
// A Tag is the classification (the type) of an Entry.

View File

@@ -188,6 +188,7 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
// flag
case formFlag:
val = b.uint8() == 1
// New in DWARF 4.
case formFlagPresent:
// The attribute is implicitly indicated as present, and no value is
// encoded in the debugging information entry itself.
@@ -236,6 +237,30 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
b.err = b1.err
return nil
}
// lineptr, loclistptr, macptr, rangelistptr
// New in DWARF 4, but clang can generate them with -gdwarf-2.
// Section reference, replacing use of formData4 and formData8.
case formSecOffset:
is64, known := b.format.dwarf64()
if !known {
b.error("unknown size for DW_FORM_sec_offset")
} else if is64 {
val = int64(b.uint64())
} else {
val = int64(b.uint32())
}
// exprloc
// New in DWARF 4.
case formExprloc:
val = b.bytes(int(b.uint()))
// reference
// New in DWARF 4.
case formRefSig8:
// 64-bit type signature.
val = b.uint64()
}
e.Field[i].Val = val
}

View File

@@ -53,7 +53,7 @@ import (
// Unmarshal records the attribute value in that field.
//
// * If the XML element contains character data, that data is
// accumulated in the first struct field that has tag "chardata".
// accumulated in the first struct field that has tag ",chardata".
// The struct field may have type []byte or string.
// If there is no such field, the character data is discarded.
//

View File

@@ -94,6 +94,7 @@
// - the compiler being used, either "gc" or "gccgo"
// - "cgo", if ctxt.CgoEnabled is true
// - "go1.1", from Go version 1.1 onward
// - "go1.2", from Go version 1.2 onward
// - any additional words listed in ctxt.BuildTags
//
// If a file's name, after stripping the extension and a possible _test suffix,

View File

@@ -1,69 +0,0 @@
// Derived from Inferno's libkern/getfcr-amd64.s
// http://code.google.com/p/inferno-os/source/browse/libkern/getfcr-amd64.s
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
// Portions Copyright 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "../../cmd/ld/textflag.h"
TEXT ·SetFPControl(SB), NOSPLIT, $8
// Set new
MOVL p+0(FP), DI
XORL $(0x3F<<7), DI
ANDL $0xFFC0, DI
WAIT
STMXCSR 0(SP)
MOVL 0(SP), AX
ANDL $~0x3F, AX
ORL DI, AX
MOVL AX, 0(SP)
LDMXCSR 0(SP)
RET
TEXT ·GetFPControl(SB), NOSPLIT, $0
WAIT
STMXCSR 0(SP)
MOVWLZX 0(SP), AX
ANDL $0xFFC0, AX
XORL $(0x3F<<7), AX
MOVL AX, ret+0(FP)
RET
TEXT ·SetFPStatus(SB), $0
MOVL p+0(FP), DI
ANDL $0x3F, DI
WAIT
STMXCSR 0(SP)
MOVL 0(SP), AX
ANDL $~0x3F, AX
ORL DI, AX
MOVL AX, 0(SP)
LDMXCSR 0(SP)
RET
TEXT ·GetFPStatus(SB), $0
WAIT
STMXCSR 0(SP)
MOVL 0(SP), AX
ANDL $0x3F, AX
MOVL AX, ret+0(FP)
RET

View File

@@ -215,26 +215,30 @@ func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Con
// dialSingle attempts to establish and returns a single connection to
// the destination address.
func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (Conn, error) {
func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
if la != nil && la.Network() != ra.Network() {
return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
}
switch ra := ra.(type) {
case *TCPAddr:
la, _ := la.(*TCPAddr)
return dialTCP(net, la, ra, deadline)
c, err = dialTCP(net, la, ra, deadline)
case *UDPAddr:
la, _ := la.(*UDPAddr)
return dialUDP(net, la, ra, deadline)
c, err = dialUDP(net, la, ra, deadline)
case *IPAddr:
la, _ := la.(*IPAddr)
return dialIP(net, la, ra, deadline)
c, err = dialIP(net, la, ra, deadline)
case *UnixAddr:
la, _ := la.(*UnixAddr)
return dialUnix(net, la, ra, deadline)
c, err = dialUnix(net, la, ra, deadline)
default:
return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}}
}
if err != nil {
return nil, err // c is non-nil interface containing nil pointer
}
return c, nil
}
// Listen announces on the local network address laddr.
@@ -246,14 +250,19 @@ func Listen(net, laddr string) (Listener, error) {
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
}
var l Listener
switch la := la.toAddr().(type) {
case *TCPAddr:
return ListenTCP(net, la)
l, err = ListenTCP(net, la)
case *UnixAddr:
return ListenUnix(net, la)
l, err = ListenUnix(net, la)
default:
return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
}
if err != nil {
return nil, err // l is non-nil interface containing nil pointer
}
return l, nil
}
// ListenPacket announces on the local network address laddr.
@@ -265,14 +274,19 @@ func ListenPacket(net, laddr string) (PacketConn, error) {
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
}
var l PacketConn
switch la := la.toAddr().(type) {
case *UDPAddr:
return ListenUDP(net, la)
l, err = ListenUDP(net, la)
case *IPAddr:
return ListenIP(net, la)
l, err = ListenIP(net, la)
case *UnixAddr:
return ListenUnixgram(net, la)
l, err = ListenUnixgram(net, la)
default:
return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
}
if err != nil {
return nil, err // l is non-nil interface containing nil pointer
}
return l, nil
}

View File

@@ -53,6 +53,19 @@ func TestLookupStaticHost(t *testing.T) {
hostsPath = p
}
// https://code.google.com/p/go/issues/detail?id=6646
func TestSingleLineHostsFile(t *testing.T) {
p := hostsPath
hostsPath = "testdata/hosts_singleline"
ips := lookupStaticHost("odin")
if len(ips) != 1 || ips[0] != "127.0.0.2" {
t.Errorf("lookupStaticHost = %v, want %v", ips, []string{"127.0.0.2"})
}
hostsPath = p
}
func TestLookupHost(t *testing.T) {
// Can't depend on this to return anything in particular,
// but if it does return something, make sure it doesn't

View File

@@ -45,13 +45,27 @@ func (c *dumpConn) SetDeadline(t time.Time) error { return nil }
func (c *dumpConn) SetReadDeadline(t time.Time) error { return nil }
func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
type neverEnding byte
func (b neverEnding) Read(p []byte) (n int, err error) {
for i := range p {
p[i] = byte(b)
}
return len(p), nil
}
// DumpRequestOut is like DumpRequest but includes
// headers that the standard http.Transport adds,
// such as User-Agent.
func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
save := req.Body
dummyBody := false
if !body || req.Body == nil {
req.Body = nil
if req.ContentLength != 0 {
req.Body = ioutil.NopCloser(io.LimitReader(neverEnding('x'), req.ContentLength))
dummyBody = true
}
} else {
var err error
save, req.Body, err = drainBody(req.Body)
@@ -99,7 +113,19 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
if err != nil {
return nil, err
}
return buf.Bytes(), nil
dump := buf.Bytes()
// If we used a dummy body above, remove it now.
// TODO: if the req.ContentLength is large, we allocate memory
// unnecessarily just to slice it off here. But this is just
// a debug function, so this is acceptable for now. We could
// discard the body earlier if this matters.
if dummyBody {
if i := bytes.Index(dump, []byte("\r\n\r\n")); i >= 0 {
dump = dump[:i+4]
}
}
return dump, nil
}
// delegateReader is a reader that delegates to another reader,

View File

@@ -20,6 +20,7 @@ type dumpTest struct {
WantDump string
WantDumpOut string
NoBody bool // if true, set DumpRequest{,Out} body to false
}
var dumpTests = []dumpTest{
@@ -83,6 +84,31 @@ var dumpTests = []dumpTest{
"User-Agent: Go 1.1 package http\r\n" +
"Accept-Encoding: gzip\r\n\r\n",
},
// Request with Body, but Dump requested without it.
{
Req: http.Request{
Method: "POST",
URL: &url.URL{
Scheme: "http",
Host: "post.tld",
Path: "/",
},
ContentLength: 6,
ProtoMajor: 1,
ProtoMinor: 1,
},
Body: []byte("abcdef"),
WantDumpOut: "POST / HTTP/1.1\r\n" +
"Host: post.tld\r\n" +
"User-Agent: Go 1.1 package http\r\n" +
"Content-Length: 6\r\n" +
"Accept-Encoding: gzip\r\n\r\n",
NoBody: true,
},
}
func TestDumpRequest(t *testing.T) {
@@ -105,7 +131,7 @@ func TestDumpRequest(t *testing.T) {
if tt.WantDump != "" {
setBody()
dump, err := DumpRequest(&tt.Req, true)
dump, err := DumpRequest(&tt.Req, !tt.NoBody)
if err != nil {
t.Errorf("DumpRequest #%d: %s", i, err)
continue
@@ -118,7 +144,7 @@ func TestDumpRequest(t *testing.T) {
if tt.WantDumpOut != "" {
setBody()
dump, err := DumpRequestOut(&tt.Req, true)
dump, err := DumpRequestOut(&tt.Req, !tt.NoBody)
if err != nil {
t.Errorf("DumpRequestOut #%d: %s", i, err)
continue

View File

@@ -521,7 +521,7 @@ func isAtext(c byte, dot bool) bool {
return bytes.IndexByte(atextChars, c) >= 0
}
// isQtext returns true if c is an RFC 5322 qtest character.
// isQtext returns true if c is an RFC 5322 qtext character.
func isQtext(c byte) bool {
// Printable US-ASCII, excluding backslash or quote.
if c == '\\' || c == '"' {

View File

@@ -218,3 +218,41 @@ func TestTCPClose(t *testing.T) {
t.Fatal(err)
}
}
func TestErrorNil(t *testing.T) {
c, err := Dial("tcp", "127.0.0.1:65535")
if err == nil {
t.Fatal("Dial 127.0.0.1:65535 succeeded")
}
if c != nil {
t.Fatalf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
}
// Make Listen fail by relistening on the same address.
l, err := Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal("Listen 127.0.0.1:0: %v", err)
}
defer l.Close()
l1, err := Listen("tcp", l.Addr().String())
if err == nil {
t.Fatal("second Listen %v: %v", l.Addr(), err)
}
if l1 != nil {
t.Fatalf("Listen returned non-nil interface %T(%v) with err != nil", l1, l1)
}
// Make ListenPacket fail by relistening on the same address.
lp, err := ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatal("Listen 127.0.0.1:0: %v", err)
}
defer lp.Close()
lp1, err := ListenPacket("udp", lp.LocalAddr().String())
if err == nil {
t.Fatal("second Listen %v: %v", lp.LocalAddr(), err)
}
if lp1 != nil {
t.Fatalf("ListenPacket returned non-nil interface %T(%v) with err != nil", lp1, lp1)
}
}

View File

@@ -54,7 +54,7 @@ func (f *file) readLine() (s string, ok bool) {
if n >= 0 {
f.data = f.data[0 : ln+n]
}
if err == io.EOF {
if err == io.EOF || err == io.ErrUnexpectedEOF {
f.atEOF = true
}
}

1
src/pkg/net/testdata/hosts_singleline vendored Normal file
View File

@@ -0,0 +1 @@
127.0.0.2 odin

View File

@@ -558,8 +558,8 @@ func parseQuery(m Values, query string) (err error) {
return err
}
// Encode encodes the values into ``URL encoded'' form.
// e.g. "foo=bar&bar=baz"
// Encode encodes the values into ``URL encoded'' form
// ("bar=baz&foo=quux") sorted by key.
func (v Values) Encode() string {
if v == nil {
return ""

View File

@@ -165,14 +165,11 @@ func (f *File) readdir(n int) (fi []FileInfo, err error) {
fi = make([]FileInfo, len(names))
for i, filename := range names {
fip, lerr := lstat(dirname + filename)
if lerr == nil {
fi[i] = fip
} else {
if lerr != nil {
fi[i] = &fileStat{name: filename}
if err == nil {
err = lerr
}
continue
}
fi[i] = fip
}
return fi, err
}

View File

@@ -92,8 +92,8 @@ func TestReaddirWithBadLstat(t *testing.T) {
defer func() { *LstatP = Lstat }()
dirs, err := handle.Readdir(-1)
if err != ErrInvalid {
t.Fatalf("Expected Readdir to return ErrInvalid, got %v", err)
if err != nil {
t.Fatalf("Expected Readdir to return no error, got %v", err)
}
foundfail := false
for _, dir := range dirs {

View File

@@ -255,10 +255,6 @@ runtime·MProf_Malloc(void *p, uintptr size)
uintptr stk[32];
Bucket *b;
if(m->nomemprof > 0)
return;
m->nomemprof++;
nstk = runtime·callers(1, stk, 32);
runtime·lock(&proflock);
b = stkbucket(MProf, stk, nstk, true);
@@ -266,7 +262,6 @@ runtime·MProf_Malloc(void *p, uintptr size)
b->recent_alloc_bytes += size;
setaddrbucket((uintptr)p, b);
runtime·unlock(&proflock);
m->nomemprof--;
}
// Called when freeing a profiled block.
@@ -275,10 +270,6 @@ runtime·MProf_Free(void *p, uintptr size)
{
Bucket *b;
if(m->nomemprof > 0)
return;
m->nomemprof++;
runtime·lock(&proflock);
b = getaddrbucket((uintptr)p);
if(b != nil) {
@@ -286,7 +277,6 @@ runtime·MProf_Free(void *p, uintptr size)
b->recent_free_bytes += size;
}
runtime·unlock(&proflock);
m->nomemprof--;
}
int64 runtime·blockprofilerate; // in CPU ticks

View File

@@ -8,6 +8,7 @@ import (
"bytes"
"fmt"
"hash/crc32"
"math/big"
"os/exec"
"regexp"
"runtime"
@@ -123,6 +124,10 @@ func testCPUProfile(t *testing.T, need []string, f func()) {
}
})
if len(need) == 0 {
return
}
var total uintptr
for i, name := range need {
total += have[i]
@@ -237,6 +242,26 @@ func TestGoroutineSwitch(t *testing.T) {
}
}
// Test that profiling of division operations is okay, especially on ARM. See issue 6681.
func TestMathBigDivide(t *testing.T) {
testCPUProfile(t, nil, func() {
t := time.After(5 * time.Second)
pi := new(big.Int)
for {
for i := 0; i < 100; i++ {
n := big.NewInt(2646693125139304345)
d := big.NewInt(842468587426513207)
pi.Div(n, d)
}
select {
case <-t:
return
default:
}
}
})
}
// Operating systems that are expected to fail the tests. See issue 6047.
var badOS = map[string]bool{
"darwin": true,

View File

@@ -133,7 +133,6 @@ runtime·schedinit(void)
runtime·sched.maxmcount = 10000;
runtime·precisestack = haveexperiment("precisestack");
m->nomemprof++;
runtime·mprofinit();
runtime·mallocinit();
mcommoninit(m);
@@ -163,7 +162,6 @@ runtime·schedinit(void)
procresize(procs);
mstats.enablegc = 1;
m->nomemprof--;
if(raceenabled)
g->racectx = runtime·raceinit();

View File

@@ -310,7 +310,6 @@ struct M
int32 throwing;
int32 gcing;
int32 locks;
int32 nomemprof;
int32 dying;
int32 profilehz;
int32 helpgc;

View File

@@ -255,7 +255,7 @@ runtime·newstack(void)
if(gp->stackguard0 == (uintptr)StackPreempt) {
if(gp == m->g0)
runtime·throw("runtime: preempt g0");
if(oldstatus == Grunning && m->p == nil)
if(oldstatus == Grunning && m->p == nil && m->locks == 0)
runtime·throw("runtime: g is running but p is not");
if(oldstatus == Gsyscall && m->locks == 0)
runtime·throw("runtime: stack split during syscall");

View File

@@ -84,7 +84,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.lr = 0;
flr = nil;
} else {
if(frame.lr == 0)
if((n == 0 && frame.sp < frame.fp) || frame.lr == 0)
frame.lr = *(uintptr*)frame.sp;
flr = runtime·findfunc(frame.lr);
if(flr == nil) {

View File

@@ -364,17 +364,18 @@ func makeSingleStringReplacer(pattern string, value string) *singleStringReplace
func (r *singleStringReplacer) Replace(s string) string {
var buf []byte
i := 0
i, matched := 0, false
for {
match := r.finder.next(s[i:])
if match == -1 {
break
}
matched = true
buf = append(buf, s[i:i+match]...)
buf = append(buf, r.value...)
i += match + len(r.finder.pattern)
}
if buf == nil {
if !matched {
return s
}
buf = append(buf, s[i:]...)

View File

@@ -261,10 +261,21 @@ func TestReplacer(t *testing.T) {
testCases = append(testCases,
testCase{abcMatcher, "", ""},
testCase{abcMatcher, "ab", "ab"},
testCase{abcMatcher, "abc", "[match]"},
testCase{abcMatcher, "abcd", "[match]d"},
testCase{abcMatcher, "cabcabcdabca", "c[match][match]d[match]a"},
)
// Issue 6659 cases (more single string replacer)
noHello := NewReplacer("Hello", "")
testCases = append(testCases,
testCase{noHello, "Hello", ""},
testCase{noHello, "Hellox", "x"},
testCase{noHello, "xHello", "x"},
testCase{noHello, "xHellox", "xx"},
)
// No-arg test cases.
nop := NewReplacer()

View File

@@ -18,4 +18,7 @@ func ForceUSPacificForTesting() {
localOnce.Do(initTestingZone)
}
var ParseTimeZone = parseTimeZone
var (
ForceZipFileForTesting = forceZipFileForTesting
ParseTimeZone = parseTimeZone
)

View File

@@ -1204,11 +1204,11 @@ func ParseDuration(s string) (Duration, error) {
if err != nil {
return 0, errors.New("time: invalid duration " + orig)
}
scale := 1
scale := 1.0
for n := pl - len(s); n > 0; n-- {
scale *= 10
}
g += float64(x) / float64(scale)
g += float64(x) / scale
post = pl != len(s)
}
if !pre && !post {

View File

@@ -578,6 +578,16 @@ func TestParseInSydney(t *testing.T) {
}
}
func TestLoadLocationZipFile(t *testing.T) {
ForceZipFileForTesting(true)
defer ForceZipFileForTesting(false)
_, err := LoadLocation("Australia/Sydney")
if err != nil {
t.Fatal(err)
}
}
var rubyTests = []ParseTest{
{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
// Ignore the time zone in the test. If it parses, it'll be OK.
@@ -1318,6 +1328,8 @@ var parseDurationTests = []struct {
{"39h9m14.425s", true, 39*Hour + 9*Minute + 14*Second + 425*Millisecond},
// large value
{"52763797000ns", true, 52763797000 * Nanosecond},
// more than 9 digits after decimal point, see http://golang.org/issue/6617
{"0.3333333333333333333h", true, 20 * Minute},
// errors
{"", false, 0},

View File

@@ -154,3 +154,7 @@ func loadLocation(name string) (*Location, error) {
}
return nil, errors.New("unknown time zone " + name)
}
func forceZipFileForTesting(zipOnly bool) {
// We only use the zip file anyway.
}

View File

@@ -32,7 +32,19 @@ var zoneDirs = []string{
"/usr/share/zoneinfo/",
"/usr/share/lib/zoneinfo/",
"/usr/lib/locale/TZ/",
runtime.GOROOT() + "/lib/time/zoneinfo/",
runtime.GOROOT() + "/lib/time/zoneinfo.zip",
}
var origZoneDirs = zoneDirs
func forceZipFileForTesting(zipOnly bool) {
zoneDirs = make([]string, len(origZoneDirs))
copy(zoneDirs, origZoneDirs)
if zipOnly {
for i := 0; i < len(zoneDirs)-1; i++ {
zoneDirs[i] = "/XXXNOEXIST"
}
}
}
func initLocal() {

View File

@@ -264,3 +264,7 @@ func loadLocation(name string) (*Location, error) {
}
return nil, errors.New("unknown time zone " + name)
}
func forceZipFileForTesting(zipOnly bool) {
// We only use the zip file anyway.
}

View File

@@ -13,17 +13,13 @@ import (
"fmt"
"math"
"time"
"syscall"
)
func main() {
// Test that NaNs in maps don't go quadratic.
t := func(n int) time.Duration {
var u0 syscall.Rusage
if err := syscall.Getrusage(0, &u0); err != nil {
panic(err)
}
t1 := time.Now()
m := map[float64]int{}
nan := math.NaN()
for i := 0; i < n; i++ {
@@ -32,11 +28,7 @@ func main() {
if len(m) != n {
panic("wrong size map after nan insertion")
}
var u1 syscall.Rusage
if err := syscall.Getrusage(0, &u1); err != nil {
panic(err)
}
return time.Duration(u1.Utime.Nano() - u0.Utime.Nano())
return time.Since(t1)
}
// Depending on the machine and OS, this test might be too fast