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)
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]
// 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:
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
}
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},
- }
-
- for _, e := range examples {
- dbuf := make([]byte, StdEncoding.DecodedLen(len(e.e)))
- _, err := StdEncoding.Decode(dbuf, []byte(e.e))
+ {"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 _, 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)
}
}
}
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))
}
// 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]
}
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},
{"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)
}
}
}