This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

libgo patch committed: Update to Go 1.0.2 release


This patch updates libgo to the Go 1.0.2 release.  This is a collection
of bug fixes with no new functionality.  Bootstrapped and ran Go
testsuite on x86_64-unknown-linux-gnu.  Committed to mainline and 4.7
branch.

Ian

diff -r 6bbd6af8c8a4 libgo/MERGE
--- a/libgo/MERGE	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/MERGE	Mon Jun 25 08:37:48 2012 -0700
@@ -1,4 +1,4 @@
-2ccfd4b451d3
+5e806355a9e1
 
 The first line of this file holds the Mercurial revision number of the
 last merge done from the master library sources.
diff -r 6bbd6af8c8a4 libgo/go/compress/flate/deflate.go
--- a/libgo/go/compress/flate/deflate.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/compress/flate/deflate.go	Mon Jun 25 08:37:48 2012 -0700
@@ -32,6 +32,7 @@
 	hashSize            = 1 << hashBits
 	hashMask            = (1 << hashBits) - 1
 	hashShift           = (hashBits + minMatchLength - 1) / minMatchLength
+	maxHashOffset       = 1 << 24
 
 	skipNever = math.MaxInt32
 )
@@ -106,6 +107,25 @@
 			d.blockStart = math.MaxInt32
 		}
 		d.hashOffset += windowSize
+		if d.hashOffset > maxHashOffset {
+			delta := d.hashOffset - 1
+			d.hashOffset -= delta
+			d.chainHead -= delta
+			for i, v := range d.hashPrev {
+				if v > delta {
+					d.hashPrev[i] -= delta
+				} else {
+					d.hashPrev[i] = 0
+				}
+			}
+			for i, v := range d.hashHead {
+				if v > delta {
+					d.hashHead[i] -= delta
+				} else {
+					d.hashHead[i] = 0
+				}
+			}
+		}
 	}
 	n := copy(d.window[d.windowEnd:], b)
 	d.windowEnd += n
diff -r 6bbd6af8c8a4 libgo/go/compress/flate/deflate_test.go
--- a/libgo/go/compress/flate/deflate_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/compress/flate/deflate_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -94,6 +94,50 @@
 	}
 }
 
+// A sparseReader returns a stream consisting of 0s followed by 1<<16 1s.
+// This tests missing hash references in a very large input.
+type sparseReader struct {
+	l   int64
+	cur int64
+}
+
+func (r *sparseReader) Read(b []byte) (n int, err error) {
+	if r.cur >= r.l {
+		return 0, io.EOF
+	}
+	n = len(b)
+	cur := r.cur + int64(n)
+	if cur > r.l {
+		n -= int(cur - r.l)
+		cur = r.l
+	}
+	for i := range b[0:n] {
+		if r.cur+int64(i) >= r.l-1<<16 {
+			b[i] = 1
+		} else {
+			b[i] = 0
+		}
+	}
+	r.cur = cur
+	return
+}
+
+func TestVeryLongSparseChunk(t *testing.T) {
+	if testing.Short() {
+		t.Logf("skipping sparse chunk during short test")
+		return
+	}
+	w, err := NewWriter(ioutil.Discard, 1)
+	if err != nil {
+		t.Errorf("NewWriter: %v", err)
+		return
+	}
+	if _, err = io.Copy(w, &sparseReader{l: 23E8}); err != nil {
+		t.Errorf("Compress failed: %v", err)
+		return
+	}
+}
+
 type syncBuffer struct {
 	buf    bytes.Buffer
 	mu     sync.RWMutex
diff -r 6bbd6af8c8a4 libgo/go/crypto/aes/const.go
--- a/libgo/go/crypto/aes/const.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/crypto/aes/const.go	Mon Jun 25 08:37:48 2012 -0700
@@ -11,11 +11,11 @@
 // http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
 
 // AES is based on the mathematical behavior of binary polynomials
-// (polynomials over GF(2)) modulo the irreducible polynomial xâ + xâ + x + x + 1.
+// (polynomials over GF(2)) modulo the irreducible polynomial xâ + xâ + x + x + 1.
 // Addition of these binary polynomials corresponds to binary xor.
 // Reducing mod poly corresponds to binary xor with poly every
 // time a 0x100 bit appears.
-const poly = 1<<8 | 1<<4 | 1<<3 | 1<<1 | 1<<0 // xâ + xâ + x + x + 1
+const poly = 1<<8 | 1<<4 | 1<<3 | 1<<1 | 1<<0 // xâ + xâ + x + x + 1
 
 // Powers of x mod poly in GF(2).
 var powx = [16]byte{
diff -r 6bbd6af8c8a4 libgo/go/crypto/ecdsa/ecdsa.go
--- a/libgo/go/crypto/ecdsa/ecdsa.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/crypto/ecdsa/ecdsa.go	Mon Jun 25 08:37:48 2012 -0700
@@ -66,7 +66,9 @@
 // hashToInt converts a hash value to an integer. There is some disagreement
 // about how this is done. [NSA] suggests that this is done in the obvious
 // manner, but [SECG] truncates the hash to the bit-length of the curve order
-// first. We follow [SECG] because that's what OpenSSL does.
+// first. We follow [SECG] because that's what OpenSSL does. Additionally,
+// OpenSSL right shifts excess bits from the number if the hash is too large
+// and we mirror that too.
 func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
 	orderBits := c.Params().N.BitLen()
 	orderBytes := (orderBits + 7) / 8
@@ -75,7 +77,7 @@
 	}
 
 	ret := new(big.Int).SetBytes(hash)
-	excess := orderBytes*8 - orderBits
+	excess := len(hash)*8 - orderBits
 	if excess > 0 {
 		ret.Rsh(ret, uint(excess))
 	}
diff -r 6bbd6af8c8a4 libgo/go/crypto/rsa/pkcs1v15.go
--- a/libgo/go/crypto/rsa/pkcs1v15.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/crypto/rsa/pkcs1v15.go	Mon Jun 25 08:37:48 2012 -0700
@@ -151,6 +151,7 @@
 var hashPrefixes = map[crypto.Hash][]byte{
 	crypto.MD5:       {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
 	crypto.SHA1:      {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
+	crypto.SHA224:    {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
 	crypto.SHA256:    {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
 	crypto.SHA384:    {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
 	crypto.SHA512:    {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
diff -r 6bbd6af8c8a4 libgo/go/crypto/tls/handshake_messages.go
--- a/libgo/go/crypto/tls/handshake_messages.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/crypto/tls/handshake_messages.go	Mon Jun 25 08:37:48 2012 -0700
@@ -563,7 +563,7 @@
 		if len(d) < 4 {
 			return false
 		}
-		certLen := uint32(d[0])<<24 | uint32(d[1])<<8 | uint32(d[2])
+		certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
 		if uint32(len(d)) < 3+certLen {
 			return false
 		}
@@ -575,7 +575,7 @@
 	m.certificates = make([][]byte, numCerts)
 	d = data[7:]
 	for i := 0; i < numCerts; i++ {
-		certLen := uint32(d[0])<<24 | uint32(d[1])<<8 | uint32(d[2])
+		certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
 		m.certificates[i] = d[3 : 3+certLen]
 		d = d[3+certLen:]
 	}
diff -r 6bbd6af8c8a4 libgo/go/crypto/x509/x509.go
--- a/libgo/go/crypto/x509/x509.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/crypto/x509/x509.go	Mon Jun 25 08:37:48 2012 -0700
@@ -388,10 +388,10 @@
 		return ErrUnsupportedAlgorithm
 	}
 
-	h := hashType.New()
-	if h == nil {
+	if !hashType.Available() {
 		return ErrUnsupportedAlgorithm
 	}
+	h := hashType.New()
 
 	h.Write(signed)
 	digest := h.Sum(nil)
diff -r 6bbd6af8c8a4 libgo/go/debug/gosym/pclntab_test.go
--- a/libgo/go/debug/gosym/pclntab_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/debug/gosym/pclntab_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -7,14 +7,19 @@
 import (
 	"debug/elf"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"os/exec"
+	"path/filepath"
 	"runtime"
 	"strings"
 	"testing"
 )
 
-var pclinetestBinary string
+var (
+	pclineTempDir    string
+	pclinetestBinary string
+)
 
 func dotest() bool {
 	// For now, only works on ELF platforms.
@@ -24,10 +29,18 @@
 	if pclinetestBinary != "" {
 		return true
 	}
+	var err error
+	pclineTempDir, err = ioutil.TempDir("", "pclinetest")
+	if err != nil {
+		panic(err)
+	}
+	if strings.Contains(pclineTempDir, " ") {
+		panic("unexpected space in tempdir")
+	}
 	// This command builds pclinetest from pclinetest.asm;
 	// the resulting binary looks like it was built from pclinetest.s,
 	// but we have renamed it to keep it away from the go tool.
-	pclinetestBinary = os.TempDir() + "/pclinetest"
+	pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest")
 	command := fmt.Sprintf("go tool 6a -o %s.6 pclinetest.asm && go tool 6l -E main -o %s %s.6",
 		pclinetestBinary, pclinetestBinary, pclinetestBinary)
 	cmd := exec.Command("sh", "-c", command)
@@ -170,6 +183,7 @@
 	if !dotest() {
 		return
 	}
+	defer os.RemoveAll(pclineTempDir)
 
 	f, tab := crack(pclinetestBinary, t)
 	text := f.Section(".text")
diff -r 6bbd6af8c8a4 libgo/go/encoding/base64/base64.go
--- a/libgo/go/encoding/base64/base64.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/encoding/base64/base64.go	Mon Jun 25 08:37:48 2012 -0700
@@ -318,7 +318,7 @@
 	}
 	nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf:nn], 4-d.nbuf)
 	d.nbuf += nn
-	if d.nbuf < 4 {
+	if d.err != nil || d.nbuf < 4 {
 		return 0, d.err
 	}
 
diff -r 6bbd6af8c8a4 libgo/go/encoding/base64/base64_test.go
--- a/libgo/go/encoding/base64/base64_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/encoding/base64/base64_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -6,9 +6,11 @@
 
 import (
 	"bytes"
+	"errors"
 	"io"
 	"io/ioutil"
 	"testing"
+	"time"
 )
 
 type testpair struct {
@@ -226,3 +228,50 @@
 		}
 	}
 }
+
+type nextRead struct {
+	n   int   // bytes to return
+	err error // error to return
+}
+
+// faultInjectReader returns data from source, rate-limited
+// and with the errors as written to nextc.
+type faultInjectReader struct {
+	source string
+	nextc  <-chan nextRead
+}
+
+func (r *faultInjectReader) Read(p []byte) (int, error) {
+	nr := <-r.nextc
+	if len(p) > nr.n {
+		p = p[:nr.n]
+	}
+	n := copy(p, r.source)
+	r.source = r.source[n:]
+	return n, nr.err
+}
+
+// tests that we don't ignore errors from our underlying reader
+func TestDecoderIssue3577(t *testing.T) {
+	next := make(chan nextRead, 10)
+	wantErr := errors.New("my error")
+	next <- nextRead{5, nil}
+	next <- nextRead{10, wantErr}
+	d := NewDecoder(StdEncoding, &faultInjectReader{
+		source: "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==", // twas brillig...
+		nextc:  next,
+	})
+	errc := make(chan error)
+	go func() {
+		_, err := ioutil.ReadAll(d)
+		errc <- err
+	}()
+	select {
+	case err := <-errc:
+		if err != wantErr {
+			t.Errorf("got error %v; want %v", err, wantErr)
+		}
+	case <-time.After(5 * time.Second):
+		t.Errorf("timeout; Decoder blocked without returning an error")
+	}
+}
diff -r 6bbd6af8c8a4 libgo/go/encoding/gob/doc.go
--- a/libgo/go/encoding/gob/doc.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/encoding/gob/doc.go	Mon Jun 25 08:37:48 2012 -0700
@@ -116,7 +116,7 @@
 All other slices and arrays are sent as an unsigned count followed by that many
 elements using the standard gob encoding for their type, recursively.
 
-Maps are sent as an unsigned count followed by that man key, element
+Maps are sent as an unsigned count followed by that many key, element
 pairs. Empty but non-nil maps are sent, so if the sender has allocated
 a map, the receiver will allocate a map even no elements are
 transmitted.
diff -r 6bbd6af8c8a4 libgo/go/encoding/json/decode.go
--- a/libgo/go/encoding/json/decode.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/encoding/json/decode.go	Mon Jun 25 08:37:48 2012 -0700
@@ -273,9 +273,14 @@
 			_, isUnmarshaler = v.Interface().(Unmarshaler)
 		}
 
+		// Load value from interface, but only if the result will be
+		// usefully addressable.
 		if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() {
-			v = iv.Elem()
-			continue
+			e := iv.Elem()
+			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
+				v = e
+				continue
+			}
 		}
 
 		pv := v
@@ -588,6 +593,11 @@
 // produce more helpful error messages.
 func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) {
 	// Check for unmarshaler.
+	if len(item) == 0 {
+		//Empty string given
+		d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+		return
+	}
 	wantptr := item[0] == 'n' // null
 	unmarshaler, pv := d.indirect(v, wantptr)
 	if unmarshaler != nil {
diff -r 6bbd6af8c8a4 libgo/go/encoding/json/decode_test.go
--- a/libgo/go/encoding/json/decode_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/encoding/json/decode_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -638,3 +638,68 @@
 		t.Fatal("Unmarshal: did set T.Y")
 	}
 }
+
+// Test that the empty string doesn't panic decoding when ,string is specified
+// Issue 3450
+func TestEmptyString(t *testing.T) {
+	type T2 struct {
+		Number1 int `json:",string"`
+		Number2 int `json:",string"`
+	}
+	data := `{"Number1":"1", "Number2":""}`
+	dec := NewDecoder(strings.NewReader(data))
+	var t2 T2
+	err := dec.Decode(&t2)
+	if err == nil {
+		t.Fatal("Decode: did not return error")
+	}
+	if t2.Number1 != 1 {
+		t.Fatal("Decode: did not set Number1")
+	}
+}
+
+func intp(x int) *int {
+	p := new(int)
+	*p = x
+	return p
+}
+
+func intpp(x *int) **int {
+	pp := new(*int)
+	*pp = x
+	return pp
+}
+
+var interfaceSetTests = []struct {
+	pre  interface{}
+	json string
+	post interface{}
+}{
+	{"foo", `"bar"`, "bar"},
+	{"foo", `2`, 2.0},
+	{"foo", `true`, true},
+	{"foo", `null`, nil},
+
+	{nil, `null`, nil},
+	{new(int), `null`, nil},
+	{(*int)(nil), `null`, nil},
+	{new(*int), `null`, new(*int)},
+	{(**int)(nil), `null`, nil},
+	{intp(1), `null`, nil},
+	{intpp(nil), `null`, intpp(nil)},
+	{intpp(intp(1)), `null`, intpp(nil)},
+}
+
+func TestInterfaceSet(t *testing.T) {
+	for _, tt := range interfaceSetTests {
+		b := struct{ X interface{} }{tt.pre}
+		blob := `{"X":` + tt.json + `}`
+		if err := Unmarshal([]byte(blob), &b); err != nil {
+			t.Errorf("Unmarshal %#q: %v", blob, err)
+			continue
+		}
+		if !reflect.DeepEqual(b.X, tt.post) {
+			t.Errorf("Unmarshal %#q into %#v: X=%#v, want %#v", blob, tt.pre, b.X, tt.post)
+		}
+	}
+}
diff -r 6bbd6af8c8a4 libgo/go/encoding/json/encode.go
--- a/libgo/go/encoding/json/encode.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/encoding/json/encode.go	Mon Jun 25 08:37:48 2012 -0700
@@ -96,7 +96,7 @@
 //
 // Channel, complex, and function values cannot be encoded in JSON.
 // Attempting to encode such a value causes Marshal to return
-// an InvalidTypeError.
+// an UnsupportedTypeError.
 //
 // JSON cannot represent cyclic data structures and Marshal does not
 // handle them.  Passing cyclic structures to Marshal will result in
@@ -157,6 +157,8 @@
 	MarshalJSON() ([]byte, error)
 }
 
+// An UnsupportedTypeError is returned by Marshal when attempting
+// to encode an unsupported value type.
 type UnsupportedTypeError struct {
 	Type reflect.Type
 }
diff -r 6bbd6af8c8a4 libgo/go/flag/flag.go
--- a/libgo/go/flag/flag.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/flag/flag.go	Mon Jun 25 08:37:48 2012 -0700
@@ -620,8 +620,9 @@
 	flag := &Flag{name, usage, value, value.String()}
 	_, alreadythere := f.formal[name]
 	if alreadythere {
-		fmt.Fprintf(f.out(), "%s flag redefined: %s\n", f.name, name)
-		panic("flag redefinition") // Happens only if flags are declared with identical names
+		msg := fmt.Sprintf("%s flag redefined: %s", f.name, name)
+		fmt.Fprintln(f.out(), msg)
+		panic(msg) // Happens only if flags are declared with identical names
 	}
 	if f.formal == nil {
 		f.formal = make(map[string]*Flag)
diff -r 6bbd6af8c8a4 libgo/go/fmt/doc.go
--- a/libgo/go/fmt/doc.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/fmt/doc.go	Mon Jun 25 08:37:48 2012 -0700
@@ -136,7 +136,7 @@
 	Fscanf and Fscanln read from a specified io.Reader; Sscan,
 	Sscanf and Sscanln read from an argument string.  Scanln,
 	Fscanln and Sscanln stop scanning at a newline and require that
-	the items be followed by one; Sscanf, Fscanf and Sscanf require
+	the items be followed by one; Scanf, Fscanf and Sscanf require
 	newlines in the input to match newlines in the format; the other
 	routines treat newlines as spaces.
 
diff -r 6bbd6af8c8a4 libgo/go/go/ast/ast.go
--- a/libgo/go/go/ast/ast.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/go/ast/ast.go	Mon Jun 25 08:37:48 2012 -0700
@@ -87,8 +87,12 @@
 	return s[0:i]
 }
 
-// Text returns the text of the comment,
-// with the comment markers - //, /*, and */ - removed.
+// Text returns the text of the comment.
+// Comment markers (//, /*, and */), the first space of a line comment, and
+// leading and trailing empty lines are removed. Multiple empty lines are
+// reduced to one, and trailing space on lines is trimmed. Unless the result
+// is empty, it is newline-terminated.
+//
 func (g *CommentGroup) Text() string {
 	if g == nil {
 		return ""
@@ -104,11 +108,9 @@
 		// The parser has given us exactly the comment text.
 		switch c[1] {
 		case '/':
-			//-style comment
+			//-style comment (no newline at the end)
 			c = c[2:]
-			// Remove leading space after //, if there is one.
-			// TODO(gri) This appears to be necessary in isolated
-			//           cases (bignum.RatFromString) - why?
+			// strip first space - required for Example tests
 			if len(c) > 0 && c[0] == ' ' {
 				c = c[1:]
 			}
diff -r 6bbd6af8c8a4 libgo/go/go/ast/ast_test.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/go/go/ast/ast_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -0,0 +1,50 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ast
+
+import (
+	"testing"
+)
+
+var comments = []struct {
+	list []string
+	text string
+}{
+	{[]string{"//"}, ""},
+	{[]string{"//   "}, ""},
+	{[]string{"//", "//", "//   "}, ""},
+	{[]string{"// foo   "}, "foo\n"},
+	{[]string{"//", "//", "// foo"}, "foo\n"},
+	{[]string{"// foo  bar  "}, "foo  bar\n"},
+	{[]string{"// foo", "// bar"}, "foo\nbar\n"},
+	{[]string{"// foo", "//", "//", "//", "// bar"}, "foo\n\nbar\n"},
+	{[]string{"// foo", "/* bar */"}, "foo\n bar\n"},
+	{[]string{"//", "//", "//", "// foo", "//", "//", "//"}, "foo\n"},
+
+	{[]string{"/**/"}, ""},
+	{[]string{"/*   */"}, ""},
+	{[]string{"/**/", "/**/", "/*   */"}, ""},
+	{[]string{"/* Foo   */"}, " Foo\n"},
+	{[]string{"/* Foo  Bar  */"}, " Foo  Bar\n"},
+	{[]string{"/* Foo*/", "/* Bar*/"}, " Foo\n Bar\n"},
+	{[]string{"/* Foo*/", "/**/", "/**/", "/**/", "// Bar"}, " Foo\n\nBar\n"},
+	{[]string{"/* Foo*/", "/*\n*/", "//", "/*\n*/", "// Bar"}, " Foo\n\nBar\n"},
+	{[]string{"/* Foo*/", "// Bar"}, " Foo\nBar\n"},
+	{[]string{"/* Foo\n Bar*/"}, " Foo\n Bar\n"},
+}
+
+func TestCommentText(t *testing.T) {
+	for i, c := range comments {
+		list := make([]*Comment, len(c.list))
+		for i, s := range c.list {
+			list[i] = &Comment{Text: s}
+		}
+
+		text := (&CommentGroup{list}).Text()
+		if text != c.text {
+			t.Errorf("case %d: got %q; expected %q", i, text, c.text)
+		}
+	}
+}
diff -r 6bbd6af8c8a4 libgo/go/go/build/build.go
--- a/libgo/go/go/build/build.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/go/build/build.go	Mon Jun 25 08:37:48 2012 -0700
@@ -68,7 +68,7 @@
 
 	// ReadDir returns a slice of os.FileInfo, sorted by Name,
 	// describing the content of the named directory.
-	// If ReadDir is nil, Import uses io.ReadDir.
+	// If ReadDir is nil, Import uses ioutil.ReadDir.
 	ReadDir func(dir string) (fi []os.FileInfo, err error)
 
 	// OpenFile opens a file (not a directory) for reading.
@@ -339,7 +339,7 @@
 //	- files starting with _ or . (likely editor temporary files)
 //	- files with build constraints not satisfied by the context
 //
-// If an error occurs, Import returns a non-nil error also returns a non-nil
+// If an error occurs, Import returns a non-nil error and a non-nil
 // *Package containing partial information.
 //
 func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) {
diff -r 6bbd6af8c8a4 libgo/go/go/parser/parser.go
--- a/libgo/go/go/parser/parser.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/go/parser/parser.go	Mon Jun 25 08:37:48 2012 -0700
@@ -267,13 +267,13 @@
 
 // Consume a group of adjacent comments, add it to the parser's
 // comments list, and return it together with the line at which
-// the last comment in the group ends. An empty line or non-comment
-// token terminates a comment group.
+// the last comment in the group ends. A non-comment token or n
+// empty lines terminate a comment group.
 //
-func (p *parser) consumeCommentGroup() (comments *ast.CommentGroup, endline int) {
+func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) {
 	var list []*ast.Comment
 	endline = p.file.Line(p.pos)
-	for p.tok == token.COMMENT && endline+1 >= p.file.Line(p.pos) {
+	for p.tok == token.COMMENT && p.file.Line(p.pos) <= endline+n {
 		var comment *ast.Comment
 		comment, endline = p.consumeComment()
 		list = append(list, comment)
@@ -314,7 +314,7 @@
 		if p.file.Line(p.pos) == line {
 			// The comment is on same line as the previous token; it
 			// cannot be a lead comment but may be a line comment.
-			comment, endline = p.consumeCommentGroup()
+			comment, endline = p.consumeCommentGroup(0)
 			if p.file.Line(p.pos) != endline {
 				// The next token is on a different line, thus
 				// the last comment group is a line comment.
@@ -325,7 +325,7 @@
 		// consume successor comments, if any
 		endline = -1
 		for p.tok == token.COMMENT {
-			comment, endline = p.consumeCommentGroup()
+			comment, endline = p.consumeCommentGroup(1)
 		}
 
 		if endline+1 == p.file.Line(p.pos) {
@@ -627,10 +627,10 @@
 
 	doc := p.leadComment
 
-	// fields
+	// FieldDecl
 	list, typ := p.parseVarList(false)
 
-	// optional tag
+	// Tag
 	var tag *ast.BasicLit
 	if p.tok == token.STRING {
 		tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
@@ -645,7 +645,6 @@
 	} else {
 		// ["*"] TypeName (AnonymousField)
 		typ = list[0] // we always have at least one element
-		p.resolve(typ)
 		if n := len(list); n > 1 || !isTypeName(deref(typ)) {
 			pos := typ.Pos()
 			p.errorExpected(pos, "anonymous field")
@@ -657,6 +656,7 @@
 
 	field := &ast.Field{Doc: doc, Names: idents, Type: typ, Tag: tag, Comment: p.lineComment}
 	p.declare(field, nil, scope, ast.Var, idents...)
+	p.resolve(typ)
 
 	return field
 }
@@ -699,12 +699,15 @@
 	return &ast.StarExpr{Star: star, X: base}
 }
 
+// If the result is an identifier, it is not resolved.
 func (p *parser) tryVarType(isParam bool) ast.Expr {
 	if isParam && p.tok == token.ELLIPSIS {
 		pos := p.pos
 		p.next()
 		typ := p.tryIdentOrType(isParam) // don't use parseType so we can provide better error message
-		if typ == nil {
+		if typ != nil {
+			p.resolve(typ)
+		} else {
 			p.error(pos, "'...' parameter is missing type")
 			typ = &ast.BadExpr{From: pos, To: p.pos}
 		}
@@ -713,6 +716,7 @@
 	return p.tryIdentOrType(false)
 }
 
+// If the result is an identifier, it is not resolved.
 func (p *parser) parseVarType(isParam bool) ast.Expr {
 	typ := p.tryVarType(isParam)
 	if typ == nil {
@@ -724,6 +728,7 @@
 	return typ
 }
 
+// If any of the results are identifiers, they are not resolved.
 func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
 	if p.trace {
 		defer un(trace(p, "VarList"))
@@ -744,9 +749,7 @@
 	}
 
 	// if we had a list of identifiers, it must be followed by a type
-	if typ = p.tryVarType(isParam); typ != nil {
-		p.resolve(typ)
-	}
+	typ = p.tryVarType(isParam)
 
 	return
 }
@@ -756,7 +759,10 @@
 		defer un(trace(p, "ParameterList"))
 	}
 
+	// ParameterDecl
 	list, typ := p.parseVarList(ellipsisOk)
+
+	// analyze case
 	if typ != nil {
 		// IdentifierList Type
 		idents := p.makeIdentList(list)
@@ -765,10 +771,10 @@
 		// Go spec: The scope of an identifier denoting a function
 		// parameter or result variable is the function body.
 		p.declare(field, nil, scope, ast.Var, idents...)
+		p.resolve(typ)
 		if p.tok == token.COMMA {
 			p.next()
 		}
-
 		for p.tok != token.RPAREN && p.tok != token.EOF {
 			idents := p.parseIdentList()
 			typ := p.parseVarType(ellipsisOk)
@@ -777,18 +783,18 @@
 			// Go spec: The scope of an identifier denoting a function
 			// parameter or result variable is the function body.
 			p.declare(field, nil, scope, ast.Var, idents...)
+			p.resolve(typ)
 			if !p.atComma("parameter list") {
 				break
 			}
 			p.next()
 		}
-
 	} else {
 		// Type { "," Type } (anonymous parameters)
 		params = make([]*ast.Field, len(list))
-		for i, x := range list {
-			p.resolve(x)
-			params[i] = &ast.Field{Type: x}
+		for i, typ := range list {
+			p.resolve(typ)
+			params[i] = &ast.Field{Type: typ}
 		}
 	}
 
diff -r 6bbd6af8c8a4 libgo/go/go/parser/parser_test.go
--- a/libgo/go/go/parser/parser_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/go/parser/parser_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -5,10 +5,12 @@
 package parser
 
 import (
+	"bytes"
 	"fmt"
 	"go/ast"
 	"go/token"
 	"os"
+	"strings"
 	"testing"
 )
 
@@ -25,7 +27,7 @@
 	for _, filename := range validFiles {
 		_, err := ParseFile(fset, filename, nil, DeclarationErrors)
 		if err != nil {
-			t.Errorf("ParseFile(%s): %v", filename, err)
+			t.Fatalf("ParseFile(%s): %v", filename, err)
 		}
 	}
 }
@@ -70,7 +72,7 @@
 	src := "a + b"
 	x, err := ParseExpr(src)
 	if err != nil {
-		t.Errorf("ParseExpr(%s): %v", src, err)
+		t.Fatalf("ParseExpr(%s): %v", src, err)
 	}
 	// sanity check
 	if _, ok := x.(*ast.BinaryExpr); !ok {
@@ -81,7 +83,7 @@
 	src = "a + *"
 	_, err = ParseExpr(src)
 	if err == nil {
-		t.Errorf("ParseExpr(%s): %v", src, err)
+		t.Fatalf("ParseExpr(%s): %v", src, err)
 	}
 
 	// it must not crash
@@ -93,7 +95,7 @@
 func TestColonEqualsScope(t *testing.T) {
 	f, err := ParseFile(fset, "", `package p; func f() { x, y, z := x, y, z }`, 0)
 	if err != nil {
-		t.Errorf("parse: %s", err)
+		t.Fatal(err)
 	}
 
 	// RHS refers to undefined globals; LHS does not.
@@ -115,7 +117,7 @@
 func TestVarScope(t *testing.T) {
 	f, err := ParseFile(fset, "", `package p; func f() { var x, y, z = x, y, z }`, 0)
 	if err != nil {
-		t.Errorf("parse: %s", err)
+		t.Fatal(err)
 	}
 
 	// RHS refers to undefined globals; LHS does not.
@@ -133,6 +135,67 @@
 	}
 }
 
+func TestUnresolved(t *testing.T) {
+	f, err := ParseFile(fset, "", `
+package p
+//
+func f1a(int)
+func f2a(byte, int, float)
+func f3a(a, b int, c float)
+func f4a(...complex)
+func f5a(a s1a, b ...complex)
+//
+func f1b(*int)
+func f2b([]byte, (int), *float)
+func f3b(a, b *int, c []float)
+func f4b(...*complex)
+func f5b(a s1a, b ...[]complex)
+//
+type s1a struct { int }
+type s2a struct { byte; int; s1a }
+type s3a struct { a, b int; c float }
+//
+type s1b struct { *int }
+type s2b struct { byte; int; *float }
+type s3b struct { a, b *s3b; c []float }
+`, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	want := "int " + // f1a
+		"byte int float " + // f2a
+		"int float " + // f3a
+		"complex " + // f4a
+		"complex " + // f5a
+		//
+		"int " + // f1b
+		"byte int float " + // f2b
+		"int float " + // f3b
+		"complex " + // f4b
+		"complex " + // f5b
+		//
+		"int " + // s1a
+		"byte int " + // s2a
+		"int float " + // s3a
+		//
+		"int " + // s1a
+		"byte int float " + // s2a
+		"float " // s3a
+
+	// collect unresolved identifiers
+	var buf bytes.Buffer
+	for _, u := range f.Unresolved {
+		buf.WriteString(u.Name)
+		buf.WriteByte(' ')
+	}
+	got := buf.String()
+
+	if got != want {
+		t.Errorf("\ngot:  %s\nwant: %s", got, want)
+	}
+}
+
 var imports = map[string]bool{
 	`"a"`:        true,
 	"`a`":        true,
@@ -177,3 +240,125 @@
 		}
 	}
 }
+
+func TestCommentGroups(t *testing.T) {
+	f, err := ParseFile(fset, "", `
+package p /* 1a */ /* 1b */      /* 1c */ // 1d
+/* 2a
+*/
+// 2b
+const pi = 3.1415
+/* 3a */ // 3b
+/* 3c */ const e = 2.7182
+
+// Example from issue 3139
+func ExampleCount() {
+	fmt.Println(strings.Count("cheese", "e"))
+	fmt.Println(strings.Count("five", "")) // before & after each rune
+	// Output:
+	// 3
+	// 5
+}
+`, ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+	expected := [][]string{
+		{"/* 1a */", "/* 1b */", "/* 1c */", "// 1d"},
+		{"/* 2a\n*/", "// 2b"},
+		{"/* 3a */", "// 3b", "/* 3c */"},
+		{"// Example from issue 3139"},
+		{"// before & after each rune"},
+		{"// Output:", "// 3", "// 5"},
+	}
+	if len(f.Comments) != len(expected) {
+		t.Fatalf("got %d comment groups; expected %d", len(f.Comments), len(expected))
+	}
+	for i, exp := range expected {
+		got := f.Comments[i].List
+		if len(got) != len(exp) {
+			t.Errorf("got %d comments in group %d; expected %d", len(got), i, len(exp))
+			continue
+		}
+		for j, exp := range exp {
+			got := got[j].Text
+			if got != exp {
+				t.Errorf("got %q in group %d; expected %q", got, i, exp)
+			}
+		}
+	}
+}
+
+func getField(file *ast.File, fieldname string) *ast.Field {
+	parts := strings.Split(fieldname, ".")
+	for _, d := range file.Decls {
+		if d, ok := d.(*ast.GenDecl); ok && d.Tok == token.TYPE {
+			for _, s := range d.Specs {
+				if s, ok := s.(*ast.TypeSpec); ok && s.Name.Name == parts[0] {
+					if s, ok := s.Type.(*ast.StructType); ok {
+						for _, f := range s.Fields.List {
+							for _, name := range f.Names {
+								if name.Name == parts[1] {
+									return f
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// Don't use ast.CommentGroup.Text() - we want to see exact comment text.
+func commentText(c *ast.CommentGroup) string {
+	var buf bytes.Buffer
+	if c != nil {
+		for _, c := range c.List {
+			buf.WriteString(c.Text)
+		}
+	}
+	return buf.String()
+}
+
+func checkFieldComments(t *testing.T, file *ast.File, fieldname, lead, line string) {
+	f := getField(file, fieldname)
+	if f == nil {
+		t.Fatalf("field not found: %s", fieldname)
+	}
+	if got := commentText(f.Doc); got != lead {
+		t.Errorf("got lead comment %q; expected %q", got, lead)
+	}
+	if got := commentText(f.Comment); got != line {
+		t.Errorf("got line comment %q; expected %q", got, line)
+	}
+}
+
+func TestLeadAndLineComments(t *testing.T) {
+	f, err := ParseFile(fset, "", `
+package p
+type T struct {
+	/* F1 lead comment */
+	//
+	F1 int  /* F1 */ // line comment
+	// F2 lead
+	// comment
+	F2 int  // F2 line comment
+	// f3 lead comment
+	f3 int  // f3 line comment
+}
+`, ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+	checkFieldComments(t, f, "T.F1", "/* F1 lead comment *///", "/* F1 */// line comment")
+	checkFieldComments(t, f, "T.F2", "// F2 lead// comment", "// F2 line comment")
+	checkFieldComments(t, f, "T.f3", "// f3 lead comment", "// f3 line comment")
+	ast.FileExports(f)
+	checkFieldComments(t, f, "T.F1", "/* F1 lead comment *///", "/* F1 */// line comment")
+	checkFieldComments(t, f, "T.F2", "// F2 lead// comment", "// F2 line comment")
+	if getField(f, "T.f3") != nil {
+		t.Error("not expected to find T.f3")
+	}
+}
diff -r 6bbd6af8c8a4 libgo/go/go/printer/nodes.go
--- a/libgo/go/go/printer/nodes.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/go/printer/nodes.go	Mon Jun 25 08:37:48 2012 -0700
@@ -60,8 +60,8 @@
 
 // setComment sets g as the next comment if g != nil and if node comments
 // are enabled - this mode is used when printing source code fragments such
-// as exports only. It assumes that there are no other pending comments to
-// intersperse.
+// as exports only. It assumes that there is no pending comment in p.comments
+// and at most one pending comment in the p.comment cache.
 func (p *printer) setComment(g *ast.CommentGroup) {
 	if g == nil || !p.useNodeComments {
 		return
@@ -74,10 +74,19 @@
 		// should never happen - handle gracefully and flush
 		// all comments up to g, ignore anything after that
 		p.flush(p.posFor(g.List[0].Pos()), token.ILLEGAL)
+		p.comments = p.comments[0:1]
+		// in debug mode, report error
+		p.internalError("setComment found pending comments")
 	}
 	p.comments[0] = g
 	p.cindex = 0
-	p.nextComment() // get comment ready for use
+	// don't overwrite any pending comment in the p.comment cache
+	// (there may be a pending comment when a line comment is
+	// immediately followed by a lead comment with no other
+	// tokens inbetween)
+	if p.commentOffset == infinity {
+		p.nextComment() // get comment ready for use
+	}
 }
 
 type exprListMode uint
diff -r 6bbd6af8c8a4 libgo/go/log/log.go
--- a/libgo/go/log/log.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/log/log.go	Mon Jun 25 08:37:48 2012 -0700
@@ -26,7 +26,7 @@
 	// Bits or'ed together to control what's printed. There is no control over the
 	// order they appear (the order listed here) or the format they present (as
 	// described in the comments).  A colon appears after these items:
-	//	2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
+	//	2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
 	Ldate         = 1 << iota     // the date: 2009/01/23
 	Ltime                         // the time: 01:23:23
 	Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
diff -r 6bbd6af8c8a4 libgo/go/math/big/nat.go
--- a/libgo/go/math/big/nat.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/math/big/nat.go	Mon Jun 25 08:37:48 2012 -0700
@@ -271,10 +271,10 @@
 	//   xd = x1 - x0
 	//   yd = y0 - y1
 	//
-	//   z1 =      xd*yd                    + z1 + z0
-	//      = (x1-x0)*(y0 - y1)             + z1 + z0
-	//      = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z1 + z0
-	//      = x1*y0 -    z1 -    z0 + x0*y1 + z1 + z0
+	//   z1 =      xd*yd                    + z2 + z0
+	//      = (x1-x0)*(y0 - y1)             + z2 + z0
+	//      = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z2 + z0
+	//      = x1*y0 -    z2 -    z0 + x0*y1 + z2 + z0
 	//      = x1*y0                 + x0*y1
 
 	// split x, y into "digits"
@@ -318,7 +318,7 @@
 	// save original z2:z0
 	// (ok to use upper half of z since we're done recursing)
 	r := z[n*4:]
-	copy(r, z)
+	copy(r, z[:n*2])
 
 	// add up all partial products
 	//
diff -r 6bbd6af8c8a4 libgo/go/math/big/nat_test.go
--- a/libgo/go/math/big/nat_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/math/big/nat_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -661,3 +661,21 @@
 		}
 	}
 }
+
+func ExpHelper(b *testing.B, x, y Word) {
+	var z nat
+	for i := 0; i < b.N; i++ {
+		z.expWW(x, y)
+	}
+}
+
+func BenchmarkExp3Power0x10(b *testing.B)     { ExpHelper(b, 3, 0x10) }
+func BenchmarkExp3Power0x40(b *testing.B)     { ExpHelper(b, 3, 0x40) }
+func BenchmarkExp3Power0x100(b *testing.B)    { ExpHelper(b, 3, 0x100) }
+func BenchmarkExp3Power0x400(b *testing.B)    { ExpHelper(b, 3, 0x400) }
+func BenchmarkExp3Power0x1000(b *testing.B)   { ExpHelper(b, 3, 0x1000) }
+func BenchmarkExp3Power0x4000(b *testing.B)   { ExpHelper(b, 3, 0x4000) }
+func BenchmarkExp3Power0x10000(b *testing.B)  { ExpHelper(b, 3, 0x10000) }
+func BenchmarkExp3Power0x40000(b *testing.B)  { ExpHelper(b, 3, 0x40000) }
+func BenchmarkExp3Power0x100000(b *testing.B) { ExpHelper(b, 3, 0x100000) }
+func BenchmarkExp3Power0x400000(b *testing.B) { ExpHelper(b, 3, 0x400000) }
diff -r 6bbd6af8c8a4 libgo/go/mime/multipart/multipart.go
--- a/libgo/go/mime/multipart/multipart.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/mime/multipart/multipart.go	Mon Jun 25 08:37:48 2012 -0700
@@ -22,11 +22,6 @@
 	"net/textproto"
 )
 
-// TODO(bradfitz): inline these once the compiler can inline them in
-// read-only situation (such as bytes.HasSuffix)
-var lf = []byte("\n")
-var crlf = []byte("\r\n")
-
 var emptyParams = make(map[string]string)
 
 // A Part represents a single part in a multipart body.
@@ -36,8 +31,9 @@
 	// i.e. "foo-bar" changes case to "Foo-Bar"
 	Header textproto.MIMEHeader
 
-	buffer *bytes.Buffer
-	mr     *Reader
+	buffer    *bytes.Buffer
+	mr        *Reader
+	bytesRead int
 
 	disposition       string
 	dispositionParams map[string]string
@@ -113,14 +109,26 @@
 // Read reads the body of a part, after its headers and before the
 // next part (if any) begins.
 func (p *Part) Read(d []byte) (n int, err error) {
+	defer func() {
+		p.bytesRead += n
+	}()
 	if p.buffer.Len() >= len(d) {
 		// Internal buffer of unconsumed data is large enough for
 		// the read request.  No need to parse more at the moment.
 		return p.buffer.Read(d)
 	}
 	peek, err := p.mr.bufReader.Peek(4096) // TODO(bradfitz): add buffer size accessor
-	unexpectedEof := err == io.EOF
-	if err != nil && !unexpectedEof {
+
+	// Look for an immediate empty part without a leading \r\n
+	// before the boundary separator.  Some MIME code makes empty
+	// parts like this. Most browsers, however, write the \r\n
+	// before the subsequent boundary even for empty parts and
+	// won't hit this path.
+	if p.bytesRead == 0 && p.mr.peekBufferIsEmptyPart(peek) {
+		return 0, io.EOF
+	}
+	unexpectedEOF := err == io.EOF
+	if err != nil && !unexpectedEOF {
 		return 0, fmt.Errorf("multipart: Part Read: %v", err)
 	}
 	if peek == nil {
@@ -138,7 +146,7 @@
 		foundBoundary = true
 	} else if safeCount := len(peek) - len(p.mr.nlDashBoundary); safeCount > 0 {
 		nCopy = safeCount
-	} else if unexpectedEof {
+	} else if unexpectedEOF {
 		// If we've run out of peek buffer and the boundary
 		// wasn't found (and can't possibly fit), we must have
 		// hit the end of the file unexpectedly.
@@ -172,7 +180,10 @@
 	currentPart *Part
 	partsRead   int
 
-	nl, nlDashBoundary, dashBoundaryDash, dashBoundary []byte
+	nl               []byte // "\r\n" or "\n" (set after seeing first boundary line)
+	nlDashBoundary   []byte // nl + "--boundary"
+	dashBoundaryDash []byte // "--boundary--"
+	dashBoundary     []byte // "--boundary"
 }
 
 // NextPart returns the next part in the multipart or an error.
@@ -185,7 +196,7 @@
 	expectNewPart := false
 	for {
 		line, err := r.bufReader.ReadSlice('\n')
-		if err == io.EOF && bytes.Equal(line, r.dashBoundaryDash) {
+		if err == io.EOF && r.isFinalBoundary(line) {
 			// If the buffer ends in "--boundary--" without the
 			// trailing "\r\n", ReadSlice will return an error
 			// (since it's missing the '\n'), but this is a valid
@@ -207,7 +218,7 @@
 			return bp, nil
 		}
 
-		if hasPrefixThenNewline(line, r.dashBoundaryDash) {
+		if r.isFinalBoundary(line) {
 			// Expected EOF
 			return nil, io.EOF
 		}
@@ -235,7 +246,19 @@
 	panic("unreachable")
 }
 
-func (mr *Reader) isBoundaryDelimiterLine(line []byte) bool {
+// isFinalBoundary returns whether line is the final boundary line
+// indiciating that all parts are over.
+// It matches `^--boundary--[ \t]*(\r\n)?$`
+func (mr *Reader) isFinalBoundary(line []byte) bool {
+	if !bytes.HasPrefix(line, mr.dashBoundaryDash) {
+		return false
+	}
+	rest := line[len(mr.dashBoundaryDash):]
+	rest = skipLWSPChar(rest)
+	return len(rest) == 0 || bytes.Equal(rest, mr.nl)
+}
+
+func (mr *Reader) isBoundaryDelimiterLine(line []byte) (ret bool) {
 	// http://tools.ietf.org/html/rfc2046#section-5.1
 	//   The boundary delimiter line is then defined as a line
 	//   consisting entirely of two hyphen characters ("-",
@@ -245,32 +268,52 @@
 	if !bytes.HasPrefix(line, mr.dashBoundary) {
 		return false
 	}
-	if bytes.HasSuffix(line, mr.nl) {
-		return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-len(mr.nl)])
+	rest := line[len(mr.dashBoundary):]
+	rest = skipLWSPChar(rest)
+
+	// On the first part, see our lines are ending in \n instead of \r\n
+	// and switch into that mode if so.  This is a violation of the spec,
+	// but occurs in practice.
+	if mr.partsRead == 0 && len(rest) == 1 && rest[0] == '\n' {
+		mr.nl = mr.nl[1:]
+		mr.nlDashBoundary = mr.nlDashBoundary[1:]
 	}
-	// Violate the spec and also support newlines without the
-	// carriage return...
-	if mr.partsRead == 0 && bytes.HasSuffix(line, lf) {
-		if onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-1]) {
-			mr.nl = mr.nl[1:]
-			mr.nlDashBoundary = mr.nlDashBoundary[1:]
-			return true
-		}
-	}
-	return false
+	return bytes.Equal(rest, mr.nl)
 }
 
-func onlyHorizontalWhitespace(s []byte) bool {
-	for _, b := range s {
-		if b != ' ' && b != '\t' {
-			return false
-		}
+// peekBufferIsEmptyPart returns whether the provided peek-ahead
+// buffer represents an empty part.  This is only called if we've not
+// already read any bytes in this part and checks for the case of MIME
+// software not writing the \r\n on empty parts. Some does, some
+// doesn't.
+//
+// This checks that what follows the "--boundary" is actually the end
+// ("--boundary--" with optional whitespace) or optional whitespace
+// and then a newline, so we don't catch "--boundaryFAKE", in which
+// case the whole line is part of the data.
+func (mr *Reader) peekBufferIsEmptyPart(peek []byte) bool {
+	// End of parts case.
+	// Test whether peek matches `^--boundary--[ \t]*(?:\r\n|$)`
+	if bytes.HasPrefix(peek, mr.dashBoundaryDash) {
+		rest := peek[len(mr.dashBoundaryDash):]
+		rest = skipLWSPChar(rest)
+		return bytes.HasPrefix(rest, mr.nl) || len(rest) == 0
 	}
-	return true
+	if !bytes.HasPrefix(peek, mr.dashBoundary) {
+		return false
+	}
+	// Test whether rest matches `^[ \t]*\r\n`)
+	rest := peek[len(mr.dashBoundary):]
+	rest = skipLWSPChar(rest)
+	return bytes.HasPrefix(rest, mr.nl)
 }
 
-func hasPrefixThenNewline(s, prefix []byte) bool {
-	return bytes.HasPrefix(s, prefix) &&
-		(len(s) == len(prefix)+1 && s[len(s)-1] == '\n' ||
-			len(s) == len(prefix)+2 && bytes.HasSuffix(s, crlf))
+// skipLWSPChar returns b with leading spaces and tabs removed.
+// RFC 822 defines:
+//    LWSP-char = SPACE / HTAB
+func skipLWSPChar(b []byte) []byte {
+	for len(b) > 0 && (b[0] == ' ' || b[0] == '\t') {
+		b = b[1:]
+	}
+	return b
 }
diff -r 6bbd6af8c8a4 libgo/go/mime/multipart/multipart_test.go
--- a/libgo/go/mime/multipart/multipart_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/mime/multipart/multipart_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -10,20 +10,13 @@
 	"fmt"
 	"io"
 	"io/ioutil"
+	"net/textproto"
 	"os"
+	"reflect"
 	"strings"
 	"testing"
 )
 
-func TestHorizontalWhitespace(t *testing.T) {
-	if !onlyHorizontalWhitespace([]byte(" \t")) {
-		t.Error("expected pass")
-	}
-	if onlyHorizontalWhitespace([]byte("foo bar")) {
-		t.Error("expected failure")
-	}
-}
-
 func TestBoundaryLine(t *testing.T) {
 	mr := NewReader(strings.NewReader(""), "myBoundary")
 	if !mr.isBoundaryDelimiterLine([]byte("--myBoundary\r\n")) {
@@ -319,29 +312,6 @@
 	}
 }
 
-func TestZeroLengthBody(t *testing.T) {
-	testBody := strings.Replace(`
-This is a multi-part message.  This line is ignored.
---MyBoundary
-foo: bar
-
-
---MyBoundary--
-`, "\n", "\r\n", -1)
-	r := NewReader(strings.NewReader(testBody), "MyBoundary")
-	part, err := r.NextPart()
-	if err != nil {
-		t.Fatalf("didn't get a part")
-	}
-	n, err := io.Copy(ioutil.Discard, part)
-	if err != nil {
-		t.Errorf("error reading part: %v", err)
-	}
-	if n != 0 {
-		t.Errorf("read %d bytes; expected 0", n)
-	}
-}
-
 type slowReader struct {
 	r io.Reader
 }
@@ -427,3 +397,214 @@
 		t.Fatalf("final outer NextPart = %v; want io.EOF", err)
 	}
 }
+
+type headerBody struct {
+	header textproto.MIMEHeader
+	body   string
+}
+
+func formData(key, value string) headerBody {
+	return headerBody{
+		textproto.MIMEHeader{
+			"Content-Type":        {"text/plain; charset=ISO-8859-1"},
+			"Content-Disposition": {"form-data; name=" + key},
+		},
+		value,
+	}
+}
+
+type parseTest struct {
+	name    string
+	in, sep string
+	want    []headerBody
+}
+
+var parseTests = []parseTest{
+	// Actual body from App Engine on a blob upload. The final part (the
+	// Content-Type: message/external-body) is what App Engine replaces
+	// the uploaded file with.  The other form fields (prefixed with
+	// "other" in their form-data name) are unchanged.  A bug was
+	// reported with blob uploads failing when the other fields were
+	// empty. This was the MIME POST body that previously failed.
+	{
+		name: "App Engine post",
+		sep:  "00151757727e9583fd04bfbca4c6",
+		in:   "--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherEmpty1\r\n\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherFoo1\r\n\r\nfoo\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherFoo2\r\n\r\nfoo\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherEmpty2\r\n\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherRepeatFoo\r\n\r\nfoo\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherRepeatFoo\r\n\r\nfoo\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherRepeatEmpty\r\n\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=otherRepeatEmpty\r\n\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=submit\r\n\r\nSubmit\r\n--00151757727e9583fd04bfbca4c6\r\nContent-Type: message/external-body; charset=ISO-8859-1; blob-key=AHAZQqG84qllx7HUqO_oou5EvdYQNS3Mbbkb0RjjBoM_Kc1UqEN2ygDxWiyCPulIhpHRPx-VbpB6RX4MrsqhWAi_ZxJ48O9P2cTIACbvATHvg7IgbvZytyGMpL7xO1tlIvgwcM47JNfv_tGhy1XwyEUO8oldjPqg5Q\r\nContent-Disposition: form-data; name=file; filename=\"fall.png\"\r\n\r\nContent-Type: image/png\r\nContent-Length: 232303\r\nX-AppEngine-Upload-Creation: 2012-05-10 23:14:02.715173\r\nContent-MD5: MzRjODU1ZDZhZGU1NmRlOWEwZmMwMDdlODBmZTA0NzA=\r\nContent-Disposition: form-data; name=file; filename=\"fall.png\"\r\n\r\n\r\n--00151757727e9583fd04bfbca4c6--",
+		want: []headerBody{
+			formData("otherEmpty1", ""),
+			formData("otherFoo1", "foo"),
+			formData("otherFoo2", "foo"),
+			formData("otherEmpty2", ""),
+			formData("otherRepeatFoo", "foo"),
+			formData("otherRepeatFoo", "foo"),
+			formData("otherRepeatEmpty", ""),
+			formData("otherRepeatEmpty", ""),
+			formData("submit", "Submit"),
+			{textproto.MIMEHeader{
+				"Content-Type":        {"message/external-body; charset=ISO-8859-1; blob-key=AHAZQqG84qllx7HUqO_oou5EvdYQNS3Mbbkb0RjjBoM_Kc1UqEN2ygDxWiyCPulIhpHRPx-VbpB6RX4MrsqhWAi_ZxJ48O9P2cTIACbvATHvg7IgbvZytyGMpL7xO1tlIvgwcM47JNfv_tGhy1XwyEUO8oldjPqg5Q"},
+				"Content-Disposition": {"form-data; name=file; filename=\"fall.png\""},
+			}, "Content-Type: image/png\r\nContent-Length: 232303\r\nX-AppEngine-Upload-Creation: 2012-05-10 23:14:02.715173\r\nContent-MD5: MzRjODU1ZDZhZGU1NmRlOWEwZmMwMDdlODBmZTA0NzA=\r\nContent-Disposition: form-data; name=file; filename=\"fall.png\"\r\n\r\n"},
+		},
+	},
+
+	// Single empty part, ended with --boundary immediately after headers.
+	{
+		name: "single empty part, --boundary",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n--abc--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	// Single empty part, ended with \r\n--boundary immediately after headers.
+	{
+		name: "single empty part, \r\n--boundary",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n\r\n--abc--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	// Final part empty.
+	{
+		name: "final part empty",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n--abc\r\nFoo2: bar2\r\n\r\n--abc--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+			{textproto.MIMEHeader{"Foo2": {"bar2"}}, ""},
+		},
+	},
+
+	// Final part empty with newlines after final separator.
+	{
+		name: "final part empty then crlf",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n--abc--\r\n",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	// Final part empty with lwsp-chars after final separator.
+	{
+		name: "final part empty then lwsp",
+		sep:  "abc",
+		in:   "--abc\r\nFoo: bar\r\n\r\n--abc-- \t",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	// No parts (empty form as submitted by Chrome)
+	{
+		name: "no parts",
+		sep:  "----WebKitFormBoundaryQfEAfzFOiSemeHfA",
+		in:   "------WebKitFormBoundaryQfEAfzFOiSemeHfA--\r\n",
+		want: []headerBody{},
+	},
+
+	// Part containing data starting with the boundary, but with additional suffix.
+	{
+		name: "fake separator as data",
+		sep:  "sep",
+		in:   "--sep\r\nFoo: bar\r\n\r\n--sepFAKE\r\n--sep--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, "--sepFAKE"},
+		},
+	},
+
+	// Part containing a boundary with whitespace following it.
+	{
+		name: "boundary with whitespace",
+		sep:  "sep",
+		in:   "--sep \r\nFoo: bar\r\n\r\ntext\r\n--sep--",
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, "text"},
+		},
+	},
+
+	// With ignored leading line.
+	{
+		name: "leading line",
+		sep:  "MyBoundary",
+		in: strings.Replace(`This is a multi-part message.  This line is ignored.
+--MyBoundary
+foo: bar
+
+
+--MyBoundary--`, "\n", "\r\n", -1),
+		want: []headerBody{
+			{textproto.MIMEHeader{"Foo": {"bar"}}, ""},
+		},
+	},
+
+	roundTripParseTest(),
+}
+
+func TestParse(t *testing.T) {
+Cases:
+	for _, tt := range parseTests {
+		r := NewReader(strings.NewReader(tt.in), tt.sep)
+		got := []headerBody{}
+		for {
+			p, err := r.NextPart()
+			if err == io.EOF {
+				break
+			}
+			if err != nil {
+				t.Errorf("in test %q, NextPart: %v", tt.name, err)
+				continue Cases
+			}
+			pbody, err := ioutil.ReadAll(p)
+			if err != nil {
+				t.Errorf("in test %q, error reading part: %v", tt.name, err)
+				continue Cases
+			}
+			got = append(got, headerBody{p.Header, string(pbody)})
+		}
+		if !reflect.DeepEqual(tt.want, got) {
+			t.Errorf("test %q:\n got: %v\nwant: %v", tt.name, got, tt.want)
+			if len(tt.want) != len(got) {
+				t.Errorf("test %q: got %d parts, want %d", tt.name, len(got), len(tt.want))
+			} else if len(got) > 1 {
+				for pi, wantPart := range tt.want {
+					if !reflect.DeepEqual(wantPart, got[pi]) {
+						t.Errorf("test %q, part %d:\n got: %v\nwant: %v", tt.name, pi, got[pi], wantPart)
+					}
+				}
+			}
+		}
+	}
+}
+
+func roundTripParseTest() parseTest {
+	t := parseTest{
+		name: "round trip",
+		want: []headerBody{
+			formData("empty", ""),
+			formData("lf", "\n"),
+			formData("cr", "\r"),
+			formData("crlf", "\r\n"),
+			formData("foo", "bar"),
+		},
+	}
+	var buf bytes.Buffer
+	w := NewWriter(&buf)
+	for _, p := range t.want {
+		pw, err := w.CreatePart(p.header)
+		if err != nil {
+			panic(err)
+		}
+		_, err = pw.Write([]byte(p.body))
+		if err != nil {
+			panic(err)
+		}
+	}
+	w.Close()
+	t.in = buf.String()
+	t.sep = w.Boundary()
+	return t
+}
diff -r 6bbd6af8c8a4 libgo/go/net/file.go
--- a/libgo/go/net/file.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/file.go	Mon Jun 25 08:37:48 2012 -0700
@@ -89,8 +89,8 @@
 
 // FileListener returns a copy of the network listener corresponding
 // to the open file f.  It is the caller's responsibility to close l
-// when finished.  Closing c does not affect l, and closing l does not
-// affect c.
+// when finished.  Closing l does not affect f, and closing f does not
+// affect l.
 func FileListener(f *os.File) (l Listener, err error) {
 	fd, err := newFileFD(f)
 	if err != nil {
diff -r 6bbd6af8c8a4 libgo/go/net/http/client.go
--- a/libgo/go/net/http/client.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/http/client.go	Mon Jun 25 08:37:48 2012 -0700
@@ -278,6 +278,11 @@
 		return nil, err
 	}
 	req.Header.Set("Content-Type", bodyType)
+	if c.Jar != nil {
+		for _, cookie := range c.Jar.Cookies(req.URL) {
+			req.AddCookie(cookie)
+		}
+	}
 	r, err = send(req, c.Transport)
 	if err == nil && c.Jar != nil {
 		c.Jar.SetCookies(req.URL, r.Cookies())
diff -r 6bbd6af8c8a4 libgo/go/net/http/client_test.go
--- a/libgo/go/net/http/client_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/http/client_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -256,6 +256,31 @@
 	}
 })
 
+func TestClientSendsCookieFromJar(t *testing.T) {
+	tr := &recordingTransport{}
+	client := &Client{Transport: tr}
+	client.Jar = &TestJar{perURL: make(map[string][]*Cookie)}
+	us := "http://dummy.faketld/";
+	u, _ := url.Parse(us)
+	client.Jar.SetCookies(u, expectedCookies)
+
+	client.Get(us) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	client.Head(us) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	client.Post(us, "text/plain", strings.NewReader("body")) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	client.PostForm(us, url.Values{}) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	req, _ := NewRequest("GET", us, nil)
+	client.Do(req) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+}
+
 // Just enough correctness for our redirect tests. Uses the URL.Host as the
 // scope of all cookies.
 type TestJar struct {
diff -r 6bbd6af8c8a4 libgo/go/net/http/proxy_test.go
--- a/libgo/go/net/http/proxy_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/http/proxy_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -5,6 +5,7 @@
 package http
 
 import (
+	"net/url"
 	"os"
 	"testing"
 )
@@ -46,3 +47,32 @@
 		}
 	}
 }
+
+var cacheKeysTests = []struct {
+	proxy  string
+	scheme string
+	addr   string
+	key    string
+}{
+	{"", "http", "foo.com", "|http|foo.com"},
+	{"", "https", "foo.com", "|https|foo.com"},
+	{"http://foo.com";, "http", "foo.com", "http://foo.com|http|"},
+	{"http://foo.com";, "https", "foo.com", "http://foo.com|https|foo.com"},
+}
+
+func TestCacheKeys(t *testing.T) {
+	for _, tt := range cacheKeysTests {
+		var proxy *url.URL
+		if tt.proxy != "" {
+			u, err := url.Parse(tt.proxy)
+			if err != nil {
+				t.Fatal(err)
+			}
+			proxy = u
+		}
+		cm := connectMethod{proxy, tt.scheme, tt.addr}
+		if cm.String() != tt.key {
+			t.Fatalf("{%q, %q, %q} cache key %q; want %q", tt.proxy, tt.scheme, tt.addr, cm.String(), tt.key)
+		}
+	}
+}
diff -r 6bbd6af8c8a4 libgo/go/net/http/response.go
--- a/libgo/go/net/http/response.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/http/response.go	Mon Jun 25 08:37:48 2012 -0700
@@ -202,9 +202,12 @@
 			text = "status code " + strconv.Itoa(r.StatusCode)
 		}
 	}
-	io.WriteString(w, "HTTP/"+strconv.Itoa(r.ProtoMajor)+".")
-	io.WriteString(w, strconv.Itoa(r.ProtoMinor)+" ")
-	io.WriteString(w, strconv.Itoa(r.StatusCode)+" "+text+"\r\n")
+	protoMajor, protoMinor := strconv.Itoa(r.ProtoMajor), strconv.Itoa(r.ProtoMinor)
+	statusCode := strconv.Itoa(r.StatusCode) + " "
+	if strings.HasPrefix(text, statusCode) {
+		text = text[len(statusCode):]
+	}
+	io.WriteString(w, "HTTP/"+protoMajor+"."+protoMinor+" "+statusCode+text+"\r\n")
 
 	// Process Body,ContentLength,Close,Trailer
 	tw, err := newTransferWriter(r)
diff -r 6bbd6af8c8a4 libgo/go/net/http/response_test.go
--- a/libgo/go/net/http/response_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/http/response_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -14,6 +14,7 @@
 	"io/ioutil"
 	"net/url"
 	"reflect"
+	"strings"
 	"testing"
 )
 
@@ -444,3 +445,17 @@
 		}
 	}
 }
+
+func TestResponseStatusStutter(t *testing.T) {
+	r := &Response{
+		Status:     "123 some status",
+		StatusCode: 123,
+		ProtoMajor: 1,
+		ProtoMinor: 3,
+	}
+	var buf bytes.Buffer
+	r.Write(&buf)
+	if strings.Contains(buf.String(), "123 123") {
+		t.Errorf("stutter in status: %s", buf.String())
+	}
+}
diff -r 6bbd6af8c8a4 libgo/go/net/http/server.go
--- a/libgo/go/net/http/server.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/http/server.go	Mon Jun 25 08:37:48 2012 -0700
@@ -31,7 +31,7 @@
 // Errors introduced by the HTTP server.
 var (
 	ErrWriteAfterFlush = errors.New("Conn.Write called after Flush")
-	ErrBodyNotAllowed  = errors.New("http: response status code does not allow body")
+	ErrBodyNotAllowed  = errors.New("http: request method or response status code does not allow body")
 	ErrHijacked        = errors.New("Conn has been hijacked")
 	ErrContentLength   = errors.New("Conn.Write wrote more than the declared Content-Length")
 )
diff -r 6bbd6af8c8a4 libgo/go/net/http/transfer.go
--- a/libgo/go/net/http/transfer.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/http/transfer.go	Mon Jun 25 08:37:48 2012 -0700
@@ -71,7 +71,9 @@
 			}
 		}
 	case *Response:
-		t.Method = rr.Request.Method
+		if rr.Request != nil {
+			t.Method = rr.Request.Method
+		}
 		t.Body = rr.Body
 		t.BodyCloser = rr.Body
 		t.ContentLength = rr.ContentLength
@@ -79,7 +81,7 @@
 		t.TransferEncoding = rr.TransferEncoding
 		t.Trailer = rr.Trailer
 		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
-		t.ResponseToHEAD = noBodyExpected(rr.Request.Method)
+		t.ResponseToHEAD = noBodyExpected(t.Method)
 	}
 
 	// Sanitize Body,ContentLength,TransferEncoding
diff -r 6bbd6af8c8a4 libgo/go/net/http/transport.go
--- a/libgo/go/net/http/transport.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/http/transport.go	Mon Jun 25 08:37:48 2012 -0700
@@ -450,10 +450,14 @@
 
 func (ck *connectMethod) String() string {
 	proxyStr := ""
+	targetAddr := ck.targetAddr
 	if ck.proxyURL != nil {
 		proxyStr = ck.proxyURL.String()
+		if ck.targetScheme == "http" {
+			targetAddr = ""
+		}
 	}
-	return strings.Join([]string{proxyStr, ck.targetScheme, ck.targetAddr}, "|")
+	return strings.Join([]string{proxyStr, ck.targetScheme, targetAddr}, "|")
 }
 
 // addr returns the first hop "host:port" to which we need to TCP connect.
diff -r 6bbd6af8c8a4 libgo/go/net/mail/message.go
--- a/libgo/go/net/mail/message.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/mail/message.go	Mon Jun 25 08:37:48 2012 -0700
@@ -69,11 +69,12 @@
 func init() {
 	// Generate layouts based on RFC 5322, section 3.3.
 
-	dows := [...]string{"", "Mon, "}     // day-of-week
-	days := [...]string{"2", "02"}       // day = 1*2DIGIT
-	years := [...]string{"2006", "06"}   // year = 4*DIGIT / 2*DIGIT
-	seconds := [...]string{":05", ""}    // second
-	zones := [...]string{"-0700", "MST"} // zone = (("+" / "-") 4DIGIT) / "GMT" / ...
+	dows := [...]string{"", "Mon, "}   // day-of-week
+	days := [...]string{"2", "02"}     // day = 1*2DIGIT
+	years := [...]string{"2006", "06"} // year = 4*DIGIT / 2*DIGIT
+	seconds := [...]string{":05", ""}  // second
+	// "-0700 (MST)" is not in RFC 5322, but is common.
+	zones := [...]string{"-0700", "MST", "-0700 (MST)"} // zone = (("+" / "-") 4DIGIT) / "GMT" / ...
 
 	for _, dow := range dows {
 		for _, day := range days {
diff -r 6bbd6af8c8a4 libgo/go/net/mail/message_test.go
--- a/libgo/go/net/mail/message_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/mail/message_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -95,6 +95,11 @@
 			"21 Nov 97 09:55:06 GMT",
 			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("GMT", 0)),
 		},
+		// Commonly found format not specified by RFC 5322.
+		{
+			"Fri, 21 Nov 1997 09:55:06 -0600 (MDT)",
+			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)),
+		},
 	}
 	for _, test := range tests {
 		hdr := Header{
diff -r 6bbd6af8c8a4 libgo/go/net/url/url.go
--- a/libgo/go/net/url/url.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/url/url.go	Mon Jun 25 08:37:48 2012 -0700
@@ -401,11 +401,12 @@
 }
 
 func parseAuthority(authority string) (user *Userinfo, host string, err error) {
-	if strings.Index(authority, "@") < 0 {
+	i := strings.LastIndex(authority, "@")
+	if i < 0 {
 		host = authority
 		return
 	}
-	userinfo, host := split(authority, '@', true)
+	userinfo, host := authority[:i], authority[i+1:]
 	if strings.Index(userinfo, ":") < 0 {
 		if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
 			return
diff -r 6bbd6af8c8a4 libgo/go/net/url/url_test.go
--- a/libgo/go/net/url/url_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/net/url/url_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -188,6 +188,37 @@
 		},
 		"http://user:password@google.com";,
 	},
+	// unescaped @ in username should not confuse host
+	{
+		"http://j@ne:password@google.com";,
+		&URL{
+			Scheme: "http",
+			User:   UserPassword("j@ne", "password"),
+			Host:   "google.com",
+		},
+		"http://j%40ne:password@google.com";,
+	},
+	// unescaped @ in password should not confuse host
+	{
+		"http://jane:p@ssword@google.com";,
+		&URL{
+			Scheme: "http",
+			User:   UserPassword("jane", "p@ssword"),
+			Host:   "google.com",
+		},
+		"http://jane:p%40ssword@google.com";,
+	},
+	{
+		"http://j@ne:password@google.com/p@th?q=@go";,
+		&URL{
+			Scheme:   "http",
+			User:     UserPassword("j@ne", "password"),
+			Host:     "google.com",
+			Path:     "/p@th",
+			RawQuery: "q=@go",
+		},
+		"http://j%40ne:password@google.com/p@th?q=@go";,
+	},
 	{
 		"http://www.google.com/?q=go+language#foo";,
 		&URL{
diff -r 6bbd6af8c8a4 libgo/go/os/exec/exec.go
--- a/libgo/go/os/exec/exec.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/os/exec/exec.go	Mon Jun 25 08:37:48 2012 -0700
@@ -204,6 +204,12 @@
 	return pw, nil
 }
 
+func (c *Cmd) closeDescriptors(closers []io.Closer) {
+	for _, fd := range closers {
+		fd.Close()
+	}
+}
+
 // Run starts the specified command and waits for it to complete.
 //
 // The returned error is nil if the command runs, has no problems
@@ -233,6 +239,8 @@
 	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
 		fd, err := setupFd(c)
 		if err != nil {
+			c.closeDescriptors(c.closeAfterStart)
+			c.closeDescriptors(c.closeAfterWait)
 			return err
 		}
 		c.childFiles = append(c.childFiles, fd)
@@ -247,12 +255,12 @@
 		Sys:   c.SysProcAttr,
 	})
 	if err != nil {
+		c.closeDescriptors(c.closeAfterStart)
+		c.closeDescriptors(c.closeAfterWait)
 		return err
 	}
 
-	for _, fd := range c.closeAfterStart {
-		fd.Close()
-	}
+	c.closeDescriptors(c.closeAfterStart)
 
 	c.errch = make(chan error, len(c.goroutine))
 	for _, fn := range c.goroutine {
@@ -301,9 +309,7 @@
 		}
 	}
 
-	for _, fd := range c.closeAfterWait {
-		fd.Close()
-	}
+	c.closeDescriptors(c.closeAfterWait)
 
 	if err != nil {
 		return err
diff -r 6bbd6af8c8a4 libgo/go/path/filepath/path.go
--- a/libgo/go/path/filepath/path.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/path/filepath/path.go	Mon Jun 25 08:37:48 2012 -0700
@@ -320,8 +320,11 @@
 	}
 
 	for _, fileInfo := range list {
-		if err = walk(Join(path, fileInfo.Name()), fileInfo, walkFn); err != nil {
-			return err
+		err = walk(Join(path, fileInfo.Name()), fileInfo, walkFn)
+		if err != nil {
+			if !fileInfo.IsDir() || err != SkipDir {
+				return err
+			}
 		}
 	}
 	return nil
diff -r 6bbd6af8c8a4 libgo/go/path/filepath/path_plan9.go
--- a/libgo/go/path/filepath/path_plan9.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/path/filepath/path_plan9.go	Mon Jun 25 08:37:48 2012 -0700
@@ -12,7 +12,7 @@
 }
 
 // VolumeName returns the leading volume name on Windows.
-// It returns "" elsewhere
+// It returns "" elsewhere.
 func VolumeName(path string) string {
 	return ""
 }
diff -r 6bbd6af8c8a4 libgo/go/path/filepath/path_test.go
--- a/libgo/go/path/filepath/path_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/path/filepath/path_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -869,3 +869,34 @@
 		t.Errorf("Results of EvalSymlinks do not match: %q and %q", flp, fup)
 	}
 }
+
+/* This test does not work gccgo, since the sources are arranged
+   differently.
+
+func TestBug3486(t *testing.T) { // http://code.google.com/p/go/issues/detail?id=3486
+	root, err := filepath.EvalSymlinks(os.Getenv("GOROOT"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	lib := filepath.Join(root, "lib")
+	src := filepath.Join(root, "src")
+	seenSrc := false
+	filepath.Walk(root, func(pth string, info os.FileInfo, err error) error {
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		switch pth {
+		case lib:
+			return filepath.SkipDir
+		case src:
+			seenSrc = true
+		}
+		return nil
+	})
+	if !seenSrc {
+		t.Fatalf("%q not seen", src)
+	}
+}
+
+*/
diff -r 6bbd6af8c8a4 libgo/go/regexp/regexp.go
--- a/libgo/go/regexp/regexp.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/regexp/regexp.go	Mon Jun 25 08:37:48 2012 -0700
@@ -512,7 +512,7 @@
 }
 
 // ReplaceAll returns a copy of src, replacing matches of the Regexp
-// with the replacement string repl.  Inside repl, $ signs are interpreted as
+// with the replacement text repl.  Inside repl, $ signs are interpreted as
 // in Expand, so for instance $1 represents the text of the first submatch.
 func (re *Regexp) ReplaceAll(src, repl []byte) []byte {
 	n := 2
@@ -726,7 +726,7 @@
 // the submatch with the corresponding index; other names refer to
 // capturing parentheses named with the (?P<name>...) syntax.  A
 // reference to an out of range or unmatched index or a name that is not
-// present in the regular expression is replaced with an empty string.
+// present in the regular expression is replaced with an empty slice.
 // 
 // In the $name form, name is taken to be as long as possible: $1x is
 // equivalent to ${1x}, not ${1}x, and, $10 is equivalent to ${10}, not ${1}0.
diff -r 6bbd6af8c8a4 libgo/go/regexp/syntax/parse.go
--- a/libgo/go/regexp/syntax/parse.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/regexp/syntax/parse.go	Mon Jun 25 08:37:48 2012 -0700
@@ -48,6 +48,9 @@
 	ErrTrailingBackslash     ErrorCode = "trailing backslash at end of expression"
 )
 
+// TODO: Export for Go 1.1.
+const errUnexpectedParen ErrorCode = "unexpected )"
+
 func (e ErrorCode) String() string {
 	return string(e)
 }
@@ -1168,13 +1171,13 @@
 
 	n := len(p.stack)
 	if n < 2 {
-		return &Error{ErrInternalError, ""}
+		return &Error{errUnexpectedParen, p.wholeRegexp}
 	}
 	re1 := p.stack[n-1]
 	re2 := p.stack[n-2]
 	p.stack = p.stack[:n-2]
 	if re2.Op != opLeftParen {
-		return &Error{ErrMissingParen, p.wholeRegexp}
+		return &Error{errUnexpectedParen, p.wholeRegexp}
 	}
 	// Restore flags at time of paren.
 	p.flags = re2.Flags
diff -r 6bbd6af8c8a4 libgo/go/regexp/syntax/parse_test.go
--- a/libgo/go/regexp/syntax/parse_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/regexp/syntax/parse_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -442,10 +442,18 @@
 	`(`,
 	`)`,
 	`(a`,
+	`a)`,
+	`(a))`,
 	`(a|b|`,
+	`a|b|)`,
+	`(a|b|))`,
 	`(a|b`,
+	`a|b)`,
+	`(a|b))`,
 	`[a-z`,
 	`([a-z)`,
+	`[a-z)`,
+	`([a-z]))`,
 	`x{1001}`,
 	`x{9876543210}`,
 	`x{2,1}`,
diff -r 6bbd6af8c8a4 libgo/go/runtime/extern.go
--- a/libgo/go/runtime/extern.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/runtime/extern.go	Mon Jun 25 08:37:48 2012 -0700
@@ -20,7 +20,7 @@
 
 // Caller reports file and line number information about function invocations on
 // the calling goroutine's stack.  The argument skip is the number of stack frames
-// to ascend, with 1 identifying the caller of Caller.  (For historical reasons the
+// to ascend, with 0 identifying the caller of Caller.  (For historical reasons the
 // meaning of skip differs between Caller and Callers.) The return values report the
 // program counter, file name, and line number within the file of the corresponding
 // call.  The boolean ok is false if it was not possible to recover the information.
@@ -28,7 +28,8 @@
 
 // Callers fills the slice pc with the program counters of function invocations
 // on the calling goroutine's stack.  The argument skip is the number of stack frames
-// to skip before recording in pc, with 0 starting at the caller of Callers.
+// to skip before recording in pc, with 0 identifying the frame for Callers itself and
+// 1 identifying the caller of Callers.
 // It returns the number of entries written to pc.
 func Callers(skip int, pc []uintptr) int
 
diff -r 6bbd6af8c8a4 libgo/go/strconv/itoa.go
--- a/libgo/go/strconv/itoa.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/strconv/itoa.go	Mon Jun 25 08:37:48 2012 -0700
@@ -4,13 +4,17 @@
 
 package strconv
 
-// FormatUint returns the string representation of i in the given base.
+// FormatUint returns the string representation of i in the given base,
+// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
+// for digit values >= 10.
 func FormatUint(i uint64, base int) string {
 	_, s := formatBits(nil, i, base, false, false)
 	return s
 }
 
-// FormatInt returns the string representation of i in the given base.
+// FormatInt returns the string representation of i in the given base,
+// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
+// for digit values >= 10.
 func FormatInt(i int64, base int) string {
 	_, s := formatBits(nil, uint64(i), base, i < 0, false)
 	return s
diff -r 6bbd6af8c8a4 libgo/go/strings/example_test.go
--- a/libgo/go/strings/example_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/strings/example_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -41,7 +41,6 @@
 func ExampleCount() {
 	fmt.Println(strings.Count("cheese", "e"))
 	fmt.Println(strings.Count("five", "")) // before & after each rune
-
 	// Output:
 	// 3
 	// 5
diff -r 6bbd6af8c8a4 libgo/go/text/template/exec.go
--- a/libgo/go/text/template/exec.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/text/template/exec.go	Mon Jun 25 08:37:48 2012 -0700
@@ -518,6 +518,13 @@
 		}
 	}
 	if !value.Type().AssignableTo(typ) {
+		if value.Kind() == reflect.Interface && !value.IsNil() {
+			value = value.Elem()
+			if value.Type().AssignableTo(typ) {
+				return value
+			}
+			// fallthrough
+		}
 		// Does one dereference or indirection work? We could do more, as we
 		// do with method receivers, but that gets messy and method receivers
 		// are much more constrained, so it makes more sense there than here.
diff -r 6bbd6af8c8a4 libgo/go/text/template/exec_test.go
--- a/libgo/go/text/template/exec_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/text/template/exec_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -311,6 +311,7 @@
 	{".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=<he+llo>", tVal, true},
 	{"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true},
 	{"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true},
+	{"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true},
 
 	// Erroneous function calls (check args).
 	{".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false},
@@ -507,6 +508,10 @@
 	return "vfunc"
 }
 
+func stringer(s fmt.Stringer) string {
+	return s.String()
+}
+
 func testExecute(execTests []execTest, template *Template, t *testing.T) {
 	b := new(bytes.Buffer)
 	funcs := FuncMap{
@@ -516,6 +521,7 @@
 		"typeOf":   typeOf,
 		"vfunc":    vfunc,
 		"zeroArgs": zeroArgs,
+		"stringer": stringer,
 	}
 	for _, test := range execTests {
 		var tmpl *Template
diff -r 6bbd6af8c8a4 libgo/go/time/sleep_test.go
--- a/libgo/go/time/sleep_test.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/time/sleep_test.go	Mon Jun 25 08:37:48 2012 -0700
@@ -224,3 +224,25 @@
 	}
 	Sleep(3 * Second)
 }
+
+func TestSleepZeroDeadlock(t *testing.T) {
+	// Sleep(0) used to hang, the sequence of events was as follows.
+	// Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
+	// Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
+	// After the GC nobody wakes up the goroutine from Gwaiting status.
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	c := make(chan bool)
+	go func() {
+		for i := 0; i < 100; i++ {
+			runtime.GC()
+		}
+		c <- true
+	}()
+	for i := 0; i < 100; i++ {
+		Sleep(0)
+		tmp := make(chan bool, 1)
+		tmp <- true
+		<-tmp
+	}
+	<-c
+}
diff -r 6bbd6af8c8a4 libgo/go/unicode/tables.go
--- a/libgo/go/unicode/tables.go	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/go/unicode/tables.go	Mon Jun 25 08:37:48 2012 -0700
@@ -2701,7 +2701,7 @@
 	},
 }
 
-// The following variables are of type *RangeTable:
+// These variables have type *RangeTable.
 var (
 	Cc     = _Cc // Cc is the set of Unicode characters in category Cc.
 	Cf     = _Cf // Cf is the set of Unicode characters in category Cf.
@@ -4054,7 +4054,7 @@
 	},
 }
 
-// The following variables are of type *RangeTable:
+// These variables have type *RangeTable.
 var (
 	Arabic                 = _Arabic                 // Arabic is the set of Unicode characters in script Arabic.
 	Armenian               = _Armenian               // Armenian is the set of Unicode characters in script Armenian.
@@ -5116,7 +5116,7 @@
 	},
 }
 
-// The following variables are of type *RangeTable:
+// These variables have type *RangeTable.
 var (
 	ASCII_Hex_Digit                    = _ASCII_Hex_Digit                    // ASCII_Hex_Digit is the set of Unicode characters with property ASCII_Hex_Digit.
 	Bidi_Control                       = _Bidi_Control                       // Bidi_Control is the set of Unicode characters with property Bidi_Control.
diff -r 6bbd6af8c8a4 libgo/runtime/malloc.goc
--- a/libgo/runtime/malloc.goc	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/runtime/malloc.goc	Mon Jun 25 08:37:48 2012 -0700
@@ -168,6 +168,7 @@
 		c->local_by_size[sizeclass].nfree++;
 		runtime_MCache_Free(c, v, sizeclass, size);
 	}
+	c->local_nfree++;
 	c->local_alloc -= size;
 	if(prof)
 		runtime_MProf_Free(v, size);
diff -r 6bbd6af8c8a4 libgo/runtime/mfinal.c
--- a/libgo/runtime/mfinal.c	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/runtime/mfinal.c	Mon Jun 25 08:37:48 2012 -0700
@@ -150,8 +150,7 @@
 	tab = TAB(p);
 	runtime_lock(tab);
 	if(f == nil) {
-		if(lookfintab(tab, p, true, nil))
-			runtime_setblockspecial(p, false);
+		lookfintab(tab, p, true, nil);
 		runtime_unlock(tab);
 		return true;
 	}
diff -r 6bbd6af8c8a4 libgo/runtime/mgc0.c
--- a/libgo/runtime/mgc0.c	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/runtime/mgc0.c	Mon Jun 25 08:37:48 2012 -0700
@@ -1132,7 +1132,6 @@
 
 				f = &fb->fin[i];
 				params[0] = &f->arg;
-				runtime_setblockspecial(f->arg, false);
 				reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil);
 				f->fn = nil;
 				f->arg = nil;
diff -r 6bbd6af8c8a4 libgo/runtime/time.goc
--- a/libgo/runtime/time.goc	Wed Jun 13 22:02:47 2012 -0700
+++ b/libgo/runtime/time.goc	Mon Jun 25 08:37:48 2012 -0700
@@ -61,15 +61,21 @@
 void
 runtime_tsleep(int64 ns)
 {
+	G* g;
 	Timer t;
 
-	if(ns <= 0)
+	g = runtime_g();
+
+	if(ns <= 0) {
+		g->status = Grunning;
+		g->waitreason = nil;
 		return;
+	}
 
 	t.when = runtime_nanotime() + ns;
 	t.period = 0;
 	t.f = ready;
-	t.arg.__object = runtime_g();
+	t.arg.__object = g;
 	addtimer(&t);
 	runtime_gosched();
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]