From a2770af447a470cf34841f09d0a5bf23a9b5ea9e Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 20 Mar 2014 16:00:34 +1100 Subject: [PATCH] base64: fix bug that decoder fails to detect corruption Encoding.Decode() failed to detect trailing garbages if input contains "==" followed by garbage smaller than 3 bytes (for example, it failed to detect "x" in "AA==x"). This patch fixes the bug and adds a few tests. LGTM=nigeltao R=golang-codereviews, bradfitz, nigeltao CC=golang-codereviews https://golang.org/cl/75340044 --- src/pkg/encoding/base64/base64.go | 27 ++++++++++++++++++-------- src/pkg/encoding/base64/base64_test.go | 6 +++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/pkg/encoding/base64/base64.go b/src/pkg/encoding/base64/base64.go index 0b07e733a0..a6efd44615 100644 --- a/src/pkg/encoding/base64/base64.go +++ b/src/pkg/encoding/base64/base64.go @@ -224,21 +224,33 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) { var dbuf [4]byte dlen := 4 - for j := 0; j < 4; { + for j := range dbuf { if len(src) == 0 { return n, false, CorruptInputError(olen - len(src) - j) } in := src[0] src = src[1:] - if in == '=' && j >= 2 && len(src) < 4 { + if in == '=' { // We've reached the end and there's padding - if len(src)+j < 4-1 { - // not enough padding - return n, false, CorruptInputError(olen) - } - if len(src) > 0 && src[0] != '=' { + switch j { + case 0, 1: // incorrect padding return n, false, CorruptInputError(olen - len(src) - 1) + case 2: + // "==" is expected, the first "=" is already consumed. + if len(src) == 0 { + // not enough padding + return n, false, CorruptInputError(olen) + } + if src[0] != '=' { + // incorrect padding + return n, false, CorruptInputError(olen - len(src) - 1) + } + src = src[1:] + } + if len(src) > 0 { + // trailing garbage + return n, false, CorruptInputError(olen - len(src)) } dlen, end = j, true break @@ -247,7 +259,6 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) { if dbuf[j] == 0xFF { return n, false, CorruptInputError(olen - len(src) - 1) } - j++ } // Pack 4x 6-bit source blocks into 3 byte destination diff --git a/src/pkg/encoding/base64/base64_test.go b/src/pkg/encoding/base64/base64_test.go index 6bcc724d9b..0285629029 100644 --- a/src/pkg/encoding/base64/base64_test.go +++ b/src/pkg/encoding/base64/base64_test.go @@ -149,9 +149,13 @@ func TestDecodeCorrupt(t *testing.T) { }{ {"", -1}, {"!!!!", 0}, + {"====", 0}, {"x===", 1}, + {"=AAA", 0}, + {"A=AA", 1}, {"AA=A", 2}, - {"AAA=AAAA", 3}, + {"AA==A", 4}, + {"AAA=AAAA", 4}, {"AAAAA", 4}, {"AAAAAA", 4}, {"A=", 1},