diff options
author | Ian Lance Taylor <iant@golang.org> | 2019-09-06 18:12:46 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-09-06 18:12:46 +0000 |
commit | aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13 (patch) | |
tree | 7e63b06d1eec92beec6997c9d3ab47a5d6a835be /libgo/go/encoding/base64 | |
parent | 920ea3b8ba3164b61ac9490dfdfceb6936eda6dd (diff) | |
download | gcc-aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13.zip gcc-aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13.tar.gz gcc-aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13.tar.bz2 |
libgo: update to Go 1.13beta1 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/193497
From-SVN: r275473
Diffstat (limited to 'libgo/go/encoding/base64')
-rw-r--r-- | libgo/go/encoding/base64/base64.go | 123 | ||||
-rw-r--r-- | libgo/go/encoding/base64/base64_test.go | 17 |
2 files changed, 75 insertions, 65 deletions
diff --git a/libgo/go/encoding/base64/base64.go b/libgo/go/encoding/base64/base64.go index 0bb37b3..0822101 100644 --- a/libgo/go/encoding/base64/base64.go +++ b/libgo/go/encoding/base64/base64.go @@ -123,6 +123,10 @@ func (enc *Encoding) Encode(dst, src []byte) { if len(src) == 0 { return } + // enc is a pointer receiver, so the use of enc.encode within the hot + // loop below means a nil check at every operation. Lift that nil check + // outside of the loop to speed up the encoder. + _ = enc.encode di, si := 0, 0 n := (len(src) / 3) * 3 @@ -278,7 +282,10 @@ func (e CorruptInputError) Error() string { func (enc *Encoding) decodeQuantum(dst, src []byte, si int) (nsi, n int, err error) { // Decode quantum using the base64 alphabet var dbuf [4]byte - dinc, dlen := 3, 4 + dlen := 4 + + // Lift the nil check outside of the loop. + _ = enc.decodeMap for j := 0; j < len(dbuf); j++ { if len(src) == si { @@ -288,7 +295,7 @@ func (enc *Encoding) decodeQuantum(dst, src []byte, si int) (nsi, n int, err err case j == 1, enc.padChar != NoPadding: return si, 0, CorruptInputError(si - j) } - dinc, dlen = j-1, j + dlen = j break } in := src[si] @@ -340,7 +347,7 @@ func (enc *Encoding) decodeQuantum(dst, src []byte, si int) (nsi, n int, err err // trailing garbage err = CorruptInputError(si) } - dinc, dlen = 3, j + dlen = j break } @@ -365,7 +372,6 @@ func (enc *Encoding) decodeQuantum(dst, src []byte, si int) (nsi, n int, err err return si, 0, CorruptInputError(si - 2) } } - dst = dst[dinc:] return si, dlen - 1, err } @@ -464,9 +470,23 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { return 0, nil } + // Lift the nil check outside of the loop. enc.decodeMap is directly + // used later in this function, to let the compiler know that the + // receiver can't be nil. + _ = enc.decodeMap + si := 0 for strconv.IntSize >= 64 && len(src)-si >= 8 && len(dst)-n >= 8 { - if dn, ok := enc.decode64(src[si:]); ok { + if dn, ok := assemble64( + enc.decodeMap[src[si+0]], + enc.decodeMap[src[si+1]], + enc.decodeMap[src[si+2]], + enc.decodeMap[src[si+3]], + enc.decodeMap[src[si+4]], + enc.decodeMap[src[si+5]], + enc.decodeMap[src[si+6]], + enc.decodeMap[src[si+7]], + ); ok { binary.BigEndian.PutUint64(dst[n:], dn) n += 6 si += 8 @@ -481,7 +501,12 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { } for len(src)-si >= 4 && len(dst)-n >= 4 { - if dn, ok := enc.decode32(src[si:]); ok { + if dn, ok := assemble32( + enc.decodeMap[src[si+0]], + enc.decodeMap[src[si+1]], + enc.decodeMap[src[si+2]], + enc.decodeMap[src[si+3]], + ); ok { binary.BigEndian.PutUint32(dst[n:], dn) n += 3 si += 4 @@ -506,70 +531,40 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { return n, err } -// decode32 tries to decode 4 base64 characters into 3 bytes, and returns those -// bytes. len(src) must be >= 4. -// Returns (0, false) if decoding failed. -func (enc *Encoding) decode32(src []byte) (dn uint32, ok bool) { - var n uint32 - _ = src[3] - if n = uint32(enc.decodeMap[src[0]]); n == 0xff { - return 0, false - } - dn |= n << 26 - if n = uint32(enc.decodeMap[src[1]]); n == 0xff { - return 0, false - } - dn |= n << 20 - if n = uint32(enc.decodeMap[src[2]]); n == 0xff { +// assemble32 assembles 4 base64 digits into 3 bytes. +// Each digit comes from the decode map, and will be 0xff +// if it came from an invalid character. +func assemble32(n1, n2, n3, n4 byte) (dn uint32, ok bool) { + // Check that all the digits are valid. If any of them was 0xff, their + // bitwise OR will be 0xff. + if n1|n2|n3|n4 == 0xff { return 0, false } - dn |= n << 14 - if n = uint32(enc.decodeMap[src[3]]); n == 0xff { - return 0, false - } - dn |= n << 8 - return dn, true + return uint32(n1)<<26 | + uint32(n2)<<20 | + uint32(n3)<<14 | + uint32(n4)<<8, + true } -// decode64 tries to decode 8 base64 characters into 6 bytes, and returns those -// bytes. len(src) must be >= 8. -// Returns (0, false) if decoding failed. -func (enc *Encoding) decode64(src []byte) (dn uint64, ok bool) { - var n uint64 - _ = src[7] - if n = uint64(enc.decodeMap[src[0]]); n == 0xff { - return 0, false - } - dn |= n << 58 - if n = uint64(enc.decodeMap[src[1]]); n == 0xff { - return 0, false - } - dn |= n << 52 - if n = uint64(enc.decodeMap[src[2]]); n == 0xff { - return 0, false - } - dn |= n << 46 - if n = uint64(enc.decodeMap[src[3]]); n == 0xff { - return 0, false - } - dn |= n << 40 - if n = uint64(enc.decodeMap[src[4]]); n == 0xff { - return 0, false - } - dn |= n << 34 - if n = uint64(enc.decodeMap[src[5]]); n == 0xff { - return 0, false - } - dn |= n << 28 - if n = uint64(enc.decodeMap[src[6]]); n == 0xff { - return 0, false - } - dn |= n << 22 - if n = uint64(enc.decodeMap[src[7]]); n == 0xff { +// assemble64 assembles 8 base64 digits into 6 bytes. +// Each digit comes from the decode map, and will be 0xff +// if it came from an invalid character. +func assemble64(n1, n2, n3, n4, n5, n6, n7, n8 byte) (dn uint64, ok bool) { + // Check that all the digits are valid. If any of them was 0xff, their + // bitwise OR will be 0xff. + if n1|n2|n3|n4|n5|n6|n7|n8 == 0xff { return 0, false } - dn |= n << 16 - return dn, true + return uint64(n1)<<58 | + uint64(n2)<<52 | + uint64(n3)<<46 | + uint64(n4)<<40 | + uint64(n5)<<34 | + uint64(n6)<<28 | + uint64(n7)<<22 | + uint64(n8)<<16, + true } type newlineFilteringReader struct { diff --git a/libgo/go/encoding/base64/base64_test.go b/libgo/go/encoding/base64/base64_test.go index f7f312c..bc67036 100644 --- a/libgo/go/encoding/base64/base64_test.go +++ b/libgo/go/encoding/base64/base64_test.go @@ -11,6 +11,7 @@ import ( "io" "io/ioutil" "reflect" + "runtime/debug" "strings" "testing" "time" @@ -175,7 +176,7 @@ func TestDecoder(t *testing.T) { testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded)) testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded) if err != io.EOF { - count, err = decoder.Read(dbuf) + _, err = decoder.Read(dbuf) } testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF) } @@ -247,6 +248,20 @@ func TestDecodeCorrupt(t *testing.T) { } } +func TestDecodeBounds(t *testing.T) { + var buf [32]byte + s := StdEncoding.EncodeToString(buf[:]) + defer func() { + if err := recover(); err != nil { + t.Fatalf("Decode panicked unexpectedly: %v\n%s", err, debug.Stack()) + } + }() + n, err := StdEncoding.Decode(buf[:], []byte(s)) + if n != len(buf) || err != nil { + t.Fatalf("StdEncoding.Decode = %d, %v, want %d, nil", n, err, len(buf)) + } +} + func TestEncodedLen(t *testing.T) { for _, tt := range []struct { enc *Encoding |