aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/encoding/base64
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2019-09-06 18:12:46 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-09-06 18:12:46 +0000
commitaa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13 (patch)
tree7e63b06d1eec92beec6997c9d3ab47a5d6a835be /libgo/go/encoding/base64
parent920ea3b8ba3164b61ac9490dfdfceb6936eda6dd (diff)
downloadgcc-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.go123
-rw-r--r--libgo/go/encoding/base64/base64_test.go17
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