diff options
author | Ian Lance Taylor <iant@golang.org> | 2017-09-14 17:11:35 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-09-14 17:11:35 +0000 |
commit | bc998d034f45d1828a8663b2eed928faf22a7d01 (patch) | |
tree | 8d262a22ca7318f4bcd64269fe8fe9e45bcf8d0f /libgo/go/encoding/base64 | |
parent | a41a6142df74219f596e612d3a7775f68ca6e96f (diff) | |
download | gcc-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.go | 62 | ||||
-rw-r--r-- | libgo/go/encoding/base64/base64_test.go | 40 |
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) + }) } } |