mirror of
https://github.com/golang/go
synced 2024-11-12 02:50:25 -07:00
encoding/base32: don't panic when decoding "AAAA==".
Edit encoding/base64's internals and tests to match encoding/base32. Properly handling line breaks in padding is left for another CL. R=dsymonds CC=golang-dev https://golang.org/cl/7693044
This commit is contained in:
parent
1b3c969ac3
commit
79d06d7286
@ -236,7 +236,6 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
|
||||
var dbuf [8]byte
|
||||
dlen := 8
|
||||
|
||||
// do the top bytes contain any data?
|
||||
for j := 0; j < 8; {
|
||||
if len(src) == 0 {
|
||||
return n, false, CorruptInputError(len(osrc) - len(src) - j)
|
||||
@ -248,15 +247,26 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
|
||||
continue
|
||||
}
|
||||
if in == '=' && j >= 2 && len(src) < 8 {
|
||||
// We've reached the end and there's
|
||||
// padding, the rest should be padded
|
||||
for k := 0; k < 8-j-1; k++ {
|
||||
// We've reached the end and there's padding
|
||||
if len(src)+j < 8-1 {
|
||||
// not enough padding
|
||||
return n, false, CorruptInputError(len(osrc))
|
||||
}
|
||||
for k := 0; k < 8-1-j; k++ {
|
||||
if len(src) > k && src[k] != '=' {
|
||||
// incorrect padding
|
||||
return n, false, CorruptInputError(len(osrc) - len(src) + k - 1)
|
||||
}
|
||||
}
|
||||
dlen = j
|
||||
end = true
|
||||
dlen, end = j, true
|
||||
// 7, 5 and 2 are not valid padding lengths, and so 1, 3 and 6 are not
|
||||
// valid dlen values. See RFC 4648 Section 6 "Base 32 Encoding" listing
|
||||
// the five valid padding lengths, and Section 9 "Illustrations and
|
||||
// Examples" for an illustration for how the the 1st, 3rd and 6th base32
|
||||
// src bytes do not yield enough information to decode a dst byte.
|
||||
if dlen == 1 || dlen == 3 || dlen == 6 {
|
||||
return n, false, CorruptInputError(len(osrc) - len(src) - 1)
|
||||
}
|
||||
break
|
||||
}
|
||||
dbuf[j] = enc.decodeMap[in]
|
||||
@ -269,16 +279,16 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
|
||||
// Pack 8x 5-bit source blocks into 5 byte destination
|
||||
// quantum
|
||||
switch dlen {
|
||||
case 7, 8:
|
||||
case 8:
|
||||
dst[4] = dbuf[6]<<5 | dbuf[7]
|
||||
fallthrough
|
||||
case 6, 5:
|
||||
case 7:
|
||||
dst[3] = dbuf[4]<<7 | dbuf[5]<<2 | dbuf[6]>>3
|
||||
fallthrough
|
||||
case 4:
|
||||
case 5:
|
||||
dst[2] = dbuf[3]<<4 | dbuf[4]>>1
|
||||
fallthrough
|
||||
case 3:
|
||||
case 4:
|
||||
dst[1] = dbuf[1]<<6 | dbuf[2]<<1 | dbuf[3]>>4
|
||||
fallthrough
|
||||
case 2:
|
||||
@ -288,11 +298,11 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
|
||||
switch dlen {
|
||||
case 2:
|
||||
n += 1
|
||||
case 3, 4:
|
||||
case 4:
|
||||
n += 2
|
||||
case 5:
|
||||
n += 3
|
||||
case 6, 7:
|
||||
case 7:
|
||||
n += 4
|
||||
case 8:
|
||||
n += 5
|
||||
|
@ -137,27 +137,48 @@ func TestDecoderBuffering(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDecodeCorrupt(t *testing.T) {
|
||||
type corrupt struct {
|
||||
e string
|
||||
p int
|
||||
}
|
||||
examples := []corrupt{
|
||||
testCases := []struct {
|
||||
input string
|
||||
offset int // -1 means no corruption.
|
||||
}{
|
||||
{"", -1},
|
||||
{"!!!!", 0},
|
||||
{"x===", 0},
|
||||
{"AA=A====", 2},
|
||||
{"AAA=AAAA", 3},
|
||||
{"MMMMMMMMM", 8},
|
||||
{"MMMMMM", 0},
|
||||
{"A=", 1},
|
||||
{"AA=", 3},
|
||||
{"AA==", 4},
|
||||
{"AA===", 5},
|
||||
{"AAAA=", 5},
|
||||
{"AAAA==", 6},
|
||||
{"AAAAA=", 6},
|
||||
{"AAAAA==", 7},
|
||||
{"A=======", 1},
|
||||
{"AA======", -1},
|
||||
{"AAA=====", 3},
|
||||
{"AAAA====", -1},
|
||||
{"AAAAA===", -1},
|
||||
{"AAAAAA==", 6},
|
||||
{"AAAAAAA=", -1},
|
||||
{"AAAAAAAA", -1},
|
||||
}
|
||||
|
||||
for _, e := range examples {
|
||||
dbuf := make([]byte, StdEncoding.DecodedLen(len(e.e)))
|
||||
_, err := StdEncoding.Decode(dbuf, []byte(e.e))
|
||||
for _, tc := range testCases {
|
||||
dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input)))
|
||||
_, err := StdEncoding.Decode(dbuf, []byte(tc.input))
|
||||
if tc.offset == -1 {
|
||||
if err != nil {
|
||||
t.Error("Decoder wrongly detected coruption in", tc.input)
|
||||
}
|
||||
continue
|
||||
}
|
||||
switch err := err.(type) {
|
||||
case CorruptInputError:
|
||||
testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p)
|
||||
testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset)
|
||||
default:
|
||||
t.Error("Decoder failed to detect corruption in", e)
|
||||
t.Error("Decoder failed to detect corruption in", tc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,9 +227,8 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
|
||||
continue
|
||||
}
|
||||
if in == '=' && j >= 2 && len(src) < 4 {
|
||||
// We've reached the end and there's
|
||||
// padding
|
||||
if len(src) == 0 && j == 2 {
|
||||
// We've reached the end and there's padding
|
||||
if len(src)+j < 4-1 {
|
||||
// not enough padding
|
||||
return n, false, CorruptInputError(len(osrc))
|
||||
}
|
||||
@ -237,8 +236,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
|
||||
// incorrect padding
|
||||
return n, false, CorruptInputError(len(osrc) - len(src) - 1)
|
||||
}
|
||||
dlen = j
|
||||
end = true
|
||||
dlen, end = j, true
|
||||
break
|
||||
}
|
||||
dbuf[j] = enc.decodeMap[in]
|
||||
|
@ -142,11 +142,11 @@ func TestDecoderBuffering(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDecodeCorrupt(t *testing.T) {
|
||||
type corrupt struct {
|
||||
e string
|
||||
p int
|
||||
}
|
||||
examples := []corrupt{
|
||||
testCases := []struct {
|
||||
input string
|
||||
offset int // -1 means no corruption.
|
||||
}{
|
||||
{"", -1},
|
||||
{"!!!!", 0},
|
||||
{"x===", 1},
|
||||
{"AA=A", 2},
|
||||
@ -154,18 +154,27 @@ func TestDecodeCorrupt(t *testing.T) {
|
||||
{"AAAAA", 4},
|
||||
{"AAAAAA", 4},
|
||||
{"A=", 1},
|
||||
{"A==", 1},
|
||||
{"AA=", 3},
|
||||
{"AA==", -1},
|
||||
{"AAA=", -1},
|
||||
{"AAAA", -1},
|
||||
{"AAAAAA=", 7},
|
||||
}
|
||||
|
||||
for _, e := range examples {
|
||||
dbuf := make([]byte, StdEncoding.DecodedLen(len(e.e)))
|
||||
_, err := StdEncoding.Decode(dbuf, []byte(e.e))
|
||||
for _, tc := range testCases {
|
||||
dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input)))
|
||||
_, err := StdEncoding.Decode(dbuf, []byte(tc.input))
|
||||
if tc.offset == -1 {
|
||||
if err != nil {
|
||||
t.Error("Decoder wrongly detected coruption in", tc.input)
|
||||
}
|
||||
continue
|
||||
}
|
||||
switch err := err.(type) {
|
||||
case CorruptInputError:
|
||||
testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p)
|
||||
testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset)
|
||||
default:
|
||||
t.Error("Decoder failed to detect corruption in", e)
|
||||
t.Error("Decoder failed to detect corruption in", tc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user