Commit d5363590 by Ian Lance Taylor

libgo: Update to weekly.2011-12-06.

From-SVN: r182338
parent ef0d4c4d
...@@ -41,16 +41,16 @@ func main() { ...@@ -41,16 +41,16 @@ func main() {
ok := true ok := true
for i := 0; i < len(tests); i++ { for i := 0; i < len(tests); i++ {
t := tests[i] t := tests[i]
v := strconv.Ftoa64(t.f, 'g', -1) v := strconv.FormatFloat(t.f, 'g', -1, 64)
if v != t.out { if v != t.out {
println("Bad float64 const:", t.in, "want", t.out, "got", v) println("Bad float64 const:", t.in, "want", t.out, "got", v)
x, err := strconv.Atof64(t.out) x, err := strconv.ParseFloat(t.out, 64)
if err != nil { if err != nil {
println("bug120: strconv.Atof64", t.out) println("bug120: strconv.Atof64", t.out)
panic("fail") panic("fail")
} }
println("\twant exact:", strconv.Ftoa64(x, 'g', 1000)) println("\twant exact:", strconv.FormatFloat(x, 'g', 1000, 64))
println("\tgot exact: ", strconv.Ftoa64(t.f, 'g', 1000)) println("\tgot exact: ", strconv.FormatFloat(t.f, 'g', 1000, 64))
ok = false ok = false
} }
} }
......
...@@ -24,8 +24,8 @@ func main() { ...@@ -24,8 +24,8 @@ func main() {
report := len(os.Args) > 1 report := len(os.Args) > 1
status := 0 status := 0
var b1 [10]T1 var b1 [10]T1
a0, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[0])[2:], 16) a0, _ := strconv.ParseUint(fmt.Sprintf("%p", &b1[0])[2:], 16, 64)
a1, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[1])[2:], 16) a1, _ := strconv.ParseUint(fmt.Sprintf("%p", &b1[1])[2:], 16, 64)
if a1 != a0+1 { if a1 != a0+1 {
fmt.Println("FAIL") fmt.Println("FAIL")
if report { if report {
...@@ -34,8 +34,8 @@ func main() { ...@@ -34,8 +34,8 @@ func main() {
status = 1 status = 1
} }
var b2 [10]T2 var b2 [10]T2
a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[0])[2:], 16) a0, _ = strconv.ParseUint(fmt.Sprintf("%p", &b2[0])[2:], 16, 64)
a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[1])[2:], 16) a1, _ = strconv.ParseUint(fmt.Sprintf("%p", &b2[1])[2:], 16, 64)
if a1 != a0+2 { if a1 != a0+2 {
if status == 0 { if status == 0 {
fmt.Println("FAIL") fmt.Println("FAIL")
...@@ -46,8 +46,8 @@ func main() { ...@@ -46,8 +46,8 @@ func main() {
} }
} }
var b4 [10]T4 var b4 [10]T4
a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[0])[2:], 16) a0, _ = strconv.ParseUint(fmt.Sprintf("%p", &b4[0])[2:], 16, 64)
a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[1])[2:], 16) a1, _ = strconv.ParseUint(fmt.Sprintf("%p", &b4[1])[2:], 16, 64)
if a1 != a0+4 { if a1 != a0+4 {
if status == 0 { if status == 0 {
fmt.Println("FAIL") fmt.Println("FAIL")
......
0beb796b4ef8 0c39eee85b0d
The first line of this file holds the Mercurial revision number of the The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources. last merge done from the master library sources.
...@@ -80,7 +80,7 @@ func (tr *Reader) octal(b []byte) int64 { ...@@ -80,7 +80,7 @@ func (tr *Reader) octal(b []byte) int64 {
for len(b) > 0 && (b[len(b)-1] == ' ' || b[len(b)-1] == '\x00') { for len(b) > 0 && (b[len(b)-1] == ' ' || b[len(b)-1] == '\x00') {
b = b[0 : len(b)-1] b = b[0 : len(b)-1]
} }
x, err := strconv.Btoui64(cString(b), 8) x, err := strconv.ParseUint(cString(b), 8, 64)
if err != nil { if err != nil {
tr.err = err tr.err = err
} }
......
...@@ -24,7 +24,7 @@ type untarTest struct { ...@@ -24,7 +24,7 @@ type untarTest struct {
var gnuTarTest = &untarTest{ var gnuTarTest = &untarTest{
file: "testdata/gnu.tar", file: "testdata/gnu.tar",
headers: []*Header{ headers: []*Header{
&Header{ {
Name: "small.txt", Name: "small.txt",
Mode: 0640, Mode: 0640,
Uid: 73025, Uid: 73025,
...@@ -35,7 +35,7 @@ var gnuTarTest = &untarTest{ ...@@ -35,7 +35,7 @@ var gnuTarTest = &untarTest{
Uname: "dsymonds", Uname: "dsymonds",
Gname: "eng", Gname: "eng",
}, },
&Header{ {
Name: "small2.txt", Name: "small2.txt",
Mode: 0640, Mode: 0640,
Uid: 73025, Uid: 73025,
...@@ -55,10 +55,10 @@ var gnuTarTest = &untarTest{ ...@@ -55,10 +55,10 @@ var gnuTarTest = &untarTest{
var untarTests = []*untarTest{ var untarTests = []*untarTest{
gnuTarTest, gnuTarTest,
&untarTest{ {
file: "testdata/star.tar", file: "testdata/star.tar",
headers: []*Header{ headers: []*Header{
&Header{ {
Name: "small.txt", Name: "small.txt",
Mode: 0640, Mode: 0640,
Uid: 73025, Uid: 73025,
...@@ -71,7 +71,7 @@ var untarTests = []*untarTest{ ...@@ -71,7 +71,7 @@ var untarTests = []*untarTest{
AccessTime: time.Unix(1244592783, 0), AccessTime: time.Unix(1244592783, 0),
ChangeTime: time.Unix(1244592783, 0), ChangeTime: time.Unix(1244592783, 0),
}, },
&Header{ {
Name: "small2.txt", Name: "small2.txt",
Mode: 0640, Mode: 0640,
Uid: 73025, Uid: 73025,
...@@ -86,10 +86,10 @@ var untarTests = []*untarTest{ ...@@ -86,10 +86,10 @@ var untarTests = []*untarTest{
}, },
}, },
}, },
&untarTest{ {
file: "testdata/v7.tar", file: "testdata/v7.tar",
headers: []*Header{ headers: []*Header{
&Header{ {
Name: "small.txt", Name: "small.txt",
Mode: 0444, Mode: 0444,
Uid: 73025, Uid: 73025,
...@@ -98,7 +98,7 @@ var untarTests = []*untarTest{ ...@@ -98,7 +98,7 @@ var untarTests = []*untarTest{
ModTime: time.Unix(1244593104, 0), ModTime: time.Unix(1244593104, 0),
Typeflag: '\x00', Typeflag: '\x00',
}, },
&Header{ {
Name: "small2.txt", Name: "small2.txt",
Mode: 0444, Mode: 0444,
Uid: 73025, Uid: 73025,
......
...@@ -79,7 +79,7 @@ func (tw *Writer) cString(b []byte, s string) { ...@@ -79,7 +79,7 @@ func (tw *Writer) cString(b []byte, s string) {
// Encode x as an octal ASCII string and write it into b with leading zeros. // Encode x as an octal ASCII string and write it into b with leading zeros.
func (tw *Writer) octal(b []byte, x int64) { func (tw *Writer) octal(b []byte, x int64) {
s := strconv.Itob64(x, 8) s := strconv.FormatInt(x, 8)
// leading zeros, but leave room for a NUL. // leading zeros, but leave room for a NUL.
for len(s)+1 < len(b) { for len(s)+1 < len(b) {
s = "0" + s s = "0" + s
...@@ -90,7 +90,7 @@ func (tw *Writer) octal(b []byte, x int64) { ...@@ -90,7 +90,7 @@ func (tw *Writer) octal(b []byte, x int64) {
// Write x into b, either as octal or as binary (GNUtar/star extension). // Write x into b, either as octal or as binary (GNUtar/star extension).
func (tw *Writer) numeric(b []byte, x int64) { func (tw *Writer) numeric(b []byte, x int64) {
// Try octal first. // Try octal first.
s := strconv.Itob64(x, 8) s := strconv.FormatInt(x, 8)
if len(s) < len(b) { if len(s) < len(b) {
tw.octal(b, x) tw.octal(b, x)
return return
......
...@@ -29,10 +29,10 @@ var writerTests = []*writerTest{ ...@@ -29,10 +29,10 @@ var writerTests = []*writerTest{
// tar (GNU tar) 1.26 // tar (GNU tar) 1.26
// ln -s small.txt link.txt // ln -s small.txt link.txt
// tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt // tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
&writerTest{ {
file: "testdata/writer.tar", file: "testdata/writer.tar",
entries: []*writerTestEntry{ entries: []*writerTestEntry{
&writerTestEntry{ {
header: &Header{ header: &Header{
Name: "small.txt", Name: "small.txt",
Mode: 0640, Mode: 0640,
...@@ -46,7 +46,7 @@ var writerTests = []*writerTest{ ...@@ -46,7 +46,7 @@ var writerTests = []*writerTest{
}, },
contents: "Kilts", contents: "Kilts",
}, },
&writerTestEntry{ {
header: &Header{ header: &Header{
Name: "small2.txt", Name: "small2.txt",
Mode: 0640, Mode: 0640,
...@@ -60,7 +60,7 @@ var writerTests = []*writerTest{ ...@@ -60,7 +60,7 @@ var writerTests = []*writerTest{
}, },
contents: "Google.com\n", contents: "Google.com\n",
}, },
&writerTestEntry{ {
header: &Header{ header: &Header{
Name: "link.txt", Name: "link.txt",
Mode: 0777, Mode: 0777,
...@@ -80,10 +80,10 @@ var writerTests = []*writerTest{ ...@@ -80,10 +80,10 @@ var writerTests = []*writerTest{
// The truncated test file was produced using these commands: // The truncated test file was produced using these commands:
// dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt // dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
// tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar // tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
&writerTest{ {
file: "testdata/writer-big.tar", file: "testdata/writer-big.tar",
entries: []*writerTestEntry{ entries: []*writerTestEntry{
&writerTestEntry{ {
header: &Header{ header: &Header{
Name: "tmp/16gig.txt", Name: "tmp/16gig.txt",
Mode: 0640, Mode: 0640,
......
...@@ -21,12 +21,12 @@ type WriteTest struct { ...@@ -21,12 +21,12 @@ type WriteTest struct {
} }
var writeTests = []WriteTest{ var writeTests = []WriteTest{
WriteTest{ {
Name: "foo", Name: "foo",
Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."), Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."),
Method: Store, Method: Store,
}, },
WriteTest{ {
Name: "bar", Name: "bar",
Data: nil, // large data set in the test Data: nil, // large data set in the test
Method: Deflate, Method: Deflate,
......
...@@ -20,7 +20,7 @@ type bitReader struct { ...@@ -20,7 +20,7 @@ type bitReader struct {
err error err error
} }
// bitReader needs to read bytes from an io.Reader. We attempt to cast the // bitReader needs to read bytes from an io.Reader. We attempt to convert the
// given io.Reader to this interface and, if it doesn't already fit, we wrap in // given io.Reader to this interface and, if it doesn't already fit, we wrap in
// a bufio.Reader. // a bufio.Reader.
type byteReader interface { type byteReader interface {
......
...@@ -30,44 +30,44 @@ type reverseBitsTest struct { ...@@ -30,44 +30,44 @@ type reverseBitsTest struct {
} }
var deflateTests = []*deflateTest{ var deflateTests = []*deflateTest{
&deflateTest{[]byte{}, 0, []byte{1, 0, 0, 255, 255}}, {[]byte{}, 0, []byte{1, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}}, {[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}}, {[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}}, {[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}}, {[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}}, {[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0, {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
[]byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255}, []byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255},
}, },
&deflateTest{[]byte{}, 1, []byte{1, 0, 0, 255, 255}}, {[]byte{}, 1, []byte{1, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11}, 1, []byte{18, 4, 4, 0, 0, 255, 255}}, {[]byte{0x11}, 1, []byte{18, 4, 4, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11, 0x12}, 1, []byte{18, 20, 2, 4, 0, 0, 255, 255}}, {[]byte{0x11, 0x12}, 1, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 1, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}}, {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 1, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
&deflateTest{[]byte{}, 9, []byte{1, 0, 0, 255, 255}}, {[]byte{}, 9, []byte{1, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}}, {[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}}, {[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
&deflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}}, {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
} }
var deflateInflateTests = []*deflateInflateTest{ var deflateInflateTests = []*deflateInflateTest{
&deflateInflateTest{[]byte{}}, {[]byte{}},
&deflateInflateTest{[]byte{0x11}}, {[]byte{0x11}},
&deflateInflateTest{[]byte{0x11, 0x12}}, {[]byte{0x11, 0x12}},
&deflateInflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}}, {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
&deflateInflateTest{[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}}, {[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
&deflateInflateTest{largeDataChunk()}, {largeDataChunk()},
} }
var reverseBitsTests = []*reverseBitsTest{ var reverseBitsTests = []*reverseBitsTest{
&reverseBitsTest{1, 1, 1}, {1, 1, 1},
&reverseBitsTest{1, 2, 2}, {1, 2, 2},
&reverseBitsTest{1, 3, 4}, {1, 3, 4},
&reverseBitsTest{1, 4, 8}, {1, 4, 8},
&reverseBitsTest{1, 5, 16}, {1, 5, 16},
&reverseBitsTest{17, 5, 17}, {17, 5, 17},
&reverseBitsTest{257, 9, 257}, {257, 9, 257},
&reverseBitsTest{29, 5, 23}, {29, 5, 23},
} }
func largeDataChunk() []byte { func largeDataChunk() []byte {
......
...@@ -52,7 +52,7 @@ type InitDecoderTest struct { ...@@ -52,7 +52,7 @@ type InitDecoderTest struct {
var initDecoderTests = []*InitDecoderTest{ var initDecoderTests = []*InitDecoderTest{
// Example from Connell 1973, // Example from Connell 1973,
&InitDecoderTest{ {
[]int{3, 5, 2, 4, 3, 5, 5, 4, 4, 3, 4, 5}, []int{3, 5, 2, 4, 3, 5, 5, 4, 4, 3, 4, 5},
huffmanDecoder{ huffmanDecoder{
2, 5, 2, 5,
...@@ -68,7 +68,7 @@ var initDecoderTests = []*InitDecoderTest{ ...@@ -68,7 +68,7 @@ var initDecoderTests = []*InitDecoderTest{
}, },
// Example from RFC 1951 section 3.2.2 // Example from RFC 1951 section 3.2.2
&InitDecoderTest{ {
[]int{2, 1, 3, 3}, []int{2, 1, 3, 3},
huffmanDecoder{ huffmanDecoder{
1, 3, 1, 3,
...@@ -80,7 +80,7 @@ var initDecoderTests = []*InitDecoderTest{ ...@@ -80,7 +80,7 @@ var initDecoderTests = []*InitDecoderTest{
}, },
// Second example from RFC 1951 section 3.2.2 // Second example from RFC 1951 section 3.2.2
&InitDecoderTest{ {
[]int{3, 3, 3, 3, 3, 2, 4, 4}, []int{3, 3, 3, 3, 3, 2, 4, 4},
huffmanDecoder{ huffmanDecoder{
2, 4, 2, 4,
...@@ -92,21 +92,21 @@ var initDecoderTests = []*InitDecoderTest{ ...@@ -92,21 +92,21 @@ var initDecoderTests = []*InitDecoderTest{
}, },
// Static Huffman codes (RFC 1951 section 3.2.6) // Static Huffman codes (RFC 1951 section 3.2.6)
&InitDecoderTest{ {
fixedHuffmanBits[0:], fixedHuffmanBits[0:],
fixedHuffmanDecoder, fixedHuffmanDecoder,
true, true,
}, },
// Illegal input. // Illegal input.
&InitDecoderTest{ {
[]int{}, []int{},
huffmanDecoder{}, huffmanDecoder{},
false, false,
}, },
// Illegal input. // Illegal input.
&InitDecoderTest{ {
[]int{0, 0, 0, 0, 0, 0, 0}, []int{0, 0, 0, 0, 0, 0, 0},
huffmanDecoder{}, huffmanDecoder{},
false, false,
......
...@@ -106,8 +106,8 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter { ...@@ -106,8 +106,8 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
} }
func (err WrongValueError) Error() string { func (err WrongValueError) Error() string {
return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.Itoa64(int64(err.from)) + ";" + return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.FormatInt(int64(err.from), 10) + ";" +
strconv.Itoa64(int64(err.to)) + "] but actual value is " + strconv.Itoa64(int64(err.value)) strconv.FormatInt(int64(err.to), 10) + "] but actual value is " + strconv.FormatInt(int64(err.value), 10)
} }
func (w *huffmanBitWriter) flushBits() { func (w *huffmanBitWriter) flushBits() {
......
...@@ -25,7 +25,7 @@ const ( ...@@ -25,7 +25,7 @@ const (
type CorruptInputError int64 type CorruptInputError int64
func (e CorruptInputError) Error() string { func (e CorruptInputError) Error() string {
return "flate: corrupt input before offset " + strconv.Itoa64(int64(e)) return "flate: corrupt input before offset " + strconv.FormatInt(int64(e), 10)
} }
// An InternalError reports an error in the flate code itself. // An InternalError reports an error in the flate code itself.
...@@ -40,7 +40,7 @@ type ReadError struct { ...@@ -40,7 +40,7 @@ type ReadError struct {
} }
func (e *ReadError) Error() string { func (e *ReadError) Error() string {
return "flate: read error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Err.Error() return "flate: read error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
} }
// A WriteError reports an error encountered while writing output. // A WriteError reports an error encountered while writing output.
...@@ -50,7 +50,7 @@ type WriteError struct { ...@@ -50,7 +50,7 @@ type WriteError struct {
} }
func (e *WriteError) Error() string { func (e *WriteError) Error() string {
return "flate: write error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Err.Error() return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
} }
// Huffman decoder is based on // Huffman decoder is based on
......
...@@ -348,3 +348,17 @@ func TestCipherDecrypt(t *testing.T) { ...@@ -348,3 +348,17 @@ func TestCipherDecrypt(t *testing.T) {
} }
} }
} }
func BenchmarkEncrypt(b *testing.B) {
b.StopTimer()
tt := encryptTests[0]
c, err := NewCipher(tt.key)
if err != nil {
panic("NewCipher")
}
out := make([]byte, len(tt.in))
b.StartTimer()
for i := 0; i < b.N; i++ {
c.Encrypt(out, tt.in)
}
}
...@@ -56,10 +56,10 @@ func encryptBlock(xk []uint32, dst, src []byte) { ...@@ -56,10 +56,10 @@ func encryptBlock(xk []uint32, dst, src []byte) {
nr := len(xk)/4 - 2 // - 2: one above, one more below nr := len(xk)/4 - 2 // - 2: one above, one more below
k := 4 k := 4
for r := 0; r < nr; r++ { for r := 0; r < nr; r++ {
t0 = xk[k+0] ^ te[0][s0>>24] ^ te[1][s1>>16&0xff] ^ te[2][s2>>8&0xff] ^ te[3][s3&0xff] t0 = xk[k+0] ^ te[0][uint8(s0>>24)] ^ te[1][uint8(s1>>16)] ^ te[2][uint8(s2>>8)] ^ te[3][uint8(s3)]
t1 = xk[k+1] ^ te[0][s1>>24] ^ te[1][s2>>16&0xff] ^ te[2][s3>>8&0xff] ^ te[3][s0&0xff] t1 = xk[k+1] ^ te[0][uint8(s1>>24)] ^ te[1][uint8(s2>>16)] ^ te[2][uint8(s3>>8)] ^ te[3][uint8(s0)]
t2 = xk[k+2] ^ te[0][s2>>24] ^ te[1][s3>>16&0xff] ^ te[2][s0>>8&0xff] ^ te[3][s1&0xff] t2 = xk[k+2] ^ te[0][uint8(s2>>24)] ^ te[1][uint8(s3>>16)] ^ te[2][uint8(s0>>8)] ^ te[3][uint8(s1)]
t3 = xk[k+3] ^ te[0][s3>>24] ^ te[1][s0>>16&0xff] ^ te[2][s1>>8&0xff] ^ te[3][s2&0xff] t3 = xk[k+3] ^ te[0][uint8(s3>>24)] ^ te[1][uint8(s0>>16)] ^ te[2][uint8(s1>>8)] ^ te[3][uint8(s2)]
k += 4 k += 4
s0, s1, s2, s3 = t0, t1, t2, t3 s0, s1, s2, s3 = t0, t1, t2, t3
} }
...@@ -101,10 +101,10 @@ func decryptBlock(xk []uint32, dst, src []byte) { ...@@ -101,10 +101,10 @@ func decryptBlock(xk []uint32, dst, src []byte) {
nr := len(xk)/4 - 2 // - 2: one above, one more below nr := len(xk)/4 - 2 // - 2: one above, one more below
k := 4 k := 4
for r := 0; r < nr; r++ { for r := 0; r < nr; r++ {
t0 = xk[k+0] ^ td[0][s0>>24] ^ td[1][s3>>16&0xff] ^ td[2][s2>>8&0xff] ^ td[3][s1&0xff] t0 = xk[k+0] ^ td[0][uint8(s0>>24)] ^ td[1][uint8(s3>>16)] ^ td[2][uint8(s2>>8)] ^ td[3][uint8(s1)]
t1 = xk[k+1] ^ td[0][s1>>24] ^ td[1][s0>>16&0xff] ^ td[2][s3>>8&0xff] ^ td[3][s2&0xff] t1 = xk[k+1] ^ td[0][uint8(s1>>24)] ^ td[1][uint8(s0>>16)] ^ td[2][uint8(s3>>8)] ^ td[3][uint8(s2)]
t2 = xk[k+2] ^ td[0][s2>>24] ^ td[1][s1>>16&0xff] ^ td[2][s0>>8&0xff] ^ td[3][s3&0xff] t2 = xk[k+2] ^ td[0][uint8(s2>>24)] ^ td[1][uint8(s1>>16)] ^ td[2][uint8(s0>>8)] ^ td[3][uint8(s3)]
t3 = xk[k+3] ^ td[0][s3>>24] ^ td[1][s2>>16&0xff] ^ td[2][s1>>8&0xff] ^ td[3][s0&0xff] t3 = xk[k+3] ^ td[0][uint8(s3>>24)] ^ td[1][uint8(s2>>16)] ^ td[2][uint8(s1>>8)] ^ td[3][uint8(s0)]
k += 4 k += 4
s0, s1, s2, s3 = t0, t1, t2, t3 s0, s1, s2, s3 = t0, t1, t2, t3
} }
......
...@@ -49,14 +49,13 @@ func (h *hmac) tmpPad(xor byte) { ...@@ -49,14 +49,13 @@ func (h *hmac) tmpPad(xor byte) {
} }
func (h *hmac) Sum(in []byte) []byte { func (h *hmac) Sum(in []byte) []byte {
sum := h.inner.Sum(nil) origLen := len(in)
in = h.inner.Sum(in)
h.tmpPad(0x5c) h.tmpPad(0x5c)
for i, b := range sum { copy(h.tmp[padSize:], in[origLen:])
h.tmp[padSize+i] = b
}
h.outer.Reset() h.outer.Reset()
h.outer.Write(h.tmp) h.outer.Write(h.tmp)
return h.outer.Sum(in) return h.outer.Sum(in[:origLen])
} }
func (h *hmac) Write(p []byte) (n int, err error) { func (h *hmac) Write(p []byte) (n int, err error) {
......
...@@ -79,8 +79,7 @@ func (d *digest) Write(p []byte) (nn int, err error) { ...@@ -79,8 +79,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
func (d0 *digest) Sum(in []byte) []byte { func (d0 *digest) Sum(in []byte) []byte {
// Make a copy of d0 so that caller can keep writing and summing. // Make a copy of d0 so that caller can keep writing and summing.
d := new(digest) d := *d0
*d = *d0
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
len := d.len len := d.len
...@@ -103,11 +102,13 @@ func (d0 *digest) Sum(in []byte) []byte { ...@@ -103,11 +102,13 @@ func (d0 *digest) Sum(in []byte) []byte {
panic("d.nx != 0") panic("d.nx != 0")
} }
for _, s := range d.s { var digest [Size]byte
in = append(in, byte(s>>0)) for i, s := range d.s {
in = append(in, byte(s>>8)) digest[i*4] = byte(s)
in = append(in, byte(s>>16)) digest[i*4+1] = byte(s >> 8)
in = append(in, byte(s>>24)) digest[i*4+2] = byte(s >> 16)
digest[i*4+3] = byte(s >> 24)
} }
return in
return append(in, digest[:]...)
} }
...@@ -26,6 +26,7 @@ var zero [1]byte ...@@ -26,6 +26,7 @@ var zero [1]byte
// 4880, section 3.7.1.2) using the given hash, input passphrase and salt. // 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
done := 0 done := 0
var digest []byte
for i := 0; done < len(out); i++ { for i := 0; done < len(out); i++ {
h.Reset() h.Reset()
...@@ -34,7 +35,8 @@ func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { ...@@ -34,7 +35,8 @@ func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
} }
h.Write(salt) h.Write(salt)
h.Write(in) h.Write(in)
n := copy(out[done:], h.Sum(nil)) digest = h.Sum(digest[:0])
n := copy(out[done:], digest)
done += n done += n
} }
} }
...@@ -52,6 +54,7 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { ...@@ -52,6 +54,7 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
} }
done := 0 done := 0
var digest []byte
for i := 0; done < len(out); i++ { for i := 0; done < len(out); i++ {
h.Reset() h.Reset()
for j := 0; j < i; j++ { for j := 0; j < i; j++ {
...@@ -68,7 +71,8 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { ...@@ -68,7 +71,8 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
written += len(combined) written += len(combined)
} }
} }
n := copy(out[done:], h.Sum(nil)) digest = h.Sum(digest[:0])
n := copy(out[done:], digest)
done += n done += n
} }
} }
......
...@@ -183,7 +183,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint ...@@ -183,7 +183,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
for i := range to { for i := range to {
encryptKeys[i] = to[i].encryptionKey() encryptKeys[i] = to[i].encryptionKey()
if encryptKeys[i].PublicKey == nil { if encryptKeys[i].PublicKey == nil {
return nil, error_.InvalidArgumentError("cannot encrypt a message to key id " + strconv.Uitob64(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") return nil, error_.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
} }
sig := to[i].primaryIdentity().SelfSignature sig := to[i].primaryIdentity().SelfSignature
......
...@@ -83,8 +83,7 @@ func (d *digest) Write(p []byte) (nn int, err error) { ...@@ -83,8 +83,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
func (d0 *digest) Sum(in []byte) []byte { func (d0 *digest) Sum(in []byte) []byte {
// Make a copy of d0 so that caller can keep writing and summing. // Make a copy of d0 so that caller can keep writing and summing.
d := new(digest) d := *d0
*d = *d0
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
tc := d.tc tc := d.tc
...@@ -107,11 +106,13 @@ func (d0 *digest) Sum(in []byte) []byte { ...@@ -107,11 +106,13 @@ func (d0 *digest) Sum(in []byte) []byte {
panic("d.nx != 0") panic("d.nx != 0")
} }
for _, s := range d.s { var digest [Size]byte
in = append(in, byte(s)) for i, s := range d.s {
in = append(in, byte(s>>8)) digest[i*4] = byte(s)
in = append(in, byte(s>>16)) digest[i*4+1] = byte(s >> 8)
in = append(in, byte(s>>24)) digest[i*4+2] = byte(s >> 16)
digest[i*4+3] = byte(s >> 24)
} }
return in
return append(in, digest[:]...)
} }
...@@ -189,12 +189,13 @@ func incCounter(c *[4]byte) { ...@@ -189,12 +189,13 @@ func incCounter(c *[4]byte) {
// specified in PKCS#1 v2.1. // specified in PKCS#1 v2.1.
func mgf1XOR(out []byte, hash hash.Hash, seed []byte) { func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
var counter [4]byte var counter [4]byte
var digest []byte
done := 0 done := 0
for done < len(out) { for done < len(out) {
hash.Write(seed) hash.Write(seed)
hash.Write(counter[0:4]) hash.Write(counter[0:4])
digest := hash.Sum(nil) digest = hash.Sum(digest[:0])
hash.Reset() hash.Reset()
for i := 0; i < len(digest) && done < len(out); i++ { for i := 0; i < len(digest) && done < len(out); i++ {
......
...@@ -81,8 +81,7 @@ func (d *digest) Write(p []byte) (nn int, err error) { ...@@ -81,8 +81,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
func (d0 *digest) Sum(in []byte) []byte { func (d0 *digest) Sum(in []byte) []byte {
// Make a copy of d0 so that caller can keep writing and summing. // Make a copy of d0 so that caller can keep writing and summing.
d := new(digest) d := *d0
*d = *d0
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
len := d.len len := d.len
...@@ -105,11 +104,13 @@ func (d0 *digest) Sum(in []byte) []byte { ...@@ -105,11 +104,13 @@ func (d0 *digest) Sum(in []byte) []byte {
panic("d.nx != 0") panic("d.nx != 0")
} }
for _, s := range d.h { var digest [Size]byte
in = append(in, byte(s>>24)) for i, s := range d.h {
in = append(in, byte(s>>16)) digest[i*4] = byte(s >> 24)
in = append(in, byte(s>>8)) digest[i*4+1] = byte(s >> 16)
in = append(in, byte(s)) digest[i*4+2] = byte(s >> 8)
digest[i*4+3] = byte(s)
} }
return in
return append(in, digest[:]...)
} }
...@@ -125,8 +125,7 @@ func (d *digest) Write(p []byte) (nn int, err error) { ...@@ -125,8 +125,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
func (d0 *digest) Sum(in []byte) []byte { func (d0 *digest) Sum(in []byte) []byte {
// Make a copy of d0 so that caller can keep writing and summing. // Make a copy of d0 so that caller can keep writing and summing.
d := new(digest) d := *d0
*d = *d0
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
len := d.len len := d.len
...@@ -150,14 +149,19 @@ func (d0 *digest) Sum(in []byte) []byte { ...@@ -150,14 +149,19 @@ func (d0 *digest) Sum(in []byte) []byte {
} }
h := d.h[:] h := d.h[:]
size := Size
if d.is224 { if d.is224 {
h = d.h[:7] h = d.h[:7]
size = Size224
} }
for _, s := range h {
in = append(in, byte(s>>24)) var digest [Size]byte
in = append(in, byte(s>>16)) for i, s := range h {
in = append(in, byte(s>>8)) digest[i*4] = byte(s >> 24)
in = append(in, byte(s)) digest[i*4+1] = byte(s >> 16)
digest[i*4+2] = byte(s >> 8)
digest[i*4+3] = byte(s)
} }
return in
return append(in, digest[:size]...)
} }
...@@ -150,18 +150,23 @@ func (d0 *digest) Sum(in []byte) []byte { ...@@ -150,18 +150,23 @@ func (d0 *digest) Sum(in []byte) []byte {
} }
h := d.h[:] h := d.h[:]
size := Size
if d.is384 { if d.is384 {
h = d.h[:6] h = d.h[:6]
size = Size384
} }
for _, s := range h {
in = append(in, byte(s>>56)) var digest [Size]byte
in = append(in, byte(s>>48)) for i, s := range h {
in = append(in, byte(s>>40)) digest[i*8] = byte(s >> 56)
in = append(in, byte(s>>32)) digest[i*8+1] = byte(s >> 48)
in = append(in, byte(s>>24)) digest[i*8+2] = byte(s >> 40)
in = append(in, byte(s>>16)) digest[i*8+3] = byte(s >> 32)
in = append(in, byte(s>>8)) digest[i*8+4] = byte(s >> 24)
in = append(in, byte(s)) digest[i*8+5] = byte(s >> 16)
digest[i*8+6] = byte(s >> 8)
digest[i*8+7] = byte(s)
} }
return in
return append(in, digest[:size]...)
} }
...@@ -52,12 +52,12 @@ type cipherSuite struct { ...@@ -52,12 +52,12 @@ type cipherSuite struct {
} }
var cipherSuites = []*cipherSuite{ var cipherSuites = []*cipherSuite{
&cipherSuite{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1}, {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
&cipherSuite{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, false, cipher3DES, macSHA1}, {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, false, cipher3DES, macSHA1},
&cipherSuite{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1}, {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
&cipherSuite{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1}, {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
&cipherSuite{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1}, {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1},
&cipherSuite{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
} }
func cipherRC4(key, iv []byte, isRead bool) interface{} { func cipherRC4(key, iv []byte, isRead bool) interface{} {
...@@ -96,7 +96,7 @@ func macSHA1(version uint16, key []byte) macFunction { ...@@ -96,7 +96,7 @@ func macSHA1(version uint16, key []byte) macFunction {
type macFunction interface { type macFunction interface {
Size() int Size() int
MAC(seq, data []byte) []byte MAC(digestBuf, seq, data []byte) []byte
} }
// ssl30MAC implements the SSLv3 MAC function, as defined in // ssl30MAC implements the SSLv3 MAC function, as defined in
...@@ -114,7 +114,7 @@ var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0 ...@@ -114,7 +114,7 @@ var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0
var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c} var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
func (s ssl30MAC) MAC(seq, record []byte) []byte { func (s ssl30MAC) MAC(digestBuf, seq, record []byte) []byte {
padLength := 48 padLength := 48
if s.h.Size() == 20 { if s.h.Size() == 20 {
padLength = 40 padLength = 40
...@@ -127,13 +127,13 @@ func (s ssl30MAC) MAC(seq, record []byte) []byte { ...@@ -127,13 +127,13 @@ func (s ssl30MAC) MAC(seq, record []byte) []byte {
s.h.Write(record[:1]) s.h.Write(record[:1])
s.h.Write(record[3:5]) s.h.Write(record[3:5])
s.h.Write(record[recordHeaderLen:]) s.h.Write(record[recordHeaderLen:])
digest := s.h.Sum(nil) digestBuf = s.h.Sum(digestBuf[:0])
s.h.Reset() s.h.Reset()
s.h.Write(s.key) s.h.Write(s.key)
s.h.Write(ssl30Pad2[:padLength]) s.h.Write(ssl30Pad2[:padLength])
s.h.Write(digest) s.h.Write(digestBuf)
return s.h.Sum(nil) return s.h.Sum(digestBuf[:0])
} }
// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3. // tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
...@@ -145,11 +145,11 @@ func (s tls10MAC) Size() int { ...@@ -145,11 +145,11 @@ func (s tls10MAC) Size() int {
return s.h.Size() return s.h.Size()
} }
func (s tls10MAC) MAC(seq, record []byte) []byte { func (s tls10MAC) MAC(digestBuf, seq, record []byte) []byte {
s.h.Reset() s.h.Reset()
s.h.Write(seq) s.h.Write(seq)
s.h.Write(record) s.h.Write(record)
return s.h.Sum(nil) return s.h.Sum(digestBuf[:0])
} }
func rsaKA() keyAgreement { func rsaKA() keyAgreement {
......
...@@ -118,6 +118,9 @@ type halfConn struct { ...@@ -118,6 +118,9 @@ type halfConn struct {
nextCipher interface{} // next encryption state nextCipher interface{} // next encryption state
nextMac macFunction // next MAC algorithm nextMac macFunction // next MAC algorithm
// used to save allocating a new buffer for each MAC.
inDigestBuf, outDigestBuf []byte
} }
// prepareCipherSpec sets the encryption and MAC states // prepareCipherSpec sets the encryption and MAC states
...@@ -280,12 +283,13 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) { ...@@ -280,12 +283,13 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
b.data[4] = byte(n) b.data[4] = byte(n)
b.resize(recordHeaderLen + n) b.resize(recordHeaderLen + n)
remoteMAC := payload[n:] remoteMAC := payload[n:]
localMAC := hc.mac.MAC(hc.seq[0:], b.data) localMAC := hc.mac.MAC(hc.inDigestBuf, hc.seq[0:], b.data)
hc.incSeq() hc.incSeq()
if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 { if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
return false, alertBadRecordMAC return false, alertBadRecordMAC
} }
hc.inDigestBuf = localMAC
} }
return true, 0 return true, 0
...@@ -312,12 +316,13 @@ func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) { ...@@ -312,12 +316,13 @@ func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
func (hc *halfConn) encrypt(b *block) (bool, alert) { func (hc *halfConn) encrypt(b *block) (bool, alert) {
// mac // mac
if hc.mac != nil { if hc.mac != nil {
mac := hc.mac.MAC(hc.seq[0:], b.data) mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data)
hc.incSeq() hc.incSeq()
n := len(b.data) n := len(b.data)
b.resize(n + len(mac)) b.resize(n + len(mac))
copy(b.data[n:], mac) copy(b.data[n:], mac)
hc.outDigestBuf = mac
} }
payload := b.data[recordHeaderLen:] payload := b.data[recordHeaderLen:]
......
...@@ -231,10 +231,10 @@ func (c *Conn) clientHandshake() error { ...@@ -231,10 +231,10 @@ func (c *Conn) clientHandshake() error {
if cert != nil { if cert != nil {
certVerify := new(certificateVerifyMsg) certVerify := new(certificateVerifyMsg)
var digest [36]byte digest := make([]byte, 0, 36)
copy(digest[0:16], finishedHash.serverMD5.Sum(nil)) digest = finishedHash.serverMD5.Sum(digest)
copy(digest[16:36], finishedHash.serverSHA1.Sum(nil)) digest = finishedHash.serverSHA1.Sum(digest)
signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, crypto.MD5SHA1, digest[0:]) signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, crypto.MD5SHA1, digest)
if err != nil { if err != nil {
return c.sendAlert(alertInternalError) return c.sendAlert(alertInternalError)
} }
......
...@@ -234,9 +234,9 @@ FindCipherSuite: ...@@ -234,9 +234,9 @@ FindCipherSuite:
return c.sendAlert(alertUnexpectedMessage) return c.sendAlert(alertUnexpectedMessage)
} }
digest := make([]byte, 36) digest := make([]byte, 0, 36)
copy(digest[0:16], finishedHash.serverMD5.Sum(nil)) digest = finishedHash.serverMD5.Sum(digest)
copy(digest[16:36], finishedHash.serverSHA1.Sum(nil)) digest = finishedHash.serverSHA1.Sum(digest)
err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature) err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
if err != nil { if err != nil {
c.sendAlert(alertBadCertificate) c.sendAlert(alertBadCertificate)
......
...@@ -159,7 +159,7 @@ func TestHandshakeServerSSLv3(t *testing.T) { ...@@ -159,7 +159,7 @@ func TestHandshakeServerSSLv3(t *testing.T) {
var serve = flag.Bool("serve", false, "run a TLS server on :10443") var serve = flag.Bool("serve", false, "run a TLS server on :10443")
var testCipherSuites = flag.String("ciphersuites", var testCipherSuites = flag.String("ciphersuites",
"0x"+strconv.Itob(int(TLS_RSA_WITH_RC4_128_SHA), 16), "0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16),
"cipher suites to accept in serving mode") "cipher suites to accept in serving mode")
func TestRunServer(t *testing.T) { func TestRunServer(t *testing.T) {
...@@ -170,7 +170,7 @@ func TestRunServer(t *testing.T) { ...@@ -170,7 +170,7 @@ func TestRunServer(t *testing.T) {
suites := strings.Split(*testCipherSuites, ",") suites := strings.Split(*testCipherSuites, ",")
testConfig.CipherSuites = make([]uint16, len(suites)) testConfig.CipherSuites = make([]uint16, len(suites))
for i := range suites { for i := range suites {
suite, err := strconv.Btoui64(suites[i], 0) suite, err := strconv.ParseUint(suites[i], 0, 64)
if err != nil { if err != nil {
panic(err) panic(err)
} }
......
...@@ -927,10 +927,15 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P ...@@ -927,10 +927,15 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
return return
} }
asn1Issuer, err := asn1.Marshal(parent.Subject.ToRDNSequence()) var asn1Issuer []byte
if err != nil { if len(parent.RawSubject) > 0 {
return asn1Issuer = parent.RawSubject
} else {
if asn1Issuer, err = asn1.Marshal(parent.Subject.ToRDNSequence()); err != nil {
return
}
} }
asn1Subject, err := asn1.Marshal(template.Subject.ToRDNSequence()) asn1Subject, err := asn1.Marshal(template.Subject.ToRDNSequence())
if err != nil { if err != nil {
return return
......
...@@ -149,5 +149,5 @@ type DecodeError struct { ...@@ -149,5 +149,5 @@ type DecodeError struct {
} }
func (e DecodeError) Error() string { func (e DecodeError) Error() string {
return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.Itob64(int64(e.Offset), 16) + ": " + e.Err return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err
} }
...@@ -178,7 +178,7 @@ func (a Attr) GoString() string { ...@@ -178,7 +178,7 @@ func (a Attr) GoString() string {
return "dwarf.Attr" + s return "dwarf.Attr" + s
} }
} }
return "dwarf.Attr(" + strconv.Itoa64(int64(a)) + ")" return "dwarf.Attr(" + strconv.FormatInt(int64(a), 10) + ")"
} }
// A format is a DWARF data encoding format. // A format is a DWARF data encoding format.
...@@ -347,7 +347,7 @@ func (t Tag) GoString() string { ...@@ -347,7 +347,7 @@ func (t Tag) GoString() string {
return "dwarf.Tag" + s return "dwarf.Tag" + s
} }
} }
return "dwarf.Tag(" + strconv.Itoa64(int64(t)) + ")" return "dwarf.Tag(" + strconv.FormatInt(int64(t), 10) + ")"
} }
// Location expression operators. // Location expression operators.
......
...@@ -110,7 +110,7 @@ type ArrayType struct { ...@@ -110,7 +110,7 @@ type ArrayType struct {
} }
func (t *ArrayType) String() string { func (t *ArrayType) String() string {
return "[" + strconv.Itoa64(t.Count) + "]" + t.Type.String() return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String()
} }
func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() } func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() }
...@@ -171,10 +171,10 @@ func (t *StructType) Defn() string { ...@@ -171,10 +171,10 @@ func (t *StructType) Defn() string {
s += "; " s += "; "
} }
s += f.Name + " " + f.Type.String() s += f.Name + " " + f.Type.String()
s += "@" + strconv.Itoa64(f.ByteOffset) s += "@" + strconv.FormatInt(f.ByteOffset, 10)
if f.BitSize > 0 { if f.BitSize > 0 {
s += " : " + strconv.Itoa64(f.BitSize) s += " : " + strconv.FormatInt(f.BitSize, 10)
s += "@" + strconv.Itoa64(f.BitOffset) s += "@" + strconv.FormatInt(f.BitOffset, 10)
} }
} }
s += "}" s += "}"
...@@ -206,7 +206,7 @@ func (t *EnumType) String() string { ...@@ -206,7 +206,7 @@ func (t *EnumType) String() string {
if i > 0 { if i > 0 {
s += "; " s += "; "
} }
s += v.Name + "=" + strconv.Itoa64(v.Val) s += v.Name + "=" + strconv.FormatInt(v.Val, 10)
} }
s += "}" s += "}"
return s return s
......
...@@ -1490,11 +1490,11 @@ func stringName(i uint32, names []intName, goSyntax bool) string { ...@@ -1490,11 +1490,11 @@ func stringName(i uint32, names []intName, goSyntax bool) string {
if goSyntax { if goSyntax {
s = "elf." + s s = "elf." + s
} }
return s + "+" + strconv.Uitoa64(uint64(i-n.i)) return s + "+" + strconv.FormatUint(uint64(i-n.i), 10)
} }
} }
return strconv.Uitoa64(uint64(i)) return strconv.FormatUint(uint64(i), 10)
} }
func flagName(i uint32, names []intName, goSyntax bool) string { func flagName(i uint32, names []intName, goSyntax bool) string {
...@@ -1512,10 +1512,10 @@ func flagName(i uint32, names []intName, goSyntax bool) string { ...@@ -1512,10 +1512,10 @@ func flagName(i uint32, names []intName, goSyntax bool) string {
} }
} }
if len(s) == 0 { if len(s) == 0 {
return "0x" + strconv.Uitob64(uint64(i), 16) return "0x" + strconv.FormatUint(uint64(i), 16)
} }
if i != 0 { if i != 0 {
s += "+0x" + strconv.Uitob64(uint64(i), 16) s += "+0x" + strconv.FormatUint(uint64(i), 16)
} }
return s return s
} }
...@@ -21,11 +21,11 @@ var fileTests = []fileTest{ ...@@ -21,11 +21,11 @@ var fileTests = []fileTest{
"testdata/gcc-386-darwin-exec", "testdata/gcc-386-darwin-exec",
FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0xc, 0x3c0, 0x85}, FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0xc, 0x3c0, 0x85},
[]*SegmentHeader{ []*SegmentHeader{
&SegmentHeader{LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, {LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
&SegmentHeader{LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0}, {LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0},
&SegmentHeader{LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0}, {LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0},
&SegmentHeader{LoadCmdSegment, 0x7c, "__IMPORT", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0}, {LoadCmdSegment, 0x7c, "__IMPORT", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0},
&SegmentHeader{LoadCmdSegment, 0x38, "__LINKEDIT", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0}, {LoadCmdSegment, 0x38, "__LINKEDIT", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0},
nil, nil,
nil, nil,
nil, nil,
...@@ -35,21 +35,21 @@ var fileTests = []fileTest{ ...@@ -35,21 +35,21 @@ var fileTests = []fileTest{
nil, nil,
}, },
[]*SectionHeader{ []*SectionHeader{
&SectionHeader{"__text", "__TEXT", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400}, {"__text", "__TEXT", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400},
&SectionHeader{"__cstring", "__TEXT", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2}, {"__cstring", "__TEXT", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2},
&SectionHeader{"__data", "__DATA", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0}, {"__data", "__DATA", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0},
&SectionHeader{"__dyld", "__DATA", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0}, {"__dyld", "__DATA", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0},
&SectionHeader{"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008}, {"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008},
}, },
}, },
{ {
"testdata/gcc-amd64-darwin-exec", "testdata/gcc-amd64-darwin-exec",
FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0xb, 0x568, 0x85}, FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0xb, 0x568, 0x85},
[]*SegmentHeader{ []*SegmentHeader{
&SegmentHeader{LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, {LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
&SegmentHeader{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0}, {LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0},
&SegmentHeader{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0}, {LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0},
&SegmentHeader{LoadCmdSegment64, 0x48, "__LINKEDIT", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0}, {LoadCmdSegment64, 0x48, "__LINKEDIT", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0},
nil, nil,
nil, nil,
nil, nil,
...@@ -59,14 +59,14 @@ var fileTests = []fileTest{ ...@@ -59,14 +59,14 @@ var fileTests = []fileTest{
nil, nil,
}, },
[]*SectionHeader{ []*SectionHeader{
&SectionHeader{"__text", "__TEXT", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400}, {"__text", "__TEXT", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400},
&SectionHeader{"__symbol_stub1", "__TEXT", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408}, {"__symbol_stub1", "__TEXT", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408},
&SectionHeader{"__stub_helper", "__TEXT", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0}, {"__stub_helper", "__TEXT", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0},
&SectionHeader{"__cstring", "__TEXT", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2}, {"__cstring", "__TEXT", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2},
&SectionHeader{"__eh_frame", "__TEXT", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b}, {"__eh_frame", "__TEXT", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b},
&SectionHeader{"__data", "__DATA", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0}, {"__data", "__DATA", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0},
&SectionHeader{"__dyld", "__DATA", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0}, {"__dyld", "__DATA", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0},
&SectionHeader{"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7}, {"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7},
}, },
}, },
{ {
...@@ -74,26 +74,26 @@ var fileTests = []fileTest{ ...@@ -74,26 +74,26 @@ var fileTests = []fileTest{
FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0xa, 0x4, 0x5a0, 0}, FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0xa, 0x4, 0x5a0, 0},
[]*SegmentHeader{ []*SegmentHeader{
nil, nil,
&SegmentHeader{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0}, {LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0},
&SegmentHeader{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0}, {LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0},
&SegmentHeader{LoadCmdSegment64, 0x278, "__DWARF", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0}, {LoadCmdSegment64, 0x278, "__DWARF", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0},
}, },
[]*SectionHeader{ []*SectionHeader{
&SectionHeader{"__text", "__TEXT", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400}, {"__text", "__TEXT", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400},
&SectionHeader{"__symbol_stub1", "__TEXT", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408}, {"__symbol_stub1", "__TEXT", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408},
&SectionHeader{"__stub_helper", "__TEXT", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, {"__stub_helper", "__TEXT", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0},
&SectionHeader{"__cstring", "__TEXT", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}, {"__cstring", "__TEXT", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
&SectionHeader{"__eh_frame", "__TEXT", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b}, {"__eh_frame", "__TEXT", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b},
&SectionHeader{"__data", "__DATA", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0}, {"__data", "__DATA", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
&SectionHeader{"__dyld", "__DATA", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0}, {"__dyld", "__DATA", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
&SectionHeader{"__la_symbol_ptr", "__DATA", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7}, {"__la_symbol_ptr", "__DATA", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7},
&SectionHeader{"__debug_abbrev", "__DWARF", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0}, {"__debug_abbrev", "__DWARF", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0},
&SectionHeader{"__debug_aranges", "__DWARF", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0}, {"__debug_aranges", "__DWARF", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0},
&SectionHeader{"__debug_frame", "__DWARF", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0}, {"__debug_frame", "__DWARF", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0},
&SectionHeader{"__debug_info", "__DWARF", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0}, {"__debug_info", "__DWARF", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0},
&SectionHeader{"__debug_line", "__DWARF", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0}, {"__debug_line", "__DWARF", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0},
&SectionHeader{"__debug_pubnames", "__DWARF", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0}, {"__debug_pubnames", "__DWARF", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0},
&SectionHeader{"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0}, {"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0},
}, },
}, },
} }
......
...@@ -278,7 +278,7 @@ func stringName(i uint32, names []intName, goSyntax bool) string { ...@@ -278,7 +278,7 @@ func stringName(i uint32, names []intName, goSyntax bool) string {
return n.s return n.s
} }
} }
return strconv.Uitoa64(uint64(i)) return strconv.FormatUint(uint64(i), 10)
} }
func flagName(i uint32, names []intName, goSyntax bool) string { func flagName(i uint32, names []intName, goSyntax bool) string {
...@@ -296,10 +296,10 @@ func flagName(i uint32, names []intName, goSyntax bool) string { ...@@ -296,10 +296,10 @@ func flagName(i uint32, names []intName, goSyntax bool) string {
} }
} }
if len(s) == 0 { if len(s) == 0 {
return "0x" + strconv.Uitob64(uint64(i), 16) return "0x" + strconv.FormatUint(uint64(i), 16)
} }
if i != 0 { if i != 0 {
s += "+0x" + strconv.Uitob64(uint64(i), 16) s += "+0x" + strconv.FormatUint(uint64(i), 16)
} }
return s return s
} }
...@@ -20,39 +20,39 @@ var fileTests = []fileTest{ ...@@ -20,39 +20,39 @@ var fileTests = []fileTest{
"testdata/gcc-386-mingw-obj", "testdata/gcc-386-mingw-obj",
FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104}, FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
[]*SectionHeader{ []*SectionHeader{
&SectionHeader{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020}, {".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
&SectionHeader{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264}, {".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
&SectionHeader{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328}, {".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
&SectionHeader{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000}, {".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
&SectionHeader{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832}, {".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
&SectionHeader{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832}, {".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
&SectionHeader{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616}, {".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
&SectionHeader{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984}, {".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
&SectionHeader{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832}, {".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
&SectionHeader{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832}, {".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
&SectionHeader{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832}, {".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
&SectionHeader{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832}, {".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
}, },
}, },
{ {
"testdata/gcc-386-mingw-exec", "testdata/gcc-386-mingw-exec",
FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107}, FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
[]*SectionHeader{ []*SectionHeader{
&SectionHeader{Name: ".text", VirtualSize: 0xcd8, VirtualAddress: 0x1000, Size: 0xe00, Offset: 0x400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x60500060}, {Name: ".text", VirtualSize: 0xcd8, VirtualAddress: 0x1000, Size: 0xe00, Offset: 0x400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x60500060},
&SectionHeader{Name: ".data", VirtualSize: 0x10, VirtualAddress: 0x2000, Size: 0x200, Offset: 0x1200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040}, {Name: ".data", VirtualSize: 0x10, VirtualAddress: 0x2000, Size: 0x200, Offset: 0x1200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
&SectionHeader{Name: ".rdata", VirtualSize: 0x120, VirtualAddress: 0x3000, Size: 0x200, Offset: 0x1400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x40300040}, {Name: ".rdata", VirtualSize: 0x120, VirtualAddress: 0x3000, Size: 0x200, Offset: 0x1400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x40300040},
&SectionHeader{Name: ".bss", VirtualSize: 0xdc, VirtualAddress: 0x4000, Size: 0x0, Offset: 0x0, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0400080}, {Name: ".bss", VirtualSize: 0xdc, VirtualAddress: 0x4000, Size: 0x0, Offset: 0x0, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0400080},
&SectionHeader{Name: ".idata", VirtualSize: 0x3c8, VirtualAddress: 0x5000, Size: 0x400, Offset: 0x1600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040}, {Name: ".idata", VirtualSize: 0x3c8, VirtualAddress: 0x5000, Size: 0x400, Offset: 0x1600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
&SectionHeader{Name: ".CRT", VirtualSize: 0x18, VirtualAddress: 0x6000, Size: 0x200, Offset: 0x1a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040}, {Name: ".CRT", VirtualSize: 0x18, VirtualAddress: 0x6000, Size: 0x200, Offset: 0x1a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
&SectionHeader{Name: ".tls", VirtualSize: 0x20, VirtualAddress: 0x7000, Size: 0x200, Offset: 0x1c00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040}, {Name: ".tls", VirtualSize: 0x20, VirtualAddress: 0x7000, Size: 0x200, Offset: 0x1c00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
&SectionHeader{Name: ".debug_aranges", VirtualSize: 0x20, VirtualAddress: 0x8000, Size: 0x200, Offset: 0x1e00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, {Name: ".debug_aranges", VirtualSize: 0x20, VirtualAddress: 0x8000, Size: 0x200, Offset: 0x1e00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
&SectionHeader{Name: ".debug_pubnames", VirtualSize: 0x51, VirtualAddress: 0x9000, Size: 0x200, Offset: 0x2000, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, {Name: ".debug_pubnames", VirtualSize: 0x51, VirtualAddress: 0x9000, Size: 0x200, Offset: 0x2000, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
&SectionHeader{Name: ".debug_pubtypes", VirtualSize: 0x91, VirtualAddress: 0xa000, Size: 0x200, Offset: 0x2200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, {Name: ".debug_pubtypes", VirtualSize: 0x91, VirtualAddress: 0xa000, Size: 0x200, Offset: 0x2200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
&SectionHeader{Name: ".debug_info", VirtualSize: 0xe22, VirtualAddress: 0xb000, Size: 0x1000, Offset: 0x2400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, {Name: ".debug_info", VirtualSize: 0xe22, VirtualAddress: 0xb000, Size: 0x1000, Offset: 0x2400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
&SectionHeader{Name: ".debug_abbrev", VirtualSize: 0x157, VirtualAddress: 0xc000, Size: 0x200, Offset: 0x3400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, {Name: ".debug_abbrev", VirtualSize: 0x157, VirtualAddress: 0xc000, Size: 0x200, Offset: 0x3400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
&SectionHeader{Name: ".debug_line", VirtualSize: 0x144, VirtualAddress: 0xd000, Size: 0x200, Offset: 0x3600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, {Name: ".debug_line", VirtualSize: 0x144, VirtualAddress: 0xd000, Size: 0x200, Offset: 0x3600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
&SectionHeader{Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000}, {Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
&SectionHeader{Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, {Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
}, },
}, },
} }
......
...@@ -168,7 +168,7 @@ func (e *encoder) Close() error { ...@@ -168,7 +168,7 @@ func (e *encoder) Close() error {
type CorruptInputError int64 type CorruptInputError int64
func (e CorruptInputError) Error() string { func (e CorruptInputError) Error() string {
return "illegal ascii85 data at input byte " + strconv.Itoa64(int64(e)) return "illegal ascii85 data at input byte " + strconv.FormatInt(int64(e), 10)
} }
// Decode decodes src into dst, returning both the number // Decode decodes src into dst, returning both the number
......
...@@ -225,19 +225,19 @@ func TestUTCTime(t *testing.T) { ...@@ -225,19 +225,19 @@ func TestUTCTime(t *testing.T) {
ret, err := parseUTCTime([]byte(test.in)) ret, err := parseUTCTime([]byte(test.in))
if err != nil { if err != nil {
if test.ok { if test.ok {
t.Errorf("#%d: parseUTCTime(%q) = error %v", i, err) t.Errorf("#%d: parseUTCTime(%q) = error %v", i, test.in, err)
} }
continue continue
} }
if !test.ok { if !test.ok {
t.Errorf("#%d: parseUTCTime(%q) succeeded, should have failed", i) t.Errorf("#%d: parseUTCTime(%q) succeeded, should have failed", i, test.in)
continue continue
} }
const format = "Jan _2 15:04:05 -0700 2006" // ignore zone name, just offset const format = "Jan _2 15:04:05 -0700 2006" // ignore zone name, just offset
have := ret.Format(format) have := ret.Format(format)
want := test.out.Format(format) want := test.out.Format(format)
if have != want { if have != want {
t.Errorf("#%d: parseUTCTime(%q) = %s, want %s", test.in, have, want) t.Errorf("#%d: parseUTCTime(%q) = %s, want %s", i, test.in, have, want)
} }
} }
} }
......
...@@ -98,7 +98,7 @@ func parseFieldParameters(str string) (ret fieldParameters) { ...@@ -98,7 +98,7 @@ func parseFieldParameters(str string) (ret fieldParameters) {
case part == "printable": case part == "printable":
ret.stringType = tagPrintableString ret.stringType = tagPrintableString
case strings.HasPrefix(part, "default:"): case strings.HasPrefix(part, "default:"):
i, err := strconv.Atoi64(part[8:]) i, err := strconv.ParseInt(part[8:], 10, 64)
if err == nil { if err == nil {
ret.defaultValue = new(int64) ret.defaultValue = new(int64)
*ret.defaultValue = i *ret.defaultValue = i
......
...@@ -216,7 +216,7 @@ func (enc *Encoding) EncodedLen(n int) int { return (n + 4) / 5 * 8 } ...@@ -216,7 +216,7 @@ func (enc *Encoding) EncodedLen(n int) int { return (n + 4) / 5 * 8 }
type CorruptInputError int64 type CorruptInputError int64
func (e CorruptInputError) Error() string { func (e CorruptInputError) Error() string {
return "illegal base32 data at input byte " + strconv.Itoa64(int64(e)) return "illegal base32 data at input byte " + strconv.FormatInt(int64(e), 10)
} }
// decode is like Decode but returns an additional 'end' value, which // decode is like Decode but returns an additional 'end' value, which
......
...@@ -203,7 +203,7 @@ func (enc *Encoding) EncodedLen(n int) int { return (n + 2) / 3 * 4 } ...@@ -203,7 +203,7 @@ func (enc *Encoding) EncodedLen(n int) int { return (n + 2) / 3 * 4 }
type CorruptInputError int64 type CorruptInputError int64
func (e CorruptInputError) Error() string { func (e CorruptInputError) Error() string {
return "illegal base64 data at input byte " + strconv.Itoa64(int64(e)) return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
} }
// decode is like Decode but returns an additional 'end' value, which // decode is like Decode but returns an additional 'end' value, which
......
...@@ -15,7 +15,7 @@ import ( ...@@ -15,7 +15,7 @@ import (
type CorruptInputError int64 type CorruptInputError int64
func (e CorruptInputError) Error() string { func (e CorruptInputError) Error() string {
return "illegal git85 data at input byte " + strconv.Itoa64(int64(e)) return "illegal git85 data at input byte " + strconv.FormatInt(int64(e), 10)
} }
const encode = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~" const encode = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"
......
...@@ -119,7 +119,9 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp ...@@ -119,7 +119,9 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
switch st := actual; st.Kind() { switch st := actual; st.Kind() {
case reflect.Struct: case reflect.Struct:
for i := 0; i < st.NumField(); i++ { for i := 0; i < st.NumField(); i++ {
enc.sendType(w, state, st.Field(i).Type) if isExported(st.Field(i).Name) {
enc.sendType(w, state, st.Field(i).Type)
}
} }
case reflect.Array, reflect.Slice: case reflect.Array, reflect.Slice:
enc.sendType(w, state, st.Elem()) enc.sendType(w, state, st.Elem())
......
...@@ -662,3 +662,19 @@ func TestSequentialDecoder(t *testing.T) { ...@@ -662,3 +662,19 @@ func TestSequentialDecoder(t *testing.T) {
} }
} }
} }
// Should be able to have unrepresentable fields (chan, func) as long as they
// are unexported.
type Bug2 struct {
A int
b chan int
}
func TestUnexportedChan(t *testing.T) {
b := Bug2{23, make(chan int)}
var stream bytes.Buffer
enc := NewEncoder(&stream)
if err := enc.Encode(b); err != nil {
t.Fatalf("error encoding unexported channel: %s", err)
}
}
...@@ -642,7 +642,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) { ...@@ -642,7 +642,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
default: default:
d.error(&UnmarshalTypeError{"number", v.Type()}) d.error(&UnmarshalTypeError{"number", v.Type()})
case reflect.Interface: case reflect.Interface:
n, err := strconv.Atof64(s) n, err := strconv.ParseFloat(s, 64)
if err != nil { if err != nil {
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
break break
...@@ -650,7 +650,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) { ...@@ -650,7 +650,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
v.Set(reflect.ValueOf(n)) v.Set(reflect.ValueOf(n))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.Atoi64(s) n, err := strconv.ParseInt(s, 10, 64)
if err != nil || v.OverflowInt(n) { if err != nil || v.OverflowInt(n) {
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
break break
...@@ -658,7 +658,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) { ...@@ -658,7 +658,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
v.SetInt(n) v.SetInt(n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.Atoui64(s) n, err := strconv.ParseUint(s, 10, 64)
if err != nil || v.OverflowUint(n) { if err != nil || v.OverflowUint(n) {
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
break break
...@@ -666,7 +666,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) { ...@@ -666,7 +666,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
v.SetUint(n) v.SetUint(n)
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
n, err := strconv.AtofN(s, v.Type().Bits()) n, err := strconv.ParseFloat(s, v.Type().Bits())
if err != nil || v.OverflowFloat(n) { if err != nil || v.OverflowFloat(n) {
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
break break
...@@ -798,7 +798,7 @@ func (d *decodeState) literalInterface() interface{} { ...@@ -798,7 +798,7 @@ func (d *decodeState) literalInterface() interface{} {
if c != '-' && (c < '0' || c > '9') { if c != '-' && (c < '0' || c > '9') {
d.error(errPhase) d.error(errPhase)
} }
n, err := strconv.Atof64(string(item)) n, err := strconv.ParseFloat(string(item), 64)
if err != nil { if err != nil {
d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)}) d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
} }
...@@ -813,7 +813,7 @@ func getu4(s []byte) rune { ...@@ -813,7 +813,7 @@ func getu4(s []byte) rune {
if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
return -1 return -1
} }
r, err := strconv.Btoui64(string(s[2:6]), 16) r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
if err != nil { if err != nil {
return -1 return -1
} }
......
...@@ -345,12 +345,12 @@ var allValue = All{ ...@@ -345,12 +345,12 @@ var allValue = All{
"18": {Tag: "tag18"}, "18": {Tag: "tag18"},
}, },
MapP: map[string]*Small{ MapP: map[string]*Small{
"19": &Small{Tag: "tag19"}, "19": {Tag: "tag19"},
"20": nil, "20": nil,
}, },
EmptyMap: map[string]Small{}, EmptyMap: map[string]Small{},
Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}}, Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}},
SliceP: []*Small{&Small{Tag: "tag22"}, nil, &Small{Tag: "tag23"}}, SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}},
EmptySlice: []Small{}, EmptySlice: []Small{},
StringSlice: []string{"str24", "str25", "str26"}, StringSlice: []string{"str24", "str25", "str26"},
ByteSlice: []byte{27, 28, 29}, ByteSlice: []byte{27, 28, 29},
......
...@@ -275,13 +275,13 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) { ...@@ -275,13 +275,13 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
} }
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
writeString(e, strconv.Itoa64(v.Int())) writeString(e, strconv.FormatInt(v.Int(), 10))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
writeString(e, strconv.Uitoa64(v.Uint())) writeString(e, strconv.FormatUint(v.Uint(), 10))
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
writeString(e, strconv.FtoaN(v.Float(), 'g', -1, v.Type().Bits())) writeString(e, strconv.FormatFloat(v.Float(), 'g', -1, v.Type().Bits()))
case reflect.String: case reflect.String:
if quoted { if quoted {
......
...@@ -173,15 +173,15 @@ func (p *printer) marshalValue(val reflect.Value, name string) error { ...@@ -173,15 +173,15 @@ func (p *printer) marshalValue(val reflect.Value, name string) error {
switch k := val.Kind(); k { switch k := val.Kind(); k {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p.WriteString(strconv.Itoa64(val.Int())) p.WriteString(strconv.FormatInt(val.Int(), 10))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p.WriteString(strconv.Uitoa64(val.Uint())) p.WriteString(strconv.FormatUint(val.Uint(), 10))
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
p.WriteString(strconv.Ftoa64(val.Float(), 'g', -1)) p.WriteString(strconv.FormatFloat(val.Float(), 'g', -1, 64))
case reflect.String: case reflect.String:
Escape(p, []byte(val.String())) Escape(p, []byte(val.String()))
case reflect.Bool: case reflect.Bool:
p.WriteString(strconv.Btoa(val.Bool())) p.WriteString(strconv.FormatBool(val.Bool()))
case reflect.Array: case reflect.Array:
// will be [...]byte // will be [...]byte
bytes := make([]byte, val.Len()) bytes := make([]byte, val.Len())
......
...@@ -160,19 +160,19 @@ var marshalTests = []struct { ...@@ -160,19 +160,19 @@ var marshalTests = []struct {
Age: 1, Age: 1,
Drive: ImprobabilityDrive, Drive: ImprobabilityDrive,
Passenger: []*Passenger{ Passenger: []*Passenger{
&Passenger{ {
Name: []string{"Zaphod", "Beeblebrox"}, Name: []string{"Zaphod", "Beeblebrox"},
Weight: 7.25, Weight: 7.25,
}, },
&Passenger{ {
Name: []string{"Trisha", "McMillen"}, Name: []string{"Trisha", "McMillen"},
Weight: 5.5, Weight: 5.5,
}, },
&Passenger{ {
Name: []string{"Ford", "Prefect"}, Name: []string{"Ford", "Prefect"},
Weight: 7, Weight: 7,
}, },
&Passenger{ {
Name: []string{"Arthur", "Dent"}, Name: []string{"Arthur", "Dent"},
Weight: 6.75, Weight: 6.75,
}, },
...@@ -326,12 +326,12 @@ var marshalErrorTests = []struct { ...@@ -326,12 +326,12 @@ var marshalErrorTests = []struct {
"question": "What do you get when you multiply six by nine?", "question": "What do you get when you multiply six by nine?",
"answer": "42", "answer": "42",
}, },
Err: "xml: unsupported type: map[string] string", Err: "xml: unsupported type: map[string]string",
Kind: reflect.Map, Kind: reflect.Map,
}, },
{ {
Value: map[*Ship]bool{nil: false}, Value: map[*Ship]bool{nil: false},
Err: "xml: unsupported type: map[*xml.Ship] bool", Err: "xml: unsupported type: map[*xml.Ship]bool",
Kind: reflect.Map, Kind: reflect.Map,
}, },
} }
......
...@@ -486,19 +486,19 @@ func copyValue(dst reflect.Value, src []byte) (err error) { ...@@ -486,19 +486,19 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
// Helper functions for integer and unsigned integer conversions // Helper functions for integer and unsigned integer conversions
var itmp int64 var itmp int64
getInt64 := func() bool { getInt64 := func() bool {
itmp, err = strconv.Atoi64(string(src)) itmp, err = strconv.ParseInt(string(src), 10, 64)
// TODO: should check sizes // TODO: should check sizes
return err == nil return err == nil
} }
var utmp uint64 var utmp uint64
getUint64 := func() bool { getUint64 := func() bool {
utmp, err = strconv.Atoui64(string(src)) utmp, err = strconv.ParseUint(string(src), 10, 64)
// TODO: check for overflow? // TODO: check for overflow?
return err == nil return err == nil
} }
var ftmp float64 var ftmp float64
getFloat64 := func() bool { getFloat64 := func() bool {
ftmp, err = strconv.Atof64(string(src)) ftmp, err = strconv.ParseFloat(string(src), 64)
// TODO: check for overflow? // TODO: check for overflow?
return err == nil return err == nil
} }
...@@ -525,7 +525,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) { ...@@ -525,7 +525,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
} }
t.SetFloat(ftmp) t.SetFloat(ftmp)
case reflect.Bool: case reflect.Bool:
value, err := strconv.Atob(strings.TrimSpace(string(src))) value, err := strconv.ParseBool(strings.TrimSpace(string(src)))
if err != nil { if err != nil {
return err return err
} }
......
...@@ -889,9 +889,9 @@ Input: ...@@ -889,9 +889,9 @@ Input:
var n uint64 var n uint64
var err error var err error
if i >= 3 && s[1] == 'x' { if i >= 3 && s[1] == 'x' {
n, err = strconv.Btoui64(s[2:], 16) n, err = strconv.ParseUint(s[2:], 16, 64)
} else { } else {
n, err = strconv.Btoui64(s[1:], 10) n, err = strconv.ParseUint(s[1:], 10, 64)
} }
if err == nil && n <= unicode.MaxRune { if err == nil && n <= unicode.MaxRune {
text = string(n) text = string(n)
......
...@@ -226,7 +226,7 @@ func parseDecomposition(s string, skipfirst bool) (a []rune, e error) { ...@@ -226,7 +226,7 @@ func parseDecomposition(s string, skipfirst bool) (a []rune, e error) {
decomp = decomp[1:] decomp = decomp[1:]
} }
for _, d := range decomp { for _, d := range decomp {
point, err := strconv.Btoui64(d, 16) point, err := strconv.ParseUint(d, 16, 64)
if err != nil { if err != nil {
return a, err return a, err
} }
...@@ -240,7 +240,7 @@ func parseCharacter(line string) { ...@@ -240,7 +240,7 @@ func parseCharacter(line string) {
if len(field) != NumField { if len(field) != NumField {
logger.Fatalf("%5s: %d fields (expected %d)\n", line, len(field), NumField) logger.Fatalf("%5s: %d fields (expected %d)\n", line, len(field), NumField)
} }
x, err := strconv.Btoui64(field[FCodePoint], 16) x, err := strconv.ParseUint(field[FCodePoint], 16, 64)
point := int(x) point := int(x)
if err != nil { if err != nil {
logger.Fatalf("%.5s...: %s", line, err) logger.Fatalf("%.5s...: %s", line, err)
...@@ -264,7 +264,7 @@ func parseCharacter(line string) { ...@@ -264,7 +264,7 @@ func parseCharacter(line string) {
if state != SLast { if state != SLast {
firstChar = lastChar firstChar = lastChar
} }
x, err = strconv.Atoui64(field[FCanonicalCombiningClass]) x, err = strconv.ParseUint(field[FCanonicalCombiningClass], 10, 64)
if err != nil { if err != nil {
logger.Fatalf("%U: bad ccc field: %s", int(x), err) logger.Fatalf("%U: bad ccc field: %s", int(x), err)
} }
...@@ -336,7 +336,7 @@ func parseExclusion(line string) int { ...@@ -336,7 +336,7 @@ func parseExclusion(line string) int {
if len(matches) != 2 { if len(matches) != 2 {
logger.Fatalf("%s: %d matches (expected 1)\n", line, len(matches)) logger.Fatalf("%s: %d matches (expected 1)\n", line, len(matches))
} }
point, err := strconv.Btoui64(matches[1], 16) point, err := strconv.ParseUint(matches[1], 16, 64)
if err != nil { if err != nil {
logger.Fatalf("%.5s...: %s", line, err) logger.Fatalf("%.5s...: %s", line, err)
} }
...@@ -792,13 +792,13 @@ func testDerived() { ...@@ -792,13 +792,13 @@ func testDerived() {
continue continue
} }
rng := strings.Split(qc[1], "..") rng := strings.Split(qc[1], "..")
i, err := strconv.Btoui64(rng[0], 16) i, err := strconv.ParseUint(rng[0], 16, 64)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
j := i j := i
if len(rng) > 1 { if len(rng) > 1 {
j, err = strconv.Btoui64(rng[1], 16) j, err = strconv.ParseUint(rng[1], 16, 64)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
......
...@@ -171,7 +171,7 @@ func loadTestData() { ...@@ -171,7 +171,7 @@ func loadTestData() {
counter++ counter++
for j := 1; j < len(m)-1; j++ { for j := 1; j < len(m)-1; j++ {
for _, split := range strings.Split(m[j], " ") { for _, split := range strings.Split(m[j], " ") {
r, err := strconv.Btoui64(split, 16) r, err := strconv.ParseUint(split, 16, 64)
if err != nil { if err != nil {
logger.Fatal(err) logger.Fatal(err)
} }
......
...@@ -95,7 +95,7 @@ func convertAssign(dest, src interface{}) error { ...@@ -95,7 +95,7 @@ func convertAssign(dest, src interface{}) error {
switch dv.Kind() { switch dv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
s := asString(src) s := asString(src)
i64, err := strconv.Atoi64(s) i64, err := strconv.ParseInt(s, 10, 64)
if err != nil { if err != nil {
return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
} }
...@@ -106,7 +106,7 @@ func convertAssign(dest, src interface{}) error { ...@@ -106,7 +106,7 @@ func convertAssign(dest, src interface{}) error {
return nil return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
s := asString(src) s := asString(src)
u64, err := strconv.Atoui64(s) u64, err := strconv.ParseUint(s, 10, 64)
if err != nil { if err != nil {
return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
} }
...@@ -117,7 +117,7 @@ func convertAssign(dest, src interface{}) error { ...@@ -117,7 +117,7 @@ func convertAssign(dest, src interface{}) error {
return nil return nil
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
s := asString(src) s := asString(src)
f64, err := strconv.Atof64(s) f64, err := strconv.ParseFloat(s, 64)
if err != nil { if err != nil {
return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
} }
......
...@@ -54,13 +54,13 @@ func (boolType) ConvertValue(src interface{}) (interface{}, error) { ...@@ -54,13 +54,13 @@ func (boolType) ConvertValue(src interface{}) (interface{}, error) {
case bool: case bool:
return s, nil return s, nil
case string: case string:
b, err := strconv.Atob(s) b, err := strconv.ParseBool(s)
if err != nil { if err != nil {
return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s) return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
} }
return b, nil return b, nil
case []byte: case []byte:
b, err := strconv.Atob(string(s)) b, err := strconv.ParseBool(string(s))
if err != nil { if err != nil {
return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s) return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
} }
......
...@@ -77,12 +77,12 @@ var DefaultCipherOrder = []string{ ...@@ -77,12 +77,12 @@ var DefaultCipherOrder = []string{
var cipherModes = map[string]*cipherMode{ var cipherModes = map[string]*cipherMode{
// Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
// are defined in the order specified in the RFC. // are defined in the order specified in the RFC.
"aes128-ctr": &cipherMode{16, aes.BlockSize, 0, newAESCTR}, "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
"aes192-ctr": &cipherMode{24, aes.BlockSize, 0, newAESCTR}, "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
"aes256-ctr": &cipherMode{32, aes.BlockSize, 0, newAESCTR}, "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
// Ciphers from RFC4345, which introduces security-improved arcfour ciphers. // Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
// They are defined in the order specified in the RFC. // They are defined in the order specified in the RFC.
"arcfour128": &cipherMode{16, 0, 1536, newRC4}, "arcfour128": {16, 0, 1536, newRC4},
"arcfour256": &cipherMode{32, 0, 1536, newRC4}, "arcfour256": {32, 0, 1536, newRC4},
} }
...@@ -200,7 +200,7 @@ func (c *ClientConn) mainLoop() { ...@@ -200,7 +200,7 @@ func (c *ClientConn) mainLoop() {
peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4]) peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
if length := int(packet[5])<<24 | int(packet[6])<<16 | int(packet[7])<<8 | int(packet[8]); length > 0 { if length := int(packet[5])<<24 | int(packet[6])<<16 | int(packet[7])<<8 | int(packet[8]); length > 0 {
packet = packet[9:] packet = packet[9:]
c.getChan(peersId).data <- packet[:length] c.getChan(peersId).stdout.data <- packet[:length]
} }
case msgChannelExtendedData: case msgChannelExtendedData:
if len(packet) < 13 { if len(packet) < 13 {
...@@ -215,7 +215,7 @@ func (c *ClientConn) mainLoop() { ...@@ -215,7 +215,7 @@ func (c *ClientConn) mainLoop() {
// for stderr on interactive sessions. Other data types are // for stderr on interactive sessions. Other data types are
// silently discarded. // silently discarded.
if datatype == 1 { if datatype == 1 {
c.getChan(peersId).dataExt <- packet[:length] c.getChan(peersId).stderr.data <- packet[:length]
} }
} }
default: default:
...@@ -228,9 +228,9 @@ func (c *ClientConn) mainLoop() { ...@@ -228,9 +228,9 @@ func (c *ClientConn) mainLoop() {
c.getChan(msg.PeersId).msg <- msg c.getChan(msg.PeersId).msg <- msg
case *channelCloseMsg: case *channelCloseMsg:
ch := c.getChan(msg.PeersId) ch := c.getChan(msg.PeersId)
close(ch.win) close(ch.stdin.win)
close(ch.data) close(ch.stdout.data)
close(ch.dataExt) close(ch.stderr.data)
c.chanlist.remove(msg.PeersId) c.chanlist.remove(msg.PeersId)
case *channelEOFMsg: case *channelEOFMsg:
c.getChan(msg.PeersId).msg <- msg c.getChan(msg.PeersId).msg <- msg
...@@ -241,7 +241,7 @@ func (c *ClientConn) mainLoop() { ...@@ -241,7 +241,7 @@ func (c *ClientConn) mainLoop() {
case *channelRequestMsg: case *channelRequestMsg:
c.getChan(msg.PeersId).msg <- msg c.getChan(msg.PeersId).msg <- msg
case *windowAdjustMsg: case *windowAdjustMsg:
c.getChan(msg.PeersId).win <- int(msg.AdditionalBytes) c.getChan(msg.PeersId).stdin.win <- int(msg.AdditionalBytes)
default: default:
fmt.Printf("mainLoop: unhandled message %T: %v\n", msg, msg) fmt.Printf("mainLoop: unhandled message %T: %v\n", msg, msg)
} }
...@@ -290,21 +290,49 @@ func (c *ClientConfig) rand() io.Reader { ...@@ -290,21 +290,49 @@ func (c *ClientConfig) rand() io.Reader {
type clientChan struct { type clientChan struct {
packetWriter packetWriter
id, peersId uint32 id, peersId uint32
data chan []byte // receives the payload of channelData messages stdin *chanWriter // receives window adjustments
dataExt chan []byte // receives the payload of channelExtendedData messages stdout *chanReader // receives the payload of channelData messages
win chan int // receives window adjustments stderr *chanReader // receives the payload of channelExtendedData messages
msg chan interface{} // incoming messages msg chan interface{} // incoming messages
} }
// newClientChan returns a partially constructed *clientChan
// using the local id provided. To be usable clientChan.peersId
// needs to be assigned once known.
func newClientChan(t *transport, id uint32) *clientChan { func newClientChan(t *transport, id uint32) *clientChan {
return &clientChan{ c := &clientChan{
packetWriter: t, packetWriter: t,
id: id, id: id,
data: make(chan []byte, 16),
dataExt: make(chan []byte, 16),
win: make(chan int, 16),
msg: make(chan interface{}, 16), msg: make(chan interface{}, 16),
} }
c.stdin = &chanWriter{
win: make(chan int, 16),
clientChan: c,
}
c.stdout = &chanReader{
data: make(chan []byte, 16),
clientChan: c,
}
c.stderr = &chanReader{
data: make(chan []byte, 16),
clientChan: c,
}
return c
}
// waitForChannelOpenResponse, if successful, fills out
// the peerId and records any initial window advertisement.
func (c *clientChan) waitForChannelOpenResponse() error {
switch msg := (<-c.msg).(type) {
case *channelOpenConfirmMsg:
// fixup peersId field
c.peersId = msg.MyId
c.stdin.win <- int(msg.MyWindow)
return nil
case *channelOpenFailureMsg:
return errors.New(safeString(msg.Message))
}
return errors.New("unexpected packet")
} }
// Close closes the channel. This does not close the underlying connection. // Close closes the channel. This does not close the underlying connection.
...@@ -355,10 +383,9 @@ func (c *chanlist) remove(id uint32) { ...@@ -355,10 +383,9 @@ func (c *chanlist) remove(id uint32) {
// A chanWriter represents the stdin of a remote process. // A chanWriter represents the stdin of a remote process.
type chanWriter struct { type chanWriter struct {
win chan int // receives window adjustments win chan int // receives window adjustments
peersId uint32 // the peer's id rwin int // current rwin size
rwin int // current rwin size clientChan *clientChan // the channel backing this writer
packetWriter // for sending channelDataMsg
} }
// Write writes data to the remote process's standard input. // Write writes data to the remote process's standard input.
...@@ -372,12 +399,13 @@ func (w *chanWriter) Write(data []byte) (n int, err error) { ...@@ -372,12 +399,13 @@ func (w *chanWriter) Write(data []byte) (n int, err error) {
w.rwin += win w.rwin += win
continue continue
} }
peersId := w.clientChan.peersId
n = len(data) n = len(data)
packet := make([]byte, 0, 9+n) packet := make([]byte, 0, 9+n)
packet = append(packet, msgChannelData, packet = append(packet, msgChannelData,
byte(w.peersId>>24), byte(w.peersId>>16), byte(w.peersId>>8), byte(w.peersId), byte(peersId>>24), byte(peersId>>16), byte(peersId>>8), byte(peersId),
byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
err = w.writePacket(append(packet, data...)) err = w.clientChan.writePacket(append(packet, data...))
w.rwin -= n w.rwin -= n
return return
} }
...@@ -385,7 +413,7 @@ func (w *chanWriter) Write(data []byte) (n int, err error) { ...@@ -385,7 +413,7 @@ func (w *chanWriter) Write(data []byte) (n int, err error) {
} }
func (w *chanWriter) Close() error { func (w *chanWriter) Close() error {
return w.writePacket(marshal(msgChannelEOF, channelEOFMsg{w.peersId})) return w.clientChan.writePacket(marshal(msgChannelEOF, channelEOFMsg{w.clientChan.peersId}))
} }
// A chanReader represents stdout or stderr of a remote process. // A chanReader represents stdout or stderr of a remote process.
...@@ -393,10 +421,9 @@ type chanReader struct { ...@@ -393,10 +421,9 @@ type chanReader struct {
// TODO(dfc) a fixed size channel may not be the right data structure. // TODO(dfc) a fixed size channel may not be the right data structure.
// If writes to this channel block, they will block mainLoop, making // If writes to this channel block, they will block mainLoop, making
// it unable to receive new messages from the remote side. // it unable to receive new messages from the remote side.
data chan []byte // receives data from remote data chan []byte // receives data from remote
peersId uint32 // the peer's id clientChan *clientChan // the channel backing this reader
packetWriter // for sending windowAdjustMsg buf []byte
buf []byte
} }
// Read reads data from the remote process's stdout or stderr. // Read reads data from the remote process's stdout or stderr.
...@@ -407,10 +434,10 @@ func (r *chanReader) Read(data []byte) (int, error) { ...@@ -407,10 +434,10 @@ func (r *chanReader) Read(data []byte) (int, error) {
n := copy(data, r.buf) n := copy(data, r.buf)
r.buf = r.buf[n:] r.buf = r.buf[n:]
msg := windowAdjustMsg{ msg := windowAdjustMsg{
PeersId: r.peersId, PeersId: r.clientChan.peersId,
AdditionalBytes: uint32(n), AdditionalBytes: uint32(n),
} }
return n, r.writePacket(marshal(msgChannelWindowAdjust, msg)) return n, r.clientChan.writePacket(marshal(msgChannelWindowAdjust, msg))
} }
r.buf, ok = <-r.data r.buf, ok = <-r.data
if !ok { if !ok {
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"io" "io"
) )
// authenticate authenticates with the remote server. See RFC 4252. // authenticate authenticates with the remote server. See RFC 4252.
func (c *ClientConn) authenticate(session []byte) error { func (c *ClientConn) authenticate(session []byte) error {
// initiate user auth session // initiate user auth session
if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil { if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
...@@ -24,7 +24,7 @@ func (c *ClientConn) authenticate(session []byte) error { ...@@ -24,7 +24,7 @@ func (c *ClientConn) authenticate(session []byte) error {
return err return err
} }
// during the authentication phase the client first attempts the "none" method // during the authentication phase the client first attempts the "none" method
// then any untried methods suggested by the server. // then any untried methods suggested by the server.
tried, remain := make(map[string]bool), make(map[string]bool) tried, remain := make(map[string]bool), make(map[string]bool)
for auth := ClientAuth(new(noneAuth)); auth != nil; { for auth := ClientAuth(new(noneAuth)); auth != nil; {
ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand()) ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand())
...@@ -57,9 +57,9 @@ func (c *ClientConn) authenticate(session []byte) error { ...@@ -57,9 +57,9 @@ func (c *ClientConn) authenticate(session []byte) error {
// A ClientAuth represents an instance of an RFC 4252 authentication method. // A ClientAuth represents an instance of an RFC 4252 authentication method.
type ClientAuth interface { type ClientAuth interface {
// auth authenticates user over transport t. // auth authenticates user over transport t.
// Returns true if authentication is successful. // Returns true if authentication is successful.
// If authentication is not successful, a []string of alternative // If authentication is not successful, a []string of alternative
// method names is returned. // method names is returned.
auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error)
...@@ -79,19 +79,7 @@ func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reade ...@@ -79,19 +79,7 @@ func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reade
return false, nil, err return false, nil, err
} }
packet, err := t.readPacket() return handleAuthResponse(t)
if err != nil {
return false, nil, err
}
switch packet[0] {
case msgUserAuthSuccess:
return true, nil, nil
case msgUserAuthFailure:
msg := decode(packet).(*userAuthFailureMsg)
return false, msg.Methods, nil
}
return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
} }
func (n *noneAuth) method() string { func (n *noneAuth) method() string {
...@@ -127,19 +115,7 @@ func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.R ...@@ -127,19 +115,7 @@ func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.R
return false, nil, err return false, nil, err
} }
packet, err := t.readPacket() return handleAuthResponse(t)
if err != nil {
return false, nil, err
}
switch packet[0] {
case msgUserAuthSuccess:
return true, nil, nil
case msgUserAuthFailure:
msg := decode(packet).(*userAuthFailureMsg)
return false, msg.Methods, nil
}
return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
} }
func (p *passwordAuth) method() string { func (p *passwordAuth) method() string {
...@@ -159,7 +135,7 @@ func ClientAuthPassword(impl ClientPassword) ClientAuth { ...@@ -159,7 +135,7 @@ func ClientAuthPassword(impl ClientPassword) ClientAuth {
// ClientKeyring implements access to a client key ring. // ClientKeyring implements access to a client key ring.
type ClientKeyring interface { type ClientKeyring interface {
// Key returns the i'th rsa.Publickey or dsa.Publickey, or nil if // Key returns the i'th rsa.Publickey or dsa.Publickey, or nil if
// no key exists at i. // no key exists at i.
Key(i int) (key interface{}, err error) Key(i int) (key interface{}, err error)
...@@ -173,27 +149,28 @@ type publickeyAuth struct { ...@@ -173,27 +149,28 @@ type publickeyAuth struct {
ClientKeyring ClientKeyring
} }
type publickeyAuthMsg struct {
User string
Service string
Method string
// HasSig indicates to the reciver packet that the auth request is signed and
// should be used for authentication of the request.
HasSig bool
Algoname string
Pubkey string
// Sig is defined as []byte so marshal will exclude it during validateKey
Sig []byte `ssh:"rest"`
}
func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) { func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
type publickeyAuthMsg struct {
User string
Service string
Method string
// HasSig indicates to the reciver packet that the auth request is signed and
// should be used for authentication of the request.
HasSig bool
Algoname string
Pubkey string
// Sig is defined as []byte so marshal will exclude it during the query phase
Sig []byte `ssh:"rest"`
}
// Authentication is performed in two stages. The first stage sends an // Authentication is performed in two stages. The first stage sends an
// enquiry to test if each key is acceptable to the remote. The second // enquiry to test if each key is acceptable to the remote. The second
// stage attempts to authenticate with the valid keys obtained in the // stage attempts to authenticate with the valid keys obtained in the
// first stage. // first stage.
var index int var index int
// a map of public keys to their index in the keyring // a map of public keys to their index in the keyring
validKeys := make(map[int]interface{}) validKeys := make(map[int]interface{})
for { for {
key, err := p.Key(index) key, err := p.Key(index)
...@@ -204,33 +181,13 @@ func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io. ...@@ -204,33 +181,13 @@ func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.
// no more keys in the keyring // no more keys in the keyring
break break
} }
pubkey := serializePublickey(key)
algoname := algoName(key) if ok, err := p.validateKey(key, user, t); ok {
msg := publickeyAuthMsg{
User: user,
Service: serviceSSH,
Method: p.method(),
HasSig: false,
Algoname: algoname,
Pubkey: string(pubkey),
}
if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
return false, nil, err
}
packet, err := t.readPacket()
if err != nil {
return false, nil, err
}
switch packet[0] {
case msgUserAuthPubKeyOk:
msg := decode(packet).(*userAuthPubKeyOkMsg)
if msg.Algo != algoname || msg.PubKey != string(pubkey) {
continue
}
validKeys[index] = key validKeys[index] = key
case msgUserAuthFailure: } else {
default: if err != nil {
return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]} return false, nil, err
}
} }
index++ index++
} }
...@@ -265,24 +222,61 @@ func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io. ...@@ -265,24 +222,61 @@ func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.
if err := t.writePacket(p); err != nil { if err := t.writePacket(p); err != nil {
return false, nil, err return false, nil, err
} }
packet, err := t.readPacket() success, methods, err := handleAuthResponse(t)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
if success {
return success, methods, err
}
}
return false, methods, nil
}
// validateKey validates the key provided it is acceptable to the server.
func (p *publickeyAuth) validateKey(key interface{}, user string, t *transport) (bool, error) {
pubkey := serializePublickey(key)
algoname := algoName(key)
msg := publickeyAuthMsg{
User: user,
Service: serviceSSH,
Method: p.method(),
HasSig: false,
Algoname: algoname,
Pubkey: string(pubkey),
}
if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
return false, err
}
return p.confirmKeyAck(key, t)
}
func (p *publickeyAuth) confirmKeyAck(key interface{}, t *transport) (bool, error) {
pubkey := serializePublickey(key)
algoname := algoName(key)
for {
packet, err := t.readPacket()
if err != nil {
return false, err
}
switch packet[0] { switch packet[0] {
case msgUserAuthSuccess: case msgUserAuthBanner:
return true, nil, nil // TODO(gpaul): add callback to present the banner to the user
case msgUserAuthPubKeyOk:
msg := decode(packet).(*userAuthPubKeyOkMsg)
if msg.Algo != algoname || msg.PubKey != string(pubkey) {
return false, nil
}
return true, nil
case msgUserAuthFailure: case msgUserAuthFailure:
msg := decode(packet).(*userAuthFailureMsg) return false, nil
methods = msg.Methods
continue
case msgDisconnect:
return false, nil, io.EOF
default: default:
return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]} return false, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
} }
} }
return false, methods, nil panic("unreachable")
} }
func (p *publickeyAuth) method() string { func (p *publickeyAuth) method() string {
...@@ -293,3 +287,30 @@ func (p *publickeyAuth) method() string { ...@@ -293,3 +287,30 @@ func (p *publickeyAuth) method() string {
func ClientAuthPublickey(impl ClientKeyring) ClientAuth { func ClientAuthPublickey(impl ClientKeyring) ClientAuth {
return &publickeyAuth{impl} return &publickeyAuth{impl}
} }
// handleAuthResponse returns whether the preceding authentication request succeeded
// along with a list of remaining authentication methods to try next and
// an error if an unexpected response was received.
func handleAuthResponse(t *transport) (bool, []string, error) {
for {
packet, err := t.readPacket()
if err != nil {
return false, nil, err
}
switch packet[0] {
case msgUserAuthBanner:
// TODO: add callback to present the banner to the user
case msgUserAuthFailure:
msg := decode(packet).(*userAuthFailureMsg)
return false, msg.Methods, nil
case msgUserAuthSuccess:
return true, nil, nil
case msgDisconnect:
return false, nil, io.EOF
default:
return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
}
}
panic("unreachable")
}
...@@ -7,17 +7,20 @@ package ssh ...@@ -7,17 +7,20 @@ package ssh
import ( import (
"bytes" "bytes"
"crypto" "crypto"
"crypto/rand" "crypto/dsa"
"crypto/rsa" "crypto/rsa"
_ "crypto/sha1"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"errors" "errors"
"io" "io"
"io/ioutil" "io/ioutil"
"math/big"
"testing" "testing"
) )
const _pem = `-----BEGIN RSA PRIVATE KEY----- // private key for mock server
const testServerPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA19lGVsTqIT5iiNYRgnoY1CwkbETW5cq+Rzk5v/kTlf31XpSU MIIEpAIBAAKCAQEA19lGVsTqIT5iiNYRgnoY1CwkbETW5cq+Rzk5v/kTlf31XpSU
70HVWkbTERECjaYdXM2gGcbb+sxpq6GtXf1M3kVomycqhxwhPv4Cr6Xp4WT/jkFx 70HVWkbTERECjaYdXM2gGcbb+sxpq6GtXf1M3kVomycqhxwhPv4Cr6Xp4WT/jkFx
9z+FFzpeodGJWjOH6L2H5uX1Cvr9EDdQp9t9/J32/qBFntY8GwoUI/y/1MSTmMiF 9z+FFzpeodGJWjOH6L2H5uX1Cvr9EDdQp9t9/J32/qBFntY8GwoUI/y/1MSTmMiF
...@@ -45,25 +48,32 @@ gqnBycHj6AhEycjda75cs+0zybZvN4x65KZHOGW/O/7OAWEcZP5TPb3zf9ned3Hl ...@@ -45,25 +48,32 @@ gqnBycHj6AhEycjda75cs+0zybZvN4x65KZHOGW/O/7OAWEcZP5TPb3zf9ned3Hl
NsZoFj52ponUM6+99A2CmezFCN16c4mbA//luWF+k3VVqR6BpkrhKw== NsZoFj52ponUM6+99A2CmezFCN16c4mbA//luWF+k3VVqR6BpkrhKw==
-----END RSA PRIVATE KEY-----` -----END RSA PRIVATE KEY-----`
// reused internally by tests const testClientPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
var serverConfig = new(ServerConfig) MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld
r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ
func init() { tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC
if err := serverConfig.SetRSAPrivateKey([]byte(_pem)); err != nil { nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW
panic("unable to set private key: " + err.Error()) 2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB
} y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr
} rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg==
-----END RSA PRIVATE KEY-----`
// keychain implements the ClientPublickey interface // keychain implements the ClientPublickey interface
type keychain struct { type keychain struct {
keys []*rsa.PrivateKey keys []interface{}
} }
func (k *keychain) Key(i int) (interface{}, error) { func (k *keychain) Key(i int) (interface{}, error) {
if i < 0 || i >= len(k.keys) { if i < 0 || i >= len(k.keys) {
return nil, nil return nil, nil
} }
return k.keys[i].PublicKey, nil switch key := k.keys[i].(type) {
case *rsa.PrivateKey:
return key.PublicKey, nil
case *dsa.PrivateKey:
return key.PublicKey, nil
}
panic("unknown key type")
} }
func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) { func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
...@@ -71,7 +81,11 @@ func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err err ...@@ -71,7 +81,11 @@ func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err err
h := hashFunc.New() h := hashFunc.New()
h.Write(data) h.Write(data)
digest := h.Sum(nil) digest := h.Sum(nil)
return rsa.SignPKCS1v15(rand, k.keys[i], hashFunc, digest) switch key := k.keys[i].(type) {
case *rsa.PrivateKey:
return rsa.SignPKCS1v15(rand, key, hashFunc, digest)
}
return nil, errors.New("unknown key type")
} }
func (k *keychain) loadPEM(file string) error { func (k *keychain) loadPEM(file string) error {
...@@ -91,158 +105,153 @@ func (k *keychain) loadPEM(file string) error { ...@@ -91,158 +105,153 @@ func (k *keychain) loadPEM(file string) error {
return nil return nil
} }
var pkey *rsa.PrivateKey // password implements the ClientPassword interface
type password string
func init() { func (p password) Password(user string) (string, error) {
var err error return string(p), nil
pkey, err = rsa.GenerateKey(rand.Reader, 512)
if err != nil {
panic("unable to generate public key")
}
} }
func TestClientAuthPublickey(t *testing.T) { // reused internally by tests
k := new(keychain) var (
k.keys = append(k.keys, pkey) rsakey *rsa.PrivateKey
dsakey *dsa.PrivateKey
clientKeychain = new(keychain)
clientPassword = password("tiger")
serverConfig = &ServerConfig{
PasswordCallback: func(user, pass string) bool {
return user == "testuser" && pass == string(clientPassword)
},
PubKeyCallback: func(user, algo string, pubkey []byte) bool {
key := clientKeychain.keys[0].(*rsa.PrivateKey).PublicKey
expected := []byte(serializePublickey(key))
algoname := algoName(key)
return user == "testuser" && algo == algoname && bytes.Equal(pubkey, expected)
},
}
)
serverConfig.PubKeyCallback = func(user, algo string, pubkey []byte) bool { func init() {
expected := []byte(serializePublickey(k.keys[0].PublicKey)) if err := serverConfig.SetRSAPrivateKey([]byte(testServerPrivateKey)); err != nil {
algoname := algoName(k.keys[0].PublicKey) panic("unable to set private key: " + err.Error())
return user == "testuser" && algo == algoname && bytes.Equal(pubkey, expected)
} }
serverConfig.PasswordCallback = nil
block, _ := pem.Decode([]byte(testClientPrivateKey))
rsakey, _ = x509.ParsePKCS1PrivateKey(block.Bytes)
clientKeychain.keys = append(clientKeychain.keys, rsakey)
dsakey = new(dsa.PrivateKey)
// taken from crypto/dsa/dsa_test.go
dsakey.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
dsakey.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A1F422B9C1", 16)
dsakey.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16)
dsakey.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
dsakey.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A", 16)
}
// newMockAuthServer creates a new Server bound to
// the loopback interface. The server exits after
// processing one handshake.
func newMockAuthServer(t *testing.T) string {
l, err := Listen("tcp", "127.0.0.1:0", serverConfig) l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
if err != nil { if err != nil {
t.Fatalf("unable to listen: %s", err) t.Fatalf("unable to newMockAuthServer: %s", err)
} }
defer l.Close()
done := make(chan bool, 1)
go func() { go func() {
defer l.Close()
c, err := l.Accept() c, err := l.Accept()
defer c.Close()
if err != nil { if err != nil {
t.Fatal(err) t.Errorf("Unable to accept incoming connection: %v", err)
return
} }
defer c.Close()
if err := c.Handshake(); err != nil { if err := c.Handshake(); err != nil {
t.Error(err) // not Errorf because this is expected to
// fail for some tests.
t.Logf("Handshaking error: %v", err)
return
} }
done <- true
}() }()
return l.Addr().String()
}
func TestClientAuthPublickey(t *testing.T) {
config := &ClientConfig{ config := &ClientConfig{
User: "testuser", User: "testuser",
Auth: []ClientAuth{ Auth: []ClientAuth{
ClientAuthPublickey(k), ClientAuthPublickey(clientKeychain),
}, },
} }
c, err := Dial("tcp", newMockAuthServer(t), config)
c, err := Dial("tcp", l.Addr().String(), config)
if err != nil { if err != nil {
t.Fatalf("unable to dial remote side: %s", err) t.Fatalf("unable to dial remote side: %s", err)
} }
defer c.Close() c.Close()
<-done
}
// password implements the ClientPassword interface
type password string
func (p password) Password(user string) (string, error) {
return string(p), nil
} }
func TestClientAuthPassword(t *testing.T) { func TestClientAuthPassword(t *testing.T) {
pw := password("tiger") config := &ClientConfig{
User: "testuser",
serverConfig.PasswordCallback = func(user, pass string) bool { Auth: []ClientAuth{
return user == "testuser" && pass == string(pw) ClientAuthPassword(clientPassword),
},
} }
serverConfig.PubKeyCallback = nil
l, err := Listen("tcp", "127.0.0.1:0", serverConfig) c, err := Dial("tcp", newMockAuthServer(t), config)
if err != nil { if err != nil {
t.Fatalf("unable to listen: %s", err) t.Fatalf("unable to dial remote side: %s", err)
} }
defer l.Close() c.Close()
}
done := make(chan bool)
go func() {
c, err := l.Accept()
if err != nil {
t.Fatal(err)
}
if err := c.Handshake(); err != nil {
t.Error(err)
}
defer c.Close()
done <- true
}()
func TestClientAuthWrongPassword(t *testing.T) {
wrongPw := password("wrong")
config := &ClientConfig{ config := &ClientConfig{
User: "testuser", User: "testuser",
Auth: []ClientAuth{ Auth: []ClientAuth{
ClientAuthPassword(pw), ClientAuthPassword(wrongPw),
ClientAuthPublickey(clientKeychain),
}, },
} }
c, err := Dial("tcp", l.Addr().String(), config) c, err := Dial("tcp", newMockAuthServer(t), config)
if err != nil { if err != nil {
t.Fatalf("unable to dial remote side: %s", err) t.Fatalf("unable to dial remote side: %s", err)
} }
defer c.Close() c.Close()
<-done
} }
func TestClientAuthPasswordAndPublickey(t *testing.T) { // the mock server will only authenticate ssh-rsa keys
pw := password("tiger") func TestClientAuthInvalidPublickey(t *testing.T) {
kc := new(keychain)
serverConfig.PasswordCallback = func(user, pass string) bool { kc.keys = append(kc.keys, dsakey)
return user == "testuser" && pass == string(pw) config := &ClientConfig{
} User: "testuser",
Auth: []ClientAuth{
k := new(keychain) ClientAuthPublickey(kc),
k.keys = append(k.keys, pkey) },
serverConfig.PubKeyCallback = func(user, algo string, pubkey []byte) bool {
expected := []byte(serializePublickey(k.keys[0].PublicKey))
algoname := algoName(k.keys[0].PublicKey)
return user == "testuser" && algo == algoname && bytes.Equal(pubkey, expected)
} }
l, err := Listen("tcp", "127.0.0.1:0", serverConfig) c, err := Dial("tcp", newMockAuthServer(t), config)
if err != nil { if err == nil {
t.Fatalf("unable to listen: %s", err) c.Close()
t.Fatalf("dsa private key should not have authenticated with rsa public key")
} }
defer l.Close() }
done := make(chan bool)
go func() {
c, err := l.Accept()
if err != nil {
t.Fatal(err)
}
if err := c.Handshake(); err != nil {
t.Error(err)
}
defer c.Close()
done <- true
}()
wrongPw := password("wrong") // the client should authenticate with the second key
func TestClientAuthRSAandDSA(t *testing.T) {
kc := new(keychain)
kc.keys = append(kc.keys, dsakey, rsakey)
config := &ClientConfig{ config := &ClientConfig{
User: "testuser", User: "testuser",
Auth: []ClientAuth{ Auth: []ClientAuth{
ClientAuthPassword(wrongPw), ClientAuthPublickey(kc),
ClientAuthPublickey(k),
}, },
} }
c, err := Dial("tcp", newMockAuthServer(t), config)
c, err := Dial("tcp", l.Addr().String(), config)
if err != nil { if err != nil {
t.Fatalf("unable to dial remote side: %s", err) t.Fatalf("client could not authenticate with rsa key: %v", err)
} }
defer c.Close() c.Close()
<-done
} }
...@@ -8,15 +8,15 @@ import ( ...@@ -8,15 +8,15 @@ import (
"testing" "testing"
) )
var strings = map[string]string{
"\x20\x0d\x0a": "\x20\x0d\x0a",
"flibble": "flibble",
"new\x20line": "new\x20line",
"123456\x07789": "123456 789",
"\t\t\x10\r\n": "\t\t \r\n",
}
func TestSafeString(t *testing.T) { func TestSafeString(t *testing.T) {
strings := map[string]string{
"\x20\x0d\x0a": "\x20\x0d\x0a",
"flibble": "flibble",
"new\x20line": "new\x20line",
"123456\x07789": "123456 789",
"\t\t\x10\r\n": "\t\t \r\n",
}
for s, expected := range strings { for s, expected := range strings {
actual := safeString(s) actual := safeString(s)
if expected != actual { if expected != actual {
......
...@@ -285,13 +285,8 @@ func (s *Session) stdin() error { ...@@ -285,13 +285,8 @@ func (s *Session) stdin() error {
s.Stdin = new(bytes.Buffer) s.Stdin = new(bytes.Buffer)
} }
s.copyFuncs = append(s.copyFuncs, func() error { s.copyFuncs = append(s.copyFuncs, func() error {
w := &chanWriter{ _, err := io.Copy(s.clientChan.stdin, s.Stdin)
packetWriter: s, if err1 := s.clientChan.stdin.Close(); err == nil {
peersId: s.peersId,
win: s.win,
}
_, err := io.Copy(w, s.Stdin)
if err1 := w.Close(); err == nil {
err = err1 err = err1
} }
return err return err
...@@ -304,12 +299,7 @@ func (s *Session) stdout() error { ...@@ -304,12 +299,7 @@ func (s *Session) stdout() error {
s.Stdout = ioutil.Discard s.Stdout = ioutil.Discard
} }
s.copyFuncs = append(s.copyFuncs, func() error { s.copyFuncs = append(s.copyFuncs, func() error {
r := &chanReader{ _, err := io.Copy(s.Stdout, s.clientChan.stdout)
packetWriter: s,
peersId: s.peersId,
data: s.data,
}
_, err := io.Copy(s.Stdout, r)
return err return err
}) })
return nil return nil
...@@ -320,12 +310,7 @@ func (s *Session) stderr() error { ...@@ -320,12 +310,7 @@ func (s *Session) stderr() error {
s.Stderr = ioutil.Discard s.Stderr = ioutil.Discard
} }
s.copyFuncs = append(s.copyFuncs, func() error { s.copyFuncs = append(s.copyFuncs, func() error {
r := &chanReader{ _, err := io.Copy(s.Stderr, s.clientChan.stderr)
packetWriter: s,
peersId: s.peersId,
data: s.dataExt,
}
_, err := io.Copy(s.Stderr, r)
return err return err
}) })
return nil return nil
...@@ -398,19 +383,11 @@ func (c *ClientConn) NewSession() (*Session, error) { ...@@ -398,19 +383,11 @@ func (c *ClientConn) NewSession() (*Session, error) {
c.chanlist.remove(ch.id) c.chanlist.remove(ch.id)
return nil, err return nil, err
} }
// wait for response if err := ch.waitForChannelOpenResponse(); err != nil {
msg := <-ch.msg
switch msg := msg.(type) {
case *channelOpenConfirmMsg:
ch.peersId = msg.MyId
ch.win <- int(msg.MyWindow)
return &Session{
clientChan: ch,
}, nil
case *channelOpenFailureMsg:
c.chanlist.remove(ch.id) c.chanlist.remove(ch.id)
return nil, fmt.Errorf("ssh: channel open failed: %s", msg.Message) return nil, fmt.Errorf("ssh: unable to open session: %v", err)
} }
c.chanlist.remove(ch.id) return &Session{
return nil, fmt.Errorf("ssh: unexpected message %T: %v", msg, msg) clientChan: ch,
}, nil
} }
...@@ -61,7 +61,7 @@ func dial(t *testing.T) *ClientConn { ...@@ -61,7 +61,7 @@ func dial(t *testing.T) *ClientConn {
WantReply bool WantReply bool
Status uint32 Status uint32
} }
// TODO(dfc) casting to the concrete type should not be // TODO(dfc) converting to the concrete type should not be
// necessary to send a packet. // necessary to send a packet.
msg := exitMsg{ msg := exitMsg{
PeersId: ch.(*channel).theirId, PeersId: ch.(*channel).theirId,
......
...@@ -6,6 +6,7 @@ package ssh ...@@ -6,6 +6,7 @@ package ssh
import ( import (
"errors" "errors"
"fmt"
"io" "io"
"net" "net"
) )
...@@ -42,20 +43,21 @@ func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, err ...@@ -42,20 +43,21 @@ func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, err
}, nil }, nil
} }
// RFC 4254 7.2
type channelOpenDirectMsg struct {
ChanType string
PeersId uint32
PeersWindow uint32
MaxPacketSize uint32
raddr string
rport uint32
laddr string
lport uint32
}
// dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as // dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as
// strings and are expected to be resolveable at the remote end. // strings and are expected to be resolveable at the remote end.
func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpchan, error) { func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpchan, error) {
// RFC 4254 7.2
type channelOpenDirectMsg struct {
ChanType string
PeersId uint32
PeersWindow uint32
MaxPacketSize uint32
raddr string
rport uint32
laddr string
lport uint32
}
ch := c.newChan(c.transport) ch := c.newChan(c.transport)
if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{ if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{
ChanType: "direct-tcpip", ChanType: "direct-tcpip",
...@@ -70,30 +72,14 @@ func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tc ...@@ -70,30 +72,14 @@ func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tc
c.chanlist.remove(ch.id) c.chanlist.remove(ch.id)
return nil, err return nil, err
} }
// wait for response if err := ch.waitForChannelOpenResponse(); err != nil {
switch msg := (<-ch.msg).(type) {
case *channelOpenConfirmMsg:
ch.peersId = msg.MyId
ch.win <- int(msg.MyWindow)
case *channelOpenFailureMsg:
c.chanlist.remove(ch.id)
return nil, errors.New("ssh: error opening remote TCP connection: " + msg.Message)
default:
c.chanlist.remove(ch.id) c.chanlist.remove(ch.id)
return nil, errors.New("ssh: unexpected packet") return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err)
} }
return &tcpchan{ return &tcpchan{
clientChan: ch, clientChan: ch,
Reader: &chanReader{ Reader: ch.stdout,
packetWriter: ch, Writer: ch.stdin,
peersId: ch.peersId,
data: ch.data,
},
Writer: &chanWriter{
packetWriter: ch,
peersId: ch.peersId,
win: ch.win,
},
}, nil }, nil
} }
......
...@@ -305,7 +305,7 @@ func (p *gcParser) parseArrayType() Type { ...@@ -305,7 +305,7 @@ func (p *gcParser) parseArrayType() Type {
lit := p.expect(scanner.Int) lit := p.expect(scanner.Int)
p.expect(']') p.expect(']')
elt := p.parseType() elt := p.parseType()
n, err := strconv.Atoui64(lit) n, err := strconv.ParseUint(lit, 10, 64)
if err != nil { if err != nil {
p.error(err) p.error(err)
} }
...@@ -323,7 +323,7 @@ func (p *gcParser) parseMapType() Type { ...@@ -323,7 +323,7 @@ func (p *gcParser) parseMapType() Type {
return &Map{Key: key, Elt: elt} return &Map{Key: key, Elt: elt}
} }
// Name = identifier | "?" . // Name = identifier | "?" | ExportedName .
// //
func (p *gcParser) parseName() (name string) { func (p *gcParser) parseName() (name string) {
switch p.tok { switch p.tok {
...@@ -333,6 +333,9 @@ func (p *gcParser) parseName() (name string) { ...@@ -333,6 +333,9 @@ func (p *gcParser) parseName() (name string) {
case '?': case '?':
// anonymous // anonymous
p.next() p.next()
case '@':
// exported name prefixed with package path
_, name = p.parseExportedName()
default: default:
p.error("name expected") p.error("name expected")
} }
...@@ -619,10 +622,11 @@ func (p *gcParser) parseNumber() Const { ...@@ -619,10 +622,11 @@ func (p *gcParser) parseNumber() Const {
// exponent (base 2) // exponent (base 2)
p.next() p.next()
sign, val = p.parseInt() sign, val = p.parseInt()
exp, err := strconv.Atoui(val) exp64, err := strconv.ParseUint(val, 10, 0)
if err != nil { if err != nil {
p.error(err) p.error(err)
} }
exp := uint(exp64)
if sign == "-" { if sign == "-" {
denom := big.NewInt(1) denom := big.NewInt(1)
denom.Lsh(denom, exp) denom.Lsh(denom, exp)
...@@ -747,7 +751,7 @@ func (p *gcParser) parseFuncDecl() { ...@@ -747,7 +751,7 @@ func (p *gcParser) parseFuncDecl() {
} }
} }
// MethodDecl = "func" Receiver identifier Signature . // MethodDecl = "func" Receiver Name Signature .
// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ]. // Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ].
// //
func (p *gcParser) parseMethodDecl() { func (p *gcParser) parseMethodDecl() {
...@@ -755,7 +759,7 @@ func (p *gcParser) parseMethodDecl() { ...@@ -755,7 +759,7 @@ func (p *gcParser) parseMethodDecl() {
p.expect('(') p.expect('(')
p.parseParameter() // receiver p.parseParameter() // receiver
p.expect(')') p.expect(')')
p.expect(scanner.Ident) p.parseName() // unexported method names in imports are qualified with their package.
p.parseSignature() p.parseSignature()
if p.tok == '{' { if p.tok == '{' {
p.parseFuncBody() p.parseFuncBody()
......
...@@ -44,7 +44,7 @@ type Int struct { ...@@ -44,7 +44,7 @@ type Int struct {
mu sync.Mutex mu sync.Mutex
} }
func (v *Int) String() string { return strconv.Itoa64(v.i) } func (v *Int) String() string { return strconv.FormatInt(v.i, 10) }
func (v *Int) Add(delta int64) { func (v *Int) Add(delta int64) {
v.mu.Lock() v.mu.Lock()
...@@ -64,7 +64,7 @@ type Float struct { ...@@ -64,7 +64,7 @@ type Float struct {
mu sync.Mutex mu sync.Mutex
} }
func (v *Float) String() string { return strconv.Ftoa64(v.f, 'g', -1) } func (v *Float) String() string { return strconv.FormatFloat(v.f, 'g', -1, 64) }
// Add adds delta to v. // Add adds delta to v.
func (v *Float) Add(delta float64) { func (v *Float) Add(delta float64) {
......
...@@ -79,7 +79,7 @@ func newBoolValue(val bool, p *bool) *boolValue { ...@@ -79,7 +79,7 @@ func newBoolValue(val bool, p *bool) *boolValue {
} }
func (b *boolValue) Set(s string) bool { func (b *boolValue) Set(s string) bool {
v, err := strconv.Atob(s) v, err := strconv.ParseBool(s)
*b = boolValue(v) *b = boolValue(v)
return err == nil return err == nil
} }
...@@ -95,7 +95,7 @@ func newIntValue(val int, p *int) *intValue { ...@@ -95,7 +95,7 @@ func newIntValue(val int, p *int) *intValue {
} }
func (i *intValue) Set(s string) bool { func (i *intValue) Set(s string) bool {
v, err := strconv.Btoi64(s, 0) v, err := strconv.ParseInt(s, 0, 64)
*i = intValue(v) *i = intValue(v)
return err == nil return err == nil
} }
...@@ -111,7 +111,7 @@ func newInt64Value(val int64, p *int64) *int64Value { ...@@ -111,7 +111,7 @@ func newInt64Value(val int64, p *int64) *int64Value {
} }
func (i *int64Value) Set(s string) bool { func (i *int64Value) Set(s string) bool {
v, err := strconv.Btoi64(s, 0) v, err := strconv.ParseInt(s, 0, 64)
*i = int64Value(v) *i = int64Value(v)
return err == nil return err == nil
} }
...@@ -127,7 +127,7 @@ func newUintValue(val uint, p *uint) *uintValue { ...@@ -127,7 +127,7 @@ func newUintValue(val uint, p *uint) *uintValue {
} }
func (i *uintValue) Set(s string) bool { func (i *uintValue) Set(s string) bool {
v, err := strconv.Btoui64(s, 0) v, err := strconv.ParseUint(s, 0, 64)
*i = uintValue(v) *i = uintValue(v)
return err == nil return err == nil
} }
...@@ -143,7 +143,7 @@ func newUint64Value(val uint64, p *uint64) *uint64Value { ...@@ -143,7 +143,7 @@ func newUint64Value(val uint64, p *uint64) *uint64Value {
} }
func (i *uint64Value) Set(s string) bool { func (i *uint64Value) Set(s string) bool {
v, err := strconv.Btoui64(s, 0) v, err := strconv.ParseUint(s, 0, 64)
*i = uint64Value(v) *i = uint64Value(v)
return err == nil return err == nil
} }
...@@ -174,7 +174,7 @@ func newFloat64Value(val float64, p *float64) *float64Value { ...@@ -174,7 +174,7 @@ func newFloat64Value(val float64, p *float64) *float64Value {
} }
func (f *float64Value) Set(s string) bool { func (f *float64Value) Set(s string) bool {
v, err := strconv.Atof64(s) v, err := strconv.ParseFloat(s, 64)
*f = float64Value(v) *f = float64Value(v)
return err == nil return err == nil
} }
......
...@@ -89,18 +89,22 @@ ...@@ -89,18 +89,22 @@
If an operand implements interface Formatter, that interface If an operand implements interface Formatter, that interface
can be used for fine control of formatting. can be used for fine control of formatting.
Next, if an operand implements the error interface, the Error method If the format (which is implicitly %v for Println etc.) is valid
for a string (%s %q %v %x %X), the following two rules also apply:
1. If an operand implements the error interface, the Error method
will be used to convert the object to a string, which will then will be used to convert the object to a string, which will then
be formatted as required by the verb (if any). be formatted as required by the verb (if any).
Finally, if an operand implements method String() string that method 2. If an operand implements method String() string, that method
will be used to convert the object to a string, which will then will be used to convert the object to a string, which will then
be formatted as required by the verb (if any). be formatted as required by the verb (if any).
To avoid recursion in cases such as To avoid recursion in cases such as
type X int type X string
func (x X) String() string { return Sprintf("%d", x) } func (x X) String() string { return Sprintf("<%s>", x) }
cast the value before recurring: convert the value before recurring:
func (x X) String() string { return Sprintf("%d", int(x)) } func (x X) String() string { return Sprintf("<%s>", string(x)) }
Format errors: Format errors:
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"runtime" // for the malloc count test only "runtime" // for the malloc count test only
"strings" "strings"
"testing" "testing"
"time"
) )
type ( type (
...@@ -352,7 +353,7 @@ var fmttests = []struct { ...@@ -352,7 +353,7 @@ var fmttests = []struct {
{"%s", I(23), `<23>`}, {"%s", I(23), `<23>`},
{"%q", I(23), `"<23>"`}, {"%q", I(23), `"<23>"`},
{"%x", I(23), `3c32333e`}, {"%x", I(23), `3c32333e`},
{"%d", I(23), `%!d(string=<23>)`}, {"%d", I(23), `23`}, // Stringer applies only to string formats.
// go syntax // go syntax
{"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`}, {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`},
...@@ -361,8 +362,8 @@ var fmttests = []struct { ...@@ -361,8 +362,8 @@ var fmttests = []struct {
{"%#v", make(chan int), "(chan int)(0xPTR)"}, {"%#v", make(chan int), "(chan int)(0xPTR)"},
{"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"}, {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"},
{"%#v", 1000000000, "1000000000"}, {"%#v", 1000000000, "1000000000"},
{"%#v", map[string]int{"a": 1}, `map[string] int{"a":1}`}, {"%#v", map[string]int{"a": 1}, `map[string]int{"a":1}`},
{"%#v", map[string]B{"a": {1, 2}}, `map[string] fmt_test.B{"a":fmt_test.B{I:1, j:2}}`}, {"%#v", map[string]B{"a": {1, 2}}, `map[string]fmt_test.B{"a":fmt_test.B{I:1, j:2}}`},
{"%#v", []string{"a", "b"}, `[]string{"a", "b"}`}, {"%#v", []string{"a", "b"}, `[]string{"a", "b"}`},
{"%#v", SI{}, `fmt_test.SI{I:interface {}(nil)}`}, {"%#v", SI{}, `fmt_test.SI{I:interface {}(nil)}`},
{"%#v", []int(nil), `[]int(nil)`}, {"%#v", []int(nil), `[]int(nil)`},
...@@ -371,8 +372,8 @@ var fmttests = []struct { ...@@ -371,8 +372,8 @@ var fmttests = []struct {
{"%#v", &array, `&[5]int{1, 2, 3, 4, 5}`}, {"%#v", &array, `&[5]int{1, 2, 3, 4, 5}`},
{"%#v", iarray, `[4]interface {}{1, "hello", 2.5, interface {}(nil)}`}, {"%#v", iarray, `[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
{"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`}, {"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
{"%#v", map[int]byte(nil), `map[int] uint8(nil)`}, {"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
{"%#v", map[int]byte{}, `map[int] uint8{}`}, {"%#v", map[int]byte{}, `map[int]uint8{}`},
// slices with other formats // slices with other formats
{"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`}, {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
...@@ -430,6 +431,10 @@ var fmttests = []struct { ...@@ -430,6 +431,10 @@ var fmttests = []struct {
{"%p", make([]int, 1), "0xPTR"}, {"%p", make([]int, 1), "0xPTR"},
{"%p", 27, "%!p(int=27)"}, // not a pointer at all {"%p", 27, "%!p(int=27)"}, // not a pointer at all
// %d on Stringer should give integer if possible
{"%s", time.Time{}.Month(), "January"},
{"%d", time.Time{}.Month(), "1"},
// erroneous things // erroneous things
{"%s %", "hello", "hello %!(NOVERB)"}, {"%s %", "hello", "hello %!(NOVERB)"},
{"%s %.2", "hello", "hello %!(NOVERB)"}, {"%s %.2", "hello", "hello %!(NOVERB)"},
...@@ -495,69 +500,84 @@ func BenchmarkSprintfPrefixedInt(b *testing.B) { ...@@ -495,69 +500,84 @@ func BenchmarkSprintfPrefixedInt(b *testing.B) {
} }
} }
func BenchmarkSprintfFloat(b *testing.B) {
for i := 0; i < b.N; i++ {
Sprintf("%g", 5.23184)
}
}
func TestCountMallocs(t *testing.T) { func TestCountMallocs(t *testing.T) {
if testing.Short() { if testing.Short() {
return return
} }
const N = 100
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs := 0 - runtime.MemStats.Mallocs mallocs := 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ { for i := 0; i < N; i++ {
Sprintf("") Sprintf("")
} }
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"\"): %d\n", mallocs/100) Printf("mallocs per Sprintf(\"\"): %d\n", mallocs/N)
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ { for i := 0; i < N; i++ {
Sprintf("xxx") Sprintf("xxx")
} }
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"xxx\"): %d\n", mallocs/100) Printf("mallocs per Sprintf(\"xxx\"): %d\n", mallocs/N)
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ { for i := 0; i < N; i++ {
Sprintf("%x", i) Sprintf("%x", i)
} }
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"%%x\"): %d\n", mallocs/100) Printf("mallocs per Sprintf(\"%%x\"): %d\n", mallocs/N)
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ { for i := 0; i < N; i++ {
Sprintf("%s", "hello") Sprintf("%s", "hello")
} }
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"%%s\"): %d\n", mallocs/100) Printf("mallocs per Sprintf(\"%%s\"): %d\n", mallocs/N)
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ { for i := 0; i < N; i++ {
Sprintf("%x %x", i, i) Sprintf("%x %x", i, i)
} }
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/100) Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/N)
runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < N; i++ {
Sprintf("%g", 3.14159)
}
runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"%%g\"): %d\n", mallocs/N)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ { for i := 0; i < N; i++ {
buf.Reset() buf.Reset()
Fprintf(buf, "%x %x %x", i, i, i) Fprintf(buf, "%x %x %x", i, i, i)
} }
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Fprintf(buf, \"%%x %%x %%x\"): %d\n", mallocs/100) Printf("mallocs per Fprintf(buf, \"%%x %%x %%x\"): %d\n", mallocs/N)
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ { for i := 0; i < N; i++ {
buf.Reset() buf.Reset()
Fprintf(buf, "%s", "hello") Fprintf(buf, "%s", "hello")
} }
runtime.UpdateMemStats() runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Fprintf(buf, \"%%s\"): %d\n", mallocs/100) Printf("mallocs per Fprintf(buf, \"%%s\"): %d\n", mallocs/N)
} }
type flagPrinter struct{} type flagPrinter struct{}
...@@ -772,9 +792,9 @@ var panictests = []struct { ...@@ -772,9 +792,9 @@ var panictests = []struct {
out string out string
}{ }{
// String // String
{"%d", (*Panic)(nil), "<nil>"}, // nil pointer special case {"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case
{"%d", Panic{io.ErrUnexpectedEOF}, "%d(PANIC=unexpected EOF)"}, {"%s", Panic{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
{"%d", Panic{3}, "%d(PANIC=3)"}, {"%s", Panic{3}, "%s(PANIC=3)"},
// GoString // GoString
{"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case {"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case
{"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"}, {"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"},
......
...@@ -360,44 +360,44 @@ func (f *fmt) plusSpace(s string) { ...@@ -360,44 +360,44 @@ func (f *fmt) plusSpace(s string) {
} }
// fmt_e64 formats a float64 in the form -1.23e+12. // fmt_e64 formats a float64 in the form -1.23e+12.
func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) } func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'e', doPrec(f, 6), 64)) }
// fmt_E64 formats a float64 in the form -1.23E+12. // fmt_E64 formats a float64 in the form -1.23E+12.
func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) } func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'E', doPrec(f, 6), 64)) }
// fmt_f64 formats a float64 in the form -1.23. // fmt_f64 formats a float64 in the form -1.23.
func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) } func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'f', doPrec(f, 6), 64)) }
// fmt_g64 formats a float64 in the 'f' or 'e' form according to size. // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) } func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'g', doPrec(f, -1), 64)) }
// fmt_g64 formats a float64 in the 'f' or 'E' form according to size. // fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) } func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'G', doPrec(f, -1), 64)) }
// fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2). // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'b', 0)) } func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'b', 0, 64)) }
// float32 // float32
// cannot defer to float64 versions // cannot defer to float64 versions
// because it will get rounding wrong in corner cases. // because it will get rounding wrong in corner cases.
// fmt_e32 formats a float32 in the form -1.23e+12. // fmt_e32 formats a float32 in the form -1.23e+12.
func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) } func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'e', doPrec(f, 6), 32)) }
// fmt_E32 formats a float32 in the form -1.23E+12. // fmt_E32 formats a float32 in the form -1.23E+12.
func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) } func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'E', doPrec(f, 6), 32)) }
// fmt_f32 formats a float32 in the form -1.23. // fmt_f32 formats a float32 in the form -1.23.
func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) } func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'f', doPrec(f, 6), 32)) }
// fmt_g32 formats a float32 in the 'f' or 'e' form according to size. // fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) } func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'g', doPrec(f, -1), 32)) }
// fmt_G32 formats a float32 in the 'f' or 'E' form according to size. // fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) } func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'G', doPrec(f, -1), 32)) }
// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2). // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) } func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.FormatFloat(float64(v), 'b', 0, 32)) }
// fmt_c64 formats a complex64 according to the verb. // fmt_c64 formats a complex64 according to the verb.
func (f *fmt) fmt_c64(v complex64, verb rune) { func (f *fmt) fmt_c64(v complex64, verb rune) {
......
...@@ -631,24 +631,30 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString ...@@ -631,24 +631,30 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
return return
} }
} else { } else {
// Is it an error or Stringer? // If a string is acceptable according to the format, see if
// The duplication in the bodies is necessary: // the value satisfies one of the string-valued interfaces.
// setting wasString and handled and deferring catchPanic // Println etc. set verb to %v, which is "stringable".
// must happen before calling the method. switch verb {
switch v := p.field.(type) { case 'v', 's', 'x', 'X', 'q':
case error: // Is it an error or Stringer?
wasString = false // The duplication in the bodies is necessary:
handled = true // setting wasString and handled, and deferring catchPanic,
defer p.catchPanic(p.field, verb) // must happen before calling the method.
p.printField(v.Error(), verb, plus, false, depth) switch v := p.field.(type) {
return case error:
wasString = false
case Stringer: handled = true
wasString = false defer p.catchPanic(p.field, verb)
handled = true p.printField(v.Error(), verb, plus, false, depth)
defer p.catchPanic(p.field, verb) return
p.printField(v.String(), verb, plus, false, depth)
return case Stringer:
wasString = false
handled = true
defer p.catchPanic(p.field, verb)
p.printField(v.String(), verb, plus, false, depth)
return
}
} }
} }
handled = false handled = false
......
...@@ -613,7 +613,7 @@ func (s *ss) scanInt(verb rune, bitSize int) int64 { ...@@ -613,7 +613,7 @@ func (s *ss) scanInt(verb rune, bitSize int) int64 {
} }
} }
tok := s.scanNumber(digits, haveDigits) tok := s.scanNumber(digits, haveDigits)
i, err := strconv.Btoi64(tok, base) i, err := strconv.ParseInt(tok, base, 64)
if err != nil { if err != nil {
s.error(err) s.error(err)
} }
...@@ -643,7 +643,7 @@ func (s *ss) scanUint(verb rune, bitSize int) uint64 { ...@@ -643,7 +643,7 @@ func (s *ss) scanUint(verb rune, bitSize int) uint64 {
base, digits, haveDigits = s.scanBasePrefix() base, digits, haveDigits = s.scanBasePrefix()
} }
tok := s.scanNumber(digits, haveDigits) tok := s.scanNumber(digits, haveDigits)
i, err := strconv.Btoui64(tok, base) i, err := strconv.ParseUint(tok, base, 64)
if err != nil { if err != nil {
s.error(err) s.error(err)
} }
...@@ -719,7 +719,7 @@ func (s *ss) convertFloat(str string, n int) float64 { ...@@ -719,7 +719,7 @@ func (s *ss) convertFloat(str string, n int) float64 {
if p := strings.Index(str, "p"); p >= 0 { if p := strings.Index(str, "p"); p >= 0 {
// Atof doesn't handle power-of-2 exponents, // Atof doesn't handle power-of-2 exponents,
// but they're easy to evaluate. // but they're easy to evaluate.
f, err := strconv.AtofN(str[:p], n) f, err := strconv.ParseFloat(str[:p], n)
if err != nil { if err != nil {
// Put full string into error. // Put full string into error.
if e, ok := err.(*strconv.NumError); ok { if e, ok := err.(*strconv.NumError); ok {
...@@ -737,7 +737,7 @@ func (s *ss) convertFloat(str string, n int) float64 { ...@@ -737,7 +737,7 @@ func (s *ss) convertFloat(str string, n int) float64 {
} }
return math.Ldexp(f, n) return math.Ldexp(f, n)
} }
f, err := strconv.AtofN(str, n) f, err := strconv.ParseFloat(str, n)
if err != nil { if err != nil {
s.error(err) s.error(err)
} }
......
...@@ -24,7 +24,7 @@ var tests = []struct { ...@@ -24,7 +24,7 @@ var tests = []struct {
// maps // maps
{map[string]int{"a": 1}, {map[string]int{"a": 1},
`0 map[string] int (len = 1) { `0 map[string]int (len = 1) {
1 . "a": 1 1 . "a": 1
2 }`}, 2 }`},
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
package doc package doc
import ( import (
"bytes"
"go/ast" "go/ast"
"io" "io"
"regexp" "regexp"
...@@ -85,39 +84,6 @@ func CommentText(comment *ast.CommentGroup) string { ...@@ -85,39 +84,6 @@ func CommentText(comment *ast.CommentGroup) string {
return strings.Join(lines, "\n") return strings.Join(lines, "\n")
} }
// Split bytes into lines.
func split(text []byte) [][]byte {
// count lines
n := 0
last := 0
for i, c := range text {
if c == '\n' {
last = i + 1
n++
}
}
if last < len(text) {
n++
}
// split
out := make([][]byte, n)
last = 0
n = 0
for i, c := range text {
if c == '\n' {
out[n] = text[last : i+1]
last = i + 1
n++
}
}
if last < len(text) {
out[n] = text[last:]
}
return out
}
var ( var (
ldquo = []byte("&ldquo;") ldquo = []byte("&ldquo;")
rdquo = []byte("&rdquo;") rdquo = []byte("&rdquo;")
...@@ -125,13 +91,13 @@ var ( ...@@ -125,13 +91,13 @@ var (
// Escape comment text for HTML. If nice is set, // Escape comment text for HTML. If nice is set,
// also turn `` into &ldquo; and '' into &rdquo;. // also turn `` into &ldquo; and '' into &rdquo;.
func commentEscape(w io.Writer, s []byte, nice bool) { func commentEscape(w io.Writer, text string, nice bool) {
last := 0 last := 0
if nice { if nice {
for i := 0; i < len(s)-1; i++ { for i := 0; i < len(text)-1; i++ {
ch := s[i] ch := text[i]
if ch == s[i+1] && (ch == '`' || ch == '\'') { if ch == text[i+1] && (ch == '`' || ch == '\'') {
template.HTMLEscape(w, s[last:i]) template.HTMLEscape(w, []byte(text[last:i]))
last = i + 2 last = i + 2
switch ch { switch ch {
case '`': case '`':
...@@ -143,7 +109,7 @@ func commentEscape(w io.Writer, s []byte, nice bool) { ...@@ -143,7 +109,7 @@ func commentEscape(w io.Writer, s []byte, nice bool) {
} }
} }
} }
template.HTMLEscape(w, s[last:]) template.HTMLEscape(w, []byte(text[last:]))
} }
const ( const (
...@@ -183,9 +149,9 @@ var ( ...@@ -183,9 +149,9 @@ var (
// and the word is converted into a link. If nice is set, the remaining text's // and the word is converted into a link. If nice is set, the remaining text's
// appearance is improved where it makes sense (e.g., `` is turned into &ldquo; // appearance is improved where it makes sense (e.g., `` is turned into &ldquo;
// and '' into &rdquo;). // and '' into &rdquo;).
func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) { func emphasize(w io.Writer, line string, words map[string]string, nice bool) {
for { for {
m := matchRx.FindSubmatchIndex(line) m := matchRx.FindStringSubmatchIndex(line)
if m == nil { if m == nil {
break break
} }
...@@ -233,7 +199,7 @@ func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) { ...@@ -233,7 +199,7 @@ func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) {
commentEscape(w, line, nice) commentEscape(w, line, nice)
} }
func indentLen(s []byte) int { func indentLen(s string) int {
i := 0 i := 0
for i < len(s) && (s[i] == ' ' || s[i] == '\t') { for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
i++ i++
...@@ -241,9 +207,11 @@ func indentLen(s []byte) int { ...@@ -241,9 +207,11 @@ func indentLen(s []byte) int {
return i return i
} }
func isBlank(s []byte) bool { return len(s) == 0 || (len(s) == 1 && s[0] == '\n') } func isBlank(s string) bool {
return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
}
func commonPrefix(a, b []byte) []byte { func commonPrefix(a, b string) string {
i := 0 i := 0
for i < len(a) && i < len(b) && a[i] == b[i] { for i < len(a) && i < len(b) && a[i] == b[i] {
i++ i++
...@@ -251,7 +219,7 @@ func commonPrefix(a, b []byte) []byte { ...@@ -251,7 +219,7 @@ func commonPrefix(a, b []byte) []byte {
return a[0:i] return a[0:i]
} }
func unindent(block [][]byte) { func unindent(block []string) {
if len(block) == 0 { if len(block) == 0 {
return return
} }
...@@ -273,44 +241,39 @@ func unindent(block [][]byte) { ...@@ -273,44 +241,39 @@ func unindent(block [][]byte) {
} }
} }
// heading returns the (possibly trimmed) line if it passes as a valid section // heading returns the trimmed line if it passes as a section heading;
// heading; otherwise it returns nil. // otherwise it returns the empty string.
func heading(line []byte) []byte { func heading(line string) string {
line = bytes.TrimSpace(line) line = strings.TrimSpace(line)
if len(line) == 0 { if len(line) == 0 {
return nil return ""
} }
// a heading must start with an uppercase letter // a heading must start with an uppercase letter
r, _ := utf8.DecodeRune(line) r, _ := utf8.DecodeRuneInString(line)
if !unicode.IsLetter(r) || !unicode.IsUpper(r) { if !unicode.IsLetter(r) || !unicode.IsUpper(r) {
return nil return ""
}
// it must end in a letter, digit or ':'
r, _ = utf8.DecodeLastRune(line)
if !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != ':' {
return nil
} }
// strip trailing ':', if any // it must end in a letter or digit:
if r == ':' { r, _ = utf8.DecodeLastRuneInString(line)
line = line[0 : len(line)-1] if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
return ""
} }
// exclude lines with illegal characters // exclude lines with illegal characters
if bytes.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 { if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 {
return nil return ""
} }
// allow "'" for possessive "'s" only // allow "'" for possessive "'s" only
for b := line; ; { for b := line; ; {
i := bytes.IndexRune(b, '\'') i := strings.IndexRune(b, '\'')
if i < 0 { if i < 0 {
break break
} }
if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') { if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') {
return nil // not followed by "s " return "" // not followed by "s "
} }
b = b[i+2:] b = b[i+2:]
} }
...@@ -335,7 +298,7 @@ func heading(line []byte) []byte { ...@@ -335,7 +298,7 @@ func heading(line []byte) []byte {
// Go identifiers that appear in the words map are italicized; if the corresponding // Go identifiers that appear in the words map are italicized; if the corresponding
// map value is not the empty string, it is considered a URL and the word is converted // map value is not the empty string, it is considered a URL and the word is converted
// into a link. // into a link.
func ToHTML(w io.Writer, s []byte, words map[string]string) { func ToHTML(w io.Writer, text string, words map[string]string) {
inpara := false inpara := false
lastWasBlank := false lastWasBlank := false
lastWasHeading := false lastWasHeading := false
...@@ -353,7 +316,7 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) { ...@@ -353,7 +316,7 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) {
} }
} }
lines := split(s) lines := strings.SplitAfter(text, "\n")
unindent(lines) unindent(lines)
for i := 0; i < len(lines); { for i := 0; i < len(lines); {
line := lines[i] line := lines[i]
...@@ -397,10 +360,10 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) { ...@@ -397,10 +360,10 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) {
// current line is non-blank, sourounded by blank lines // current line is non-blank, sourounded by blank lines
// and the next non-blank line is not indented: this // and the next non-blank line is not indented: this
// might be a heading. // might be a heading.
if head := heading(line); head != nil { if head := heading(line); head != "" {
close() close()
w.Write(html_h) w.Write(html_h)
template.HTMLEscape(w, head) commentEscape(w, head, true) // nice text formatting
w.Write(html_endh) w.Write(html_endh)
i += 2 i += 2
lastWasHeading = true lastWasHeading = true
......
...@@ -18,7 +18,8 @@ var headingTests = []struct { ...@@ -18,7 +18,8 @@ var headingTests = []struct {
{"Foo 42", true}, {"Foo 42", true},
{"", false}, {"", false},
{"section", false}, {"section", false},
{"A typical usage:", true}, {"A typical usage:", false},
{"This code:", false},
{"δ is Greek", false}, {"δ is Greek", false},
{"Foo §", false}, {"Foo §", false},
{"Fermat's Last Sentence", true}, {"Fermat's Last Sentence", true},
...@@ -26,13 +27,13 @@ var headingTests = []struct { ...@@ -26,13 +27,13 @@ var headingTests = []struct {
{"'sX", false}, {"'sX", false},
{"Ted 'Too' Bar", false}, {"Ted 'Too' Bar", false},
{"Use n+m", false}, {"Use n+m", false},
{"Scanning:", true}, {"Scanning:", false},
{"N:M", false}, {"N:M", false},
} }
func TestIsHeading(t *testing.T) { func TestIsHeading(t *testing.T) {
for _, tt := range headingTests { for _, tt := range headingTests {
if h := heading([]byte(tt.line)); (h != nil) != tt.ok { if h := heading(tt.line); (len(h) > 0) != tt.ok {
t.Errorf("isHeading(%q) = %v, want %v", tt.line, h, tt.ok) t.Errorf("isHeading(%q) = %v, want %v", tt.line, h, tt.ok)
} }
} }
......
...@@ -43,7 +43,7 @@ func isGoFile(fi os.FileInfo) bool { ...@@ -43,7 +43,7 @@ func isGoFile(fi os.FileInfo) bool {
func appendHeadings(list []string, comment string) []string { func appendHeadings(list []string, comment string) []string {
var buf bytes.Buffer var buf bytes.Buffer
doc.ToHTML(&buf, []byte(comment), nil) doc.ToHTML(&buf, comment, nil)
for s := buf.String(); ; { for s := buf.String(); ; {
i := strings.Index(s, html_h) i := strings.Index(s, html_h)
if i < 0 { if i < 0 {
......
...@@ -2026,7 +2026,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList { ...@@ -2026,7 +2026,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
// must have exactly one receiver // must have exactly one receiver
if par.NumFields() != 1 { if par.NumFields() != 1 {
p.errorExpected(par.Opening, "exactly one receiver") p.errorExpected(par.Opening, "exactly one receiver")
par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{par.Opening, par.Closing + 1}}} par.List = []*ast.Field{{Type: &ast.BadExpr{par.Opening, par.Closing + 1}}}
return par return par
} }
...@@ -2035,7 +2035,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList { ...@@ -2035,7 +2035,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
base := deref(recv.Type) base := deref(recv.Type)
if _, isIdent := base.(*ast.Ident); !isIdent { if _, isIdent := base.(*ast.Ident); !isIdent {
p.errorExpected(base.Pos(), "(unqualified) identifier") p.errorExpected(base.Pos(), "(unqualified) identifier")
par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos(), recv.End()}}} par.List = []*ast.Field{{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
} }
return par return par
......
...@@ -354,7 +354,7 @@ func (p *printer) isOneLineFieldList(list []*ast.Field) bool { ...@@ -354,7 +354,7 @@ func (p *printer) isOneLineFieldList(list []*ast.Field) bool {
} }
func (p *printer) setLineComment(text string) { func (p *printer) setLineComment(text string) {
p.setComment(&ast.CommentGroup{[]*ast.Comment{&ast.Comment{token.NoPos, text}}}) p.setComment(&ast.CommentGroup{[]*ast.Comment{{token.NoPos, text}}})
} }
func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) { func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
......
...@@ -1999,7 +1999,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList { ...@@ -1999,7 +1999,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
if par.NumFields() != 1 { if par.NumFields() != 1 {
p.errorExpected(pos, "exactly one receiver") p.errorExpected(pos, "exactly one receiver")
// TODO determine a better range for BadExpr below // TODO determine a better range for BadExpr below
par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{pos, pos}}} par.List = []*ast.Field{{Type: &ast.BadExpr{pos, pos}}}
return par return par
} }
...@@ -2008,7 +2008,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList { ...@@ -2008,7 +2008,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
base := deref(recv.Type) base := deref(recv.Type)
if _, isIdent := base.(*ast.Ident); !isIdent { if _, isIdent := base.(*ast.Ident); !isIdent {
p.errorExpected(base.Pos(), "(unqualified) identifier") p.errorExpected(base.Pos(), "(unqualified) identifier")
par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos(), recv.End()}}} par.List = []*ast.Field{{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
} }
return par return par
......
...@@ -13,9 +13,9 @@ type Hash interface { ...@@ -13,9 +13,9 @@ type Hash interface {
// It never returns an error. // It never returns an error.
io.Writer io.Writer
// Sum appends the current hash in the same manner as append(), without // Sum appends the current hash to b and returns the resulting slice.
// changing the underlying hash state. // It does not change the underlying hash state.
Sum(in []byte) []byte Sum(b []byte) []byte
// Reset resets the hash to one with zero bytes written. // Reset resets the hash to one with zero bytes written.
Reset() Reset()
......
...@@ -515,7 +515,19 @@ func afterHeadIM(p *parser) bool { ...@@ -515,7 +515,19 @@ func afterHeadIM(p *parser) bool {
implied bool implied bool
) )
switch p.tok.Type { switch p.tok.Type {
case ErrorToken, TextToken: case ErrorToken:
implied = true
framesetOK = true
case TextToken:
s := strings.TrimLeft(p.tok.Data, whitespace)
if len(s) < len(p.tok.Data) {
// Add the initial whitespace to the current node.
p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
if s == "" {
return true
}
p.tok.Data = s
}
implied = true implied = true
framesetOK = true framesetOK = true
case StartTagToken: case StartTagToken:
...@@ -535,7 +547,8 @@ func afterHeadIM(p *parser) bool { ...@@ -535,7 +547,8 @@ func afterHeadIM(p *parser) bool {
defer p.oe.pop() defer p.oe.pop()
return inHeadIM(p) return inHeadIM(p)
case "head": case "head":
// TODO. // Ignore the token.
return true
default: default:
implied = true implied = true
framesetOK = true framesetOK = true
......
...@@ -167,6 +167,7 @@ func TestParser(t *testing.T) { ...@@ -167,6 +167,7 @@ func TestParser(t *testing.T) {
{"tests3.dat", -1}, {"tests3.dat", -1},
{"tests4.dat", -1}, {"tests4.dat", -1},
{"tests5.dat", -1}, {"tests5.dat", -1},
{"tests6.dat", 7},
} }
for _, tf := range testFiles { for _, tf := range testFiles {
f, err := os.Open("testdata/webkit/" + tf.filename) f, err := os.Open("testdata/webkit/" + tf.filename)
......
...@@ -14,63 +14,63 @@ func TestRenderer(t *testing.T) { ...@@ -14,63 +14,63 @@ func TestRenderer(t *testing.T) {
Type: ElementNode, Type: ElementNode,
Data: "html", Data: "html",
Child: []*Node{ Child: []*Node{
&Node{ {
Type: ElementNode, Type: ElementNode,
Data: "head", Data: "head",
}, },
&Node{ {
Type: ElementNode, Type: ElementNode,
Data: "body", Data: "body",
Child: []*Node{ Child: []*Node{
&Node{ {
Type: TextNode, Type: TextNode,
Data: "0<1", Data: "0<1",
}, },
&Node{ {
Type: ElementNode, Type: ElementNode,
Data: "p", Data: "p",
Attr: []Attribute{ Attr: []Attribute{
Attribute{ {
Key: "id", Key: "id",
Val: "A", Val: "A",
}, },
Attribute{ {
Key: "foo", Key: "foo",
Val: `abc"def`, Val: `abc"def`,
}, },
}, },
Child: []*Node{ Child: []*Node{
&Node{ {
Type: TextNode, Type: TextNode,
Data: "2", Data: "2",
}, },
&Node{ {
Type: ElementNode, Type: ElementNode,
Data: "b", Data: "b",
Attr: []Attribute{ Attr: []Attribute{
Attribute{ {
Key: "empty", Key: "empty",
Val: "", Val: "",
}, },
}, },
Child: []*Node{ Child: []*Node{
&Node{ {
Type: TextNode, Type: TextNode,
Data: "3", Data: "3",
}, },
}, },
}, },
&Node{ {
Type: ElementNode, Type: ElementNode,
Data: "i", Data: "i",
Attr: []Attribute{ Attr: []Attribute{
Attribute{ {
Key: "backslash", Key: "backslash",
Val: `\`, Val: `\`,
}, },
}, },
Child: []*Node{ Child: []*Node{
&Node{ {
Type: TextNode, Type: TextNode,
Data: "&4", Data: "&4",
}, },
...@@ -78,19 +78,19 @@ func TestRenderer(t *testing.T) { ...@@ -78,19 +78,19 @@ func TestRenderer(t *testing.T) {
}, },
}, },
}, },
&Node{ {
Type: TextNode, Type: TextNode,
Data: "5", Data: "5",
}, },
&Node{ {
Type: ElementNode, Type: ElementNode,
Data: "blockquote", Data: "blockquote",
}, },
&Node{ {
Type: ElementNode, Type: ElementNode,
Data: "br", Data: "br",
}, },
&Node{ {
Type: TextNode, Type: TextNode,
Data: "6", Data: "6",
}, },
......
...@@ -113,7 +113,7 @@ func TestDecodeCSS(t *testing.T) { ...@@ -113,7 +113,7 @@ func TestDecodeCSS(t *testing.T) {
func TestHexDecode(t *testing.T) { func TestHexDecode(t *testing.T) {
for i := 0; i < 0x200000; i += 101 /* coprime with 16 */ { for i := 0; i < 0x200000; i += 101 /* coprime with 16 */ {
s := strconv.Itob(i, 16) s := strconv.FormatInt(int64(i), 16)
if got := int(hexDecode([]byte(s))); got != i { if got := int(hexDecode([]byte(s))); got != i {
t.Errorf("%s: want %d but got %d", s, i, got) t.Errorf("%s: want %d but got %d", s, i, got)
} }
......
...@@ -716,7 +716,7 @@ func (e *escaper) editTextNode(n *parse.TextNode, text []byte) { ...@@ -716,7 +716,7 @@ func (e *escaper) editTextNode(n *parse.TextNode, text []byte) {
// commit applies changes to actions and template calls needed to contextually // commit applies changes to actions and template calls needed to contextually
// autoescape content and adds any derived templates to the set. // autoescape content and adds any derived templates to the set.
func (e *escaper) commit() { func (e *escaper) commit() {
for name, _ := range e.output { for name := range e.output {
e.template(name).Funcs(funcMap) e.template(name).Funcs(funcMap)
} }
for _, t := range e.derived { for _, t := range e.derived {
......
...@@ -689,11 +689,11 @@ func TestEscapeSet(t *testing.T) { ...@@ -689,11 +689,11 @@ func TestEscapeSet(t *testing.T) {
data := dataItem{ data := dataItem{
Children: []*dataItem{ Children: []*dataItem{
&dataItem{X: "foo"}, {X: "foo"},
&dataItem{X: "<bar>"}, {X: "<bar>"},
&dataItem{ {
Children: []*dataItem{ Children: []*dataItem{
&dataItem{X: "baz"}, {X: "baz"},
}, },
}, },
}, },
...@@ -1597,7 +1597,7 @@ func TestRedundantFuncs(t *testing.T) { ...@@ -1597,7 +1597,7 @@ func TestRedundantFuncs(t *testing.T) {
for n0, m := range redundantFuncs { for n0, m := range redundantFuncs {
f0 := funcMap[n0].(func(...interface{}) string) f0 := funcMap[n0].(func(...interface{}) string)
for n1, _ := range m { for n1 := range m {
f1 := funcMap[n1].(func(...interface{}) string) f1 := funcMap[n1].(func(...interface{}) string)
for _, input := range inputs { for _, input := range inputs {
want := f0(input) want := f0(input)
......
...@@ -47,23 +47,22 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) { ...@@ -47,23 +47,22 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
return t.text.Execute(wr, data) return t.text.Execute(wr, data)
} }
// ExecuteTemplate applies the template associated with t that has the given name // ExecuteTemplate applies the template associated with t that has the given
// to the specified data object and writes the output to wr. // name to the specified data object and writes the output to wr.
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) (err error) { func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) (err error) {
t.nameSpace.mu.Lock() t.nameSpace.mu.Lock()
tmpl := t.set[name] tmpl := t.set[name]
if tmpl == nil { if (tmpl == nil) != (t.text.Lookup(name) == nil) {
t.nameSpace.mu.Unlock() panic("html/template internal error: template escaping out of sync")
return fmt.Errorf("template: no template %q associated with template %q", name, t.Name())
} }
if !tmpl.escaped { if tmpl != nil && !tmpl.escaped {
err = escapeTemplates(tmpl, name) err = escapeTemplates(tmpl, name)
} }
t.nameSpace.mu.Unlock() t.nameSpace.mu.Unlock()
if err != nil { if err != nil {
return return
} }
return tmpl.text.ExecuteTemplate(wr, name, data) return t.text.ExecuteTemplate(wr, name, data)
} }
// Parse parses a string into a template. Nested template definitions // Parse parses a string into a template. Nested template definitions
...@@ -106,7 +105,7 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) error { ...@@ -106,7 +105,7 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) error {
// Clone is unimplemented. // Clone is unimplemented.
func (t *Template) Clone(name string) error { func (t *Template) Clone(name string) error {
return fmt.Errorf("html/template: Add unimplemented") return fmt.Errorf("html/template: Clone unimplemented")
} }
// New allocates a new HTML template with the given name. // New allocates a new HTML template with the given name.
......
...@@ -134,13 +134,22 @@ type Model interface { ...@@ -134,13 +134,22 @@ type Model interface {
Convert(c Color) Color Convert(c Color) Color
} }
// ModelFunc is an adapter type to allow the use of a color conversion // ModelFunc returns a Model that invokes f to implement the conversion.
// function as a Model. If f is such a function, ModelFunc(f) is a Model that func ModelFunc(f func(Color) Color) Model {
// invokes f to implement the conversion. // Note: using *modelFunc as the implementation
type ModelFunc func(Color) Color // means that callers can still use comparisons
// like m == RGBAModel. This is not possible if
// we use the func value directly, because funcs
// are no longer comparable.
return &modelFunc{f}
}
type modelFunc struct {
f func(Color) Color
}
func (f ModelFunc) Convert(c Color) Color { func (m *modelFunc) Convert(c Color) Color {
return f(c) return m.f(c)
} }
// RGBAModel is the Model for RGBA colors. // RGBAModel is the Model for RGBA colors.
......
...@@ -20,7 +20,7 @@ var ( ...@@ -20,7 +20,7 @@ var (
) )
// Uniform is an infinite-sized Image of uniform color. // Uniform is an infinite-sized Image of uniform color.
// It implements both the color.Color and Image interfaces. // It implements the color.Color, color.ColorModel, and Image interfaces.
type Uniform struct { type Uniform struct {
C color.Color C color.Color
} }
...@@ -30,7 +30,11 @@ func (c *Uniform) RGBA() (r, g, b, a uint32) { ...@@ -30,7 +30,11 @@ func (c *Uniform) RGBA() (r, g, b, a uint32) {
} }
func (c *Uniform) ColorModel() color.Model { func (c *Uniform) ColorModel() color.Model {
return color.ModelFunc(func(color.Color) color.Color { return c.C }) return c
}
func (c *Uniform) Convert(color.Color) color.Color {
return c.C
} }
func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} } func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
......
...@@ -429,7 +429,7 @@ func Encode(w io.Writer, m image.Image) error { ...@@ -429,7 +429,7 @@ func Encode(w io.Writer, m image.Image) error {
// also rejected. // also rejected.
mw, mh := int64(m.Bounds().Dx()), int64(m.Bounds().Dy()) mw, mh := int64(m.Bounds().Dx()), int64(m.Bounds().Dy())
if mw <= 0 || mh <= 0 || mw >= 1<<32 || mh >= 1<<32 { if mw <= 0 || mh <= 0 || mw >= 1<<32 || mh >= 1<<32 {
return FormatError("invalid image size: " + strconv.Itoa64(mw) + "x" + strconv.Itoa64(mw)) return FormatError("invalid image size: " + strconv.FormatInt(mw, 10) + "x" + strconv.FormatInt(mw, 10))
} }
var e encoder var e encoder
......
...@@ -110,7 +110,7 @@ var _cos = [...]float64{ ...@@ -110,7 +110,7 @@ var _cos = [...]float64{
// Cos returns the cosine of x. // Cos returns the cosine of x.
// //
// Special conditions are: // Special cases are:
// Cos(±Inf) = NaN // Cos(±Inf) = NaN
// Cos(NaN) = NaN // Cos(NaN) = NaN
func Cos(x float64) float64 { func Cos(x float64) float64 {
......
...@@ -8,7 +8,7 @@ package math ...@@ -8,7 +8,7 @@ package math
// Sincos(x) returns Sin(x), Cos(x). // Sincos(x) returns Sin(x), Cos(x).
// //
// Special conditions are: // Special cases are:
// Sincos(±0) = ±0, 1 // Sincos(±0) = ±0, 1
// Sincos(±Inf) = NaN, NaN // Sincos(±Inf) = NaN, NaN
// Sincos(NaN) = NaN, NaN // Sincos(NaN) = NaN, NaN
......
...@@ -17,6 +17,11 @@ package math ...@@ -17,6 +17,11 @@ package math
*/ */
// Sinh returns the hyperbolic sine of x. // Sinh returns the hyperbolic sine of x.
//
// Special cases are:
// Sinh(±0) = ±0
// Sinh(±Inf) = ±Inf
// Sinh(NaN) = NaN
func Sinh(x float64) float64 { func Sinh(x float64) float64 {
// The coefficients are #2029 from Hart & Cheney. (20.36D) // The coefficients are #2029 from Hart & Cheney. (20.36D)
const ( const (
...@@ -56,6 +61,11 @@ func Sinh(x float64) float64 { ...@@ -56,6 +61,11 @@ func Sinh(x float64) float64 {
} }
// Cosh returns the hyperbolic cosine of x. // Cosh returns the hyperbolic cosine of x.
//
// Special cases are:
// Cosh(±0) = 1
// Cosh(±Inf) = +Inf
// Cosh(NaN) = NaN
func Cosh(x float64) float64 { func Cosh(x float64) float64 {
if x < 0 { if x < 0 {
x = -x x = -x
......
...@@ -75,7 +75,7 @@ var _tanQ = [...]float64{ ...@@ -75,7 +75,7 @@ var _tanQ = [...]float64{
// Tan returns the tangent of x. // Tan returns the tangent of x.
// //
// Special conditions are: // Special cases are:
// Tan(±0) = ±0 // Tan(±0) = ±0
// Tan(±Inf) = NaN // Tan(±Inf) = NaN
// Tan(NaN) = NaN // Tan(NaN) = NaN
......
...@@ -12,6 +12,11 @@ package math ...@@ -12,6 +12,11 @@ package math
*/ */
// Tanh computes the hyperbolic tangent of x. // Tanh computes the hyperbolic tangent of x.
//
// Special cases are:
// Tanh(±0) = ±0
// Tanh(±Inf) = ±1
// Tanh(NaN) = NaN
func Tanh(x float64) float64 { func Tanh(x float64) float64 {
if x < 0 { if x < 0 {
x = -x x = -x
......
...@@ -70,7 +70,7 @@ func RequestFromMap(params map[string]string) (*http.Request, error) { ...@@ -70,7 +70,7 @@ func RequestFromMap(params map[string]string) (*http.Request, error) {
r.Host = params["HTTP_HOST"] r.Host = params["HTTP_HOST"]
if lenstr := params["CONTENT_LENGTH"]; lenstr != "" { if lenstr := params["CONTENT_LENGTH"]; lenstr != "" {
clen, err := strconv.Atoi64(lenstr) clen, err := strconv.ParseInt(lenstr, 10, 64)
if err != nil { if err != nil {
return nil, errors.New("cgi: bad CONTENT_LENGTH in environment: " + lenstr) return nil, errors.New("cgi: bad CONTENT_LENGTH in environment: " + lenstr)
} }
......
...@@ -48,7 +48,7 @@ func (cr *chunkedReader) beginChunk() { ...@@ -48,7 +48,7 @@ func (cr *chunkedReader) beginChunk() {
if cr.err != nil { if cr.err != nil {
return return
} }
cr.n, cr.err = strconv.Btoui64(line, 16) cr.n, cr.err = strconv.ParseUint(line, 16, 64)
if cr.err != nil { if cr.err != nil {
return return
} }
...@@ -147,7 +147,7 @@ func (cw *chunkedWriter) Write(data []byte) (n int, err error) { ...@@ -147,7 +147,7 @@ func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
return 0, nil return 0, nil
} }
head := strconv.Itob(len(data), 16) + "\r\n" head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
if _, err = io.WriteString(cw.Wire, head); err != nil { if _, err = io.WriteString(cw.Wire, head); err != nil {
return 0, err return 0, err
......
...@@ -81,14 +81,14 @@ var addCookieTests = []struct { ...@@ -81,14 +81,14 @@ var addCookieTests = []struct {
"", "",
}, },
{ {
[]*Cookie{&Cookie{Name: "cookie-1", Value: "v$1"}}, []*Cookie{{Name: "cookie-1", Value: "v$1"}},
"cookie-1=v$1", "cookie-1=v$1",
}, },
{ {
[]*Cookie{ []*Cookie{
&Cookie{Name: "cookie-1", Value: "v$1"}, {Name: "cookie-1", Value: "v$1"},
&Cookie{Name: "cookie-2", Value: "v$2"}, {Name: "cookie-2", Value: "v$2"},
&Cookie{Name: "cookie-3", Value: "v$3"}, {Name: "cookie-3", Value: "v$3"},
}, },
"cookie-1=v$1; cookie-2=v$2; cookie-3=v$3", "cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
}, },
...@@ -113,11 +113,11 @@ var readSetCookiesTests = []struct { ...@@ -113,11 +113,11 @@ var readSetCookiesTests = []struct {
}{ }{
{ {
Header{"Set-Cookie": {"Cookie-1=v$1"}}, Header{"Set-Cookie": {"Cookie-1=v$1"}},
[]*Cookie{&Cookie{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}}, []*Cookie{{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
}, },
{ {
Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}}, Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
[]*Cookie{&Cookie{ []*Cookie{{
Name: "NID", Name: "NID",
Value: "99=YsDT5i3E-CXax-", Value: "99=YsDT5i3E-CXax-",
Path: "/", Path: "/",
...@@ -159,30 +159,30 @@ var readCookiesTests = []struct { ...@@ -159,30 +159,30 @@ var readCookiesTests = []struct {
Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}}, Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
"", "",
[]*Cookie{ []*Cookie{
&Cookie{Name: "Cookie-1", Value: "v$1"}, {Name: "Cookie-1", Value: "v$1"},
&Cookie{Name: "c2", Value: "v2"}, {Name: "c2", Value: "v2"},
}, },
}, },
{ {
Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}}, Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
"c2", "c2",
[]*Cookie{ []*Cookie{
&Cookie{Name: "c2", Value: "v2"}, {Name: "c2", Value: "v2"},
}, },
}, },
{ {
Header{"Cookie": {"Cookie-1=v$1; c2=v2"}}, Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
"", "",
[]*Cookie{ []*Cookie{
&Cookie{Name: "Cookie-1", Value: "v$1"}, {Name: "Cookie-1", Value: "v$1"},
&Cookie{Name: "c2", Value: "v2"}, {Name: "c2", Value: "v2"},
}, },
}, },
{ {
Header{"Cookie": {"Cookie-1=v$1; c2=v2"}}, Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
"c2", "c2",
[]*Cookie{ []*Cookie{
&Cookie{Name: "c2", Value: "v2"}, {Name: "c2", Value: "v2"},
}, },
}, },
} }
......
...@@ -220,7 +220,7 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec ...@@ -220,7 +220,7 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
w.Header().Set("Accept-Ranges", "bytes") w.Header().Set("Accept-Ranges", "bytes")
if w.Header().Get("Content-Encoding") == "" { if w.Header().Get("Content-Encoding") == "" {
w.Header().Set("Content-Length", strconv.Itoa64(size)) w.Header().Set("Content-Length", strconv.FormatInt(size, 10))
} }
w.WriteHeader(code) w.WriteHeader(code)
...@@ -295,7 +295,7 @@ func parseRange(s string, size int64) ([]httpRange, error) { ...@@ -295,7 +295,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
if start == "" { if start == "" {
// If no start is specified, end specifies the // If no start is specified, end specifies the
// range start relative to the end of the file. // range start relative to the end of the file.
i, err := strconv.Atoi64(end) i, err := strconv.ParseInt(end, 10, 64)
if err != nil { if err != nil {
return nil, errors.New("invalid range") return nil, errors.New("invalid range")
} }
...@@ -305,7 +305,7 @@ func parseRange(s string, size int64) ([]httpRange, error) { ...@@ -305,7 +305,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
r.start = size - i r.start = size - i
r.length = size - r.start r.length = size - r.start
} else { } else {
i, err := strconv.Atoi64(start) i, err := strconv.ParseInt(start, 10, 64)
if err != nil || i > size || i < 0 { if err != nil || i > size || i < 0 {
return nil, errors.New("invalid range") return nil, errors.New("invalid range")
} }
...@@ -314,7 +314,7 @@ func parseRange(s string, size int64) ([]httpRange, error) { ...@@ -314,7 +314,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
// If no end is specified, range extends to end of the file. // If no end is specified, range extends to end of the file.
r.length = size - r.start r.length = size - r.start
} else { } else {
i, err := strconv.Atoi64(end) i, err := strconv.ParseInt(end, 10, 64)
if err != nil || r.start > i { if err != nil || r.start > i {
return nil, errors.New("invalid range") return nil, errors.New("invalid range")
} }
......
...@@ -50,7 +50,7 @@ func (cr *chunkedReader) beginChunk() { ...@@ -50,7 +50,7 @@ func (cr *chunkedReader) beginChunk() {
if cr.err != nil { if cr.err != nil {
return return
} }
cr.n, cr.err = strconv.Btoui64(line, 16) cr.n, cr.err = strconv.ParseUint(line, 16, 64)
if cr.err != nil { if cr.err != nil {
return return
} }
...@@ -149,7 +149,7 @@ func (cw *chunkedWriter) Write(data []byte) (n int, err error) { ...@@ -149,7 +149,7 @@ func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
return 0, nil return 0, nil
} }
head := strconv.Itob(len(data), 16) + "\r\n" head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
if _, err = io.WriteString(cw.Wire, head); err != nil { if _, err = io.WriteString(cw.Wire, head); err != nil {
return 0, err return 0, err
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment