]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/base32: don't panic when decoding "AAAA==".
authorNigel Tao <nigeltao@golang.org>
Tue, 12 Mar 2013 00:07:36 +0000 (11:07 +1100)
committerNigel Tao <nigeltao@golang.org>
Tue, 12 Mar 2013 00:07:36 +0000 (11:07 +1100)
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

src/pkg/encoding/base32/base32.go
src/pkg/encoding/base32/base32_test.go
src/pkg/encoding/base64/base64.go
src/pkg/encoding/base64/base64_test.go

index dbefc48fa37eef5a658b9aa17a20f51a5fbdee87..738a960d7f2baac4db4f36238865116304490ced 100644 (file)
@@ -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
index 98365e18cfc9f28927e911444b1b0eb4fc75bb60..b62bfeebf62738c55566e28b86f0f2d1654c0afd 100644 (file)
@@ -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},
-       }
-
-       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)
                }
        }
 }
index e66672a1c93e972d8c6a00589434f4782852f0bb..8ccd9127e11ce269021073f31668fe822c796774 100644 (file)
@@ -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]
index 2166abd7ac85adb07b066c5326e11169db1c6862..71c2bfce7f3aedd0ff9eb829f70d9bb451365771 100644 (file)
@@ -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)
                }
        }
 }