This patch to libgo updates it to the Go 1.3.3 release. This is just a few bug fixes. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 03219f2d0191 libgo/MERGE --- a/libgo/MERGE Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/MERGE Mon Oct 27 09:34:59 2014 -0700 @@ -1,4 +1,4 @@ -9895f9e36435 +f44017549ff9 The first line of this file holds the Mercurial revision number of the last merge done from the master library sources. diff -r 03219f2d0191 libgo/go/compress/gzip/gzip.go --- a/libgo/go/compress/gzip/gzip.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/compress/gzip/gzip.go Mon Oct 27 09:34:59 2014 -0700 @@ -245,7 +245,8 @@ return z.err } -// Close closes the Writer. It does not close the underlying io.Writer. +// Close closes the Writer, flushing any unwritten data to the underlying +// io.Writer, but does not close the underlying io.Writer. func (z *Writer) Close() error { if z.err != nil { return z.err diff -r 03219f2d0191 libgo/go/compress/zlib/writer.go --- a/libgo/go/compress/zlib/writer.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/compress/zlib/writer.go Mon Oct 27 09:34:59 2014 -0700 @@ -174,7 +174,8 @@ return z.err } -// Calling Close does not close the wrapped io.Writer originally passed to NewWriter. +// Close closes the Writer, flushing any unwritten data to the underlying +// io.Writer, but does not close the underlying io.Writer. func (z *Writer) Close() error { if !z.wroteHeader { z.err = z.writeHeader() diff -r 03219f2d0191 libgo/go/crypto/rsa/pkcs1v15.go --- a/libgo/go/crypto/rsa/pkcs1v15.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/crypto/rsa/pkcs1v15.go Mon Oct 27 09:34:59 2014 -0700 @@ -53,11 +53,14 @@ if err := checkPub(&priv.PublicKey); err != nil { return nil, err } - valid, out, err := decryptPKCS1v15(rand, priv, ciphertext) - if err == nil && valid == 0 { - err = ErrDecryption + valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext) + if err != nil { + return } - + if valid == 0 { + return nil, ErrDecryption + } + out = out[index:] return } @@ -80,21 +83,32 @@ } k := (priv.N.BitLen() + 7) / 8 if k-(len(key)+3+8) < 0 { - err = ErrDecryption - return + return ErrDecryption } - valid, msg, err := decryptPKCS1v15(rand, priv, ciphertext) + valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext) if err != nil { return } - valid &= subtle.ConstantTimeEq(int32(len(msg)), int32(len(key))) - subtle.ConstantTimeCopy(valid, key, msg) + if len(em) != k { + // This should be impossible because decryptPKCS1v15 always + // returns the full slice. + return ErrDecryption + } + + valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key))) + subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):]) return } -func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err error) { +// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if +// rand is not nil. It returns one or zero in valid that indicates whether the +// plaintext was correctly structured. In either case, the plaintext is +// returned in em so that it may be read independently of whether it was valid +// in order to maintain constant memory access patterns. If the plaintext was +// valid then index contains the index of the original message in em. +func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) { k := (priv.N.BitLen() + 7) / 8 if k < 11 { err = ErrDecryption @@ -107,7 +121,7 @@ return } - em := leftPad(m.Bytes(), k) + em = leftPad(m.Bytes(), k) firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2) @@ -115,8 +129,7 @@ // octets, followed by a 0, followed by the message. // lookingForIndex: 1 iff we are still looking for the zero. // index: the offset of the first zero byte. - var lookingForIndex, index int - lookingForIndex = 1 + lookingForIndex := 1 for i := 2; i < len(em); i++ { equals0 := subtle.ConstantTimeByteEq(em[i], 0) @@ -129,8 +142,8 @@ validPS := subtle.ConstantTimeLessOrEq(2+8, index) valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS - msg = em[index+1:] - return + index = subtle.ConstantTimeSelect(valid, index+1, 0) + return valid, em, index, nil } // nonZeroRandomBytes fills the given slice with non-zero random octets. diff -r 03219f2d0191 libgo/go/crypto/rsa/pkcs1v15_test.go --- a/libgo/go/crypto/rsa/pkcs1v15_test.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/crypto/rsa/pkcs1v15_test.go Mon Oct 27 09:34:59 2014 -0700 @@ -227,6 +227,26 @@ } } +func TestShortSessionKey(t *testing.T) { + // This tests that attempting to decrypt a session key where the + // ciphertext is too small doesn't run outside the array bounds. + ciphertext, err := EncryptPKCS1v15(rand.Reader, &rsaPrivateKey.PublicKey, []byte{1}) + if err != nil { + t.Fatalf("Failed to encrypt short message: %s", err) + } + + var key [32]byte + if err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, ciphertext, key[:]); err != nil { + t.Fatalf("Failed to decrypt short message: %s", err) + } + + for _, v := range key { + if v != 0 { + t.Fatal("key was modified when ciphertext was invalid") + } + } +} + // In order to generate new test vectors you'll need the PEM form of this key: // -----BEGIN RSA PRIVATE KEY----- // MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 diff -r 03219f2d0191 libgo/go/crypto/subtle/constant_time.go --- a/libgo/go/crypto/subtle/constant_time.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/crypto/subtle/constant_time.go Mon Oct 27 09:34:59 2014 -0700 @@ -49,9 +49,14 @@ return int(z & 1) } -// ConstantTimeCopy copies the contents of y into x iff v == 1. If v == 0, x is left unchanged. -// Its behavior is undefined if v takes any other value. +// ConstantTimeCopy copies the contents of y into x (a slice of equal length) +// if v == 1. If v == 0, x is left unchanged. Its behavior is undefined if v +// takes any other value. func ConstantTimeCopy(v int, x, y []byte) { + if len(x) != len(y) { + panic("subtle: slices have different lengths") + } + xmask := byte(v - 1) ymask := byte(^(v - 1)) for i := 0; i < len(x); i++ { diff -r 03219f2d0191 libgo/go/crypto/tls/handshake_server.go --- a/libgo/go/crypto/tls/handshake_server.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/crypto/tls/handshake_server.go Mon Oct 27 09:34:59 2014 -0700 @@ -214,6 +214,10 @@ func (hs *serverHandshakeState) checkForResumption() bool { c := hs.c + if c.config.SessionTicketsDisabled { + return false + } + var ok bool if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok { return false diff -r 03219f2d0191 libgo/go/crypto/tls/handshake_server_test.go --- a/libgo/go/crypto/tls/handshake_server_test.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/crypto/tls/handshake_server_test.go Mon Oct 27 09:34:59 2014 -0700 @@ -557,6 +557,32 @@ runServerTestTLS12(t, test) } +func TestResumptionDisabled(t *testing.T) { + sessionFilePath := tempFile("") + defer os.Remove(sessionFilePath) + + config := *testConfig + + test := &serverTest{ + name: "IssueTicketPreDisable", + command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath}, + config: &config, + } + runServerTestTLS12(t, test) + + config.SessionTicketsDisabled = true + + test = &serverTest{ + name: "ResumeDisabled", + command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath}, + config: &config, + } + runServerTestTLS12(t, test) + + // One needs to manually confirm that the handshake in the golden data + // file for ResumeDisabled does not include a resumption handshake. +} + // cert.pem and key.pem were generated with generate_cert.go // Thus, they have no ExtKeyUsage fields and trigger an error // when verification is turned on. diff -r 03219f2d0191 libgo/go/crypto/tls/ticket.go --- a/libgo/go/crypto/tls/ticket.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/crypto/tls/ticket.go Mon Oct 27 09:34:59 2014 -0700 @@ -153,7 +153,8 @@ } func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) { - if len(encrypted) < aes.BlockSize+sha256.Size { + if c.config.SessionTicketsDisabled || + len(encrypted) < aes.BlockSize+sha256.Size { return nil, false } diff -r 03219f2d0191 libgo/go/net/dnsconfig_unix.go --- a/libgo/go/net/dnsconfig_unix.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/net/dnsconfig_unix.go Mon Oct 27 09:34:59 2014 -0700 @@ -75,19 +75,19 @@ for i := 1; i < len(f); i++ { s := f[i] switch { - case len(s) >= 6 && s[0:6] == "ndots:": + case hasPrefix(s, "ndots:"): n, _, _ := dtoi(s, 6) if n < 1 { n = 1 } conf.ndots = n - case len(s) >= 8 && s[0:8] == "timeout:": + case hasPrefix(s, "timeout:"): n, _, _ := dtoi(s, 8) if n < 1 { n = 1 } conf.timeout = n - case len(s) >= 8 && s[0:9] == "attempts:": + case hasPrefix(s, "attempts:"): n, _, _ := dtoi(s, 9) if n < 1 { n = 1 @@ -103,3 +103,7 @@ return conf, nil } + +func hasPrefix(s, prefix string) bool { + return len(s) >= len(prefix) && s[:len(prefix)] == prefix +} diff -r 03219f2d0191 libgo/go/net/fd_unix.go --- a/libgo/go/net/fd_unix.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/net/fd_unix.go Mon Oct 27 09:34:59 2014 -0700 @@ -68,16 +68,19 @@ return fd.net + ":" + ls + "->" + rs } -func (fd *netFD) connect(la, ra syscall.Sockaddr) error { +func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. - if err := fd.pd.PrepareWrite(); err != nil { - return err - } switch err := syscall.Connect(fd.sysfd, ra); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case nil, syscall.EISCONN: + if !deadline.IsZero() && deadline.Before(time.Now()) { + return errTimeout + } + if err := fd.init(); err != nil { + return err + } return nil case syscall.EINVAL: // On Solaris we can see EINVAL if the socket has @@ -92,6 +95,13 @@ default: return err } + if err := fd.init(); err != nil { + return err + } + if !deadline.IsZero() { + fd.setWriteDeadline(deadline) + defer fd.setWriteDeadline(noDeadline) + } for { // Performing multiple connect system calls on a // non-blocking socket under Unix variants does not diff -r 03219f2d0191 libgo/go/net/fd_windows.go --- a/libgo/go/net/fd_windows.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/net/fd_windows.go Mon Oct 27 09:34:59 2014 -0700 @@ -313,10 +313,17 @@ runtime.SetFinalizer(fd, (*netFD).Close) } -func (fd *netFD) connect(la, ra syscall.Sockaddr) error { +func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. + if err := fd.init(); err != nil { + return err + } + if !deadline.IsZero() { + fd.setWriteDeadline(deadline) + defer fd.setWriteDeadline(noDeadline) + } if !canUseConnectEx(fd.net) { return syscall.Connect(fd.sysfd, ra) } diff -r 03219f2d0191 libgo/go/net/http/httptest/server_test.go --- a/libgo/go/net/http/httptest/server_test.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/net/http/httptest/server_test.go Mon Oct 27 09:34:59 2014 -0700 @@ -30,6 +30,7 @@ } func TestIssue7264(t *testing.T) { + t.Skip("broken test - removed at tip") for i := 0; i < 1000; i++ { func() { inHandler := make(chan bool, 1) diff -r 03219f2d0191 libgo/go/net/sock_posix.go --- a/libgo/go/net/sock_posix.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/net/sock_posix.go Mon Oct 27 09:34:59 2014 -0700 @@ -107,24 +107,18 @@ } } } - if err := fd.init(); err != nil { - return err - } var rsa syscall.Sockaddr if raddr != nil { if rsa, err = raddr.sockaddr(fd.family); err != nil { return err - } else if rsa != nil { - if !deadline.IsZero() { - fd.setWriteDeadline(deadline) - } - if err := fd.connect(lsa, rsa); err != nil { - return err - } - fd.isConnected = true - if !deadline.IsZero() { - fd.setWriteDeadline(noDeadline) - } + } + if err := fd.connect(lsa, rsa, deadline); err != nil { + return err + } + fd.isConnected = true + } else { + if err := fd.init(); err != nil { + return err } } lsa, _ = syscall.Getsockname(fd.sysfd) diff -r 03219f2d0191 libgo/go/net/testdata/resolv.conf --- a/libgo/go/net/testdata/resolv.conf Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/net/testdata/resolv.conf Mon Oct 27 09:34:59 2014 -0700 @@ -3,3 +3,4 @@ domain Home nameserver 192.168.1.1 options ndots:5 timeout:10 attempts:3 rotate +options attempts 3 diff -r 03219f2d0191 libgo/go/time/format_test.go --- a/libgo/go/time/format_test.go Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/go/time/format_test.go Mon Oct 27 09:34:59 2014 -0700 @@ -183,39 +183,45 @@ } } -func TestParseInSydney(t *testing.T) { - loc, err := LoadLocation("Australia/Sydney") +func TestParseInLocation(t *testing.T) { + // Check that Parse (and ParseInLocation) understand that + // Feb 01 AST (Arabia Standard Time) and Feb 01 AST (Atlantic Standard Time) + // are in different time zones even though both are called AST + + baghdad, err := LoadLocation("Asia/Baghdad") if err != nil { t.Fatal(err) } - // Check that Parse (and ParseInLocation) understand - // that Feb EST and Aug EST are different time zones in Sydney - // even though both are called EST. - t1, err := ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 EST", loc) + t1, err := ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", baghdad) if err != nil { t.Fatal(err) } - t2 := Date(2013, February, 1, 00, 00, 00, 0, loc) + t2 := Date(2013, February, 1, 00, 00, 00, 0, baghdad) if t1 != t2 { - t.Fatalf("ParseInLocation(Feb 01 2013 EST, Sydney) = %v, want %v", t1, t2) + t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad) = %v, want %v", t1, t2) } _, offset := t1.Zone() - if offset != 11*60*60 { - t.Fatalf("ParseInLocation(Feb 01 2013 EST, Sydney).Zone = _, %d, want _, %d", offset, 11*60*60) + if offset != 3*60*60 { + t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad).Zone = _, %d, want _, %d", offset, 3*60*60) } - t1, err = ParseInLocation("Jan 02 2006 MST", "Aug 01 2013 EST", loc) + blancSablon, err := LoadLocation("America/Blanc-Sablon") if err != nil { t.Fatal(err) } - t2 = Date(2013, August, 1, 00, 00, 00, 0, loc) + + t1, err = ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", blancSablon) + if err != nil { + t.Fatal(err) + } + t2 = Date(2013, February, 1, 00, 00, 00, 0, blancSablon) if t1 != t2 { - t.Fatalf("ParseInLocation(Aug 01 2013 EST, Sydney) = %v, want %v", t1, t2) + t.Fatalf("ParseInLocation(Feb 01 2013 AST, Blanc-Sablon) = %v, want %v", t1, t2) } _, offset = t1.Zone() - if offset != 10*60*60 { - t.Fatalf("ParseInLocation(Aug 01 2013 EST, Sydney).Zone = _, %d, want _, %d", offset, 10*60*60) + if offset != -4*60*60 { + t.Fatalf("ParseInLocation(Feb 01 2013 AST, Blanc-Sablon).Zone = _, %d, want _, %d", offset, -4*60*60) } } diff -r 03219f2d0191 libgo/runtime/runtime.c --- a/libgo/runtime/runtime.c Thu Oct 23 21:57:37 2014 -0700 +++ b/libgo/runtime/runtime.c Mon Oct 27 09:34:59 2014 -0700 @@ -112,8 +112,6 @@ syscall_Envs.__values = (void*)s; syscall_Envs.__count = n; syscall_Envs.__capacity = n; - - traceback_cache = ~(uint32)0; } int32 @@ -309,6 +307,16 @@ { const byte *p; intgo i, n; + bool tmp; + + // gotraceback caches the GOTRACEBACK setting in traceback_cache. + // gotraceback can be called before the environment is available. + // traceback_cache must be reset after the environment is made + // available, in order for the environment variable to take effect. + // The code is fixed differently in Go 1.4. + // This is a limited fix for Go 1.3.3. + traceback_cache = ~(uint32)0; + runtime_gotraceback(&tmp); p = runtime_getenv("GODEBUG"); if(p == nil)