aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/encoding/base64
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2017-09-14 17:11:35 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2017-09-14 17:11:35 +0000
commitbc998d034f45d1828a8663b2eed928faf22a7d01 (patch)
tree8d262a22ca7318f4bcd64269fe8fe9e45bcf8d0f /libgo/go/encoding/base64
parenta41a6142df74219f596e612d3a7775f68ca6e96f (diff)
downloadgcc-bc998d034f45d1828a8663b2eed928faf22a7d01.zip
gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.tar.gz
gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.tar.bz2
libgo: update to go1.9
Reviewed-on: https://go-review.googlesource.com/63753 From-SVN: r252767
Diffstat (limited to 'libgo/go/encoding/base64')
-rw-r--r--libgo/go/encoding/base64/base64.go62
-rw-r--r--libgo/go/encoding/base64/base64_test.go40
2 files changed, 73 insertions, 29 deletions
diff --git a/libgo/go/encoding/base64/base64.go b/libgo/go/encoding/base64/base64.go
index d2efad4..b208f9e 100644
--- a/libgo/go/encoding/base64/base64.go
+++ b/libgo/go/encoding/base64/base64.go
@@ -35,13 +35,19 @@ const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678
const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
// NewEncoding returns a new padded Encoding defined by the given alphabet,
-// which must be a 64-byte string.
+// which must be a 64-byte string that does not contain the padding character
+// or CR / LF ('\r', '\n').
// The resulting Encoding uses the default padding character ('='),
// which may be changed or disabled via WithPadding.
func NewEncoding(encoder string) *Encoding {
if len(encoder) != 64 {
panic("encoding alphabet is not 64-bytes long")
}
+ for i := 0; i < len(encoder); i++ {
+ if encoder[i] == '\n' || encoder[i] == '\r' {
+ panic("encoding alphabet contains newline character")
+ }
+ }
e := new(Encoding)
e.padChar = StdPadding
@@ -58,7 +64,20 @@ func NewEncoding(encoder string) *Encoding {
// WithPadding creates a new encoding identical to enc except
// with a specified padding character, or NoPadding to disable padding.
+// The padding character must not be '\r' or '\n', must not
+// be contained in the encoding's alphabet and must be a rune equal or
+// below '\xff'.
func (enc Encoding) WithPadding(padding rune) *Encoding {
+ if padding == '\r' || padding == '\n' || padding > 0xff {
+ panic("invalid padding")
+ }
+
+ for i := 0; i < len(enc.encode); i++ {
+ if rune(enc.encode[i]) == padding {
+ panic("padding contained in alphabet")
+ }
+ }
+
enc.padChar = padding
return &enc
}
@@ -256,19 +275,17 @@ func (e CorruptInputError) Error() string {
func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
si := 0
- // skip over newlines
- for si < len(src) && (src[si] == '\n' || src[si] == '\r') {
- si++
- }
-
for si < len(src) && !end {
// Decode quantum using the base64 alphabet
var dbuf [4]byte
dinc, dlen := 3, 4
- for j := range dbuf {
+ for j := 0; j < len(dbuf); j++ {
if len(src) == si {
- if enc.padChar != NoPadding || j < 2 {
+ switch {
+ case j == 0:
+ return n, false, nil
+ case j == 1, enc.padChar != NoPadding:
return n, false, CorruptInputError(si - j)
}
dinc, dlen, end = j-1, j, true
@@ -277,11 +294,17 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
in := src[si]
si++
- // skip over newlines
- for si < len(src) && (src[si] == '\n' || src[si] == '\r') {
- si++
+
+ out := enc.decodeMap[in]
+ if out != 0xFF {
+ dbuf[j] = out
+ continue
}
+ if in == '\n' || in == '\r' {
+ j--
+ continue
+ }
if rune(in) == enc.padChar {
// We've reached the end and there's padding
switch j {
@@ -290,6 +313,10 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
return n, false, CorruptInputError(si - 1)
case 2:
// "==" is expected, the first "=" is already consumed.
+ // skip over newlines
+ for si < len(src) && (src[si] == '\n' || src[si] == '\r') {
+ si++
+ }
if si == len(src) {
// not enough padding
return n, false, CorruptInputError(len(src))
@@ -300,10 +327,10 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
}
si++
- // skip over newlines
- for si < len(src) && (src[si] == '\n' || src[si] == '\r') {
- si++
- }
+ }
+ // skip over newlines
+ for si < len(src) && (src[si] == '\n' || src[si] == '\r') {
+ si++
}
if si < len(src) {
// trailing garbage
@@ -312,10 +339,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
dinc, dlen, end = 3, j, true
break
}
- dbuf[j] = enc.decodeMap[in]
- if dbuf[j] == 0xFF {
- return n, false, CorruptInputError(si - 1)
- }
+ return n, false, CorruptInputError(si - 1)
}
// Convert 4x 6bit source bytes into 3 bytes
diff --git a/libgo/go/encoding/base64/base64_test.go b/libgo/go/encoding/base64/base64_test.go
index e2e1d59..05011fb 100644
--- a/libgo/go/encoding/base64/base64_test.go
+++ b/libgo/go/encoding/base64/base64_test.go
@@ -7,6 +7,7 @@ package base64
import (
"bytes"
"errors"
+ "fmt"
"io"
"io/ioutil"
"reflect"
@@ -63,7 +64,7 @@ func rawRef(ref string) string {
}
// Both URL and unpadding conversions
-func rawUrlRef(ref string) string {
+func rawURLRef(ref string) string {
return rawRef(urlRef(ref))
}
@@ -83,12 +84,12 @@ var encodingTests = []encodingTest{
{StdEncoding, stdRef},
{URLEncoding, urlRef},
{RawStdEncoding, rawRef},
- {RawURLEncoding, rawUrlRef},
+ {RawURLEncoding, rawURLRef},
{funnyEncoding, funnyRef},
{StdEncoding.Strict(), stdRef},
{URLEncoding.Strict(), urlRef},
{RawStdEncoding.Strict(), rawRef},
- {RawURLEncoding.Strict(), rawUrlRef},
+ {RawURLEncoding.Strict(), rawURLRef},
{funnyEncoding.Strict(), funnyRef},
}
@@ -98,6 +99,7 @@ var bigtest = testpair{
}
func testEqual(t *testing.T, msg string, args ...interface{}) bool {
+ t.Helper()
if args[len(args)-2] != args[len(args)-1] {
t.Errorf(msg, args...)
return false
@@ -187,11 +189,15 @@ func TestDecoderBuffering(t *testing.T) {
decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded))
buf := make([]byte, len(bigtest.decoded)+12)
var total int
- for total = 0; total < len(bigtest.decoded); {
- n, err := decoder.Read(buf[total : total+bs])
- testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, error(nil))
+ var n int
+ var err error
+ for total = 0; total < len(bigtest.decoded) && err == nil; {
+ n, err = decoder.Read(buf[total : total+bs])
total += n
}
+ if err != nil && err != io.EOF {
+ t.Errorf("Read from %q at pos %d = %d, unexpected error %v", bigtest.encoded, total, n, err)
+ }
testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
}
}
@@ -202,6 +208,9 @@ func TestDecodeCorrupt(t *testing.T) {
offset int // -1 means no corruption.
}{
{"", -1},
+ {"\n", -1},
+ {"AAA=\n", -1},
+ {"AAAA\n", -1},
{"!!!!", 0},
{"====", 0},
{"x===", 1},
@@ -220,6 +229,8 @@ func TestDecodeCorrupt(t *testing.T) {
{"AAAA", -1},
{"AAAAAA=", 7},
{"YWJjZA=====", 8},
+ {"A!\n", 1},
+ {"A=\n", 1},
}
for _, tc := range testCases {
dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input)))
@@ -466,10 +477,19 @@ func BenchmarkEncodeToString(b *testing.B) {
}
func BenchmarkDecodeString(b *testing.B) {
- data := StdEncoding.EncodeToString(make([]byte, 8192))
- b.SetBytes(int64(len(data)))
- for i := 0; i < b.N; i++ {
- StdEncoding.DecodeString(data)
+ sizes := []int{2, 4, 8, 64, 8192}
+ benchFunc := func(b *testing.B, benchSize int) {
+ data := StdEncoding.EncodeToString(make([]byte, benchSize))
+ b.SetBytes(int64(len(data)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ StdEncoding.DecodeString(data)
+ }
+ }
+ for _, size := range sizes {
+ b.Run(fmt.Sprintf("%d", size), func(b *testing.B) {
+ benchFunc(b, size)
+ })
}
}