Skip to content

Commit a3c1836

Browse files
chanxuehonggopherbot
authored andcommitted
encoding/base32: reduce overflow risk when calc encode/decode len
Same as https://go-review.googlesource.com/c/go/+/510635, reduces risk of overflow Change-Id: I18f5560d73af76c3e853464a89ad7e42dbbd5894 GitHub-Last-Rev: 652c8c6 GitHub-Pull-Request: #61547 Reviewed-on: https://go-review.googlesource.com/c/go/+/512200 Auto-Submit: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]>
1 parent 6161935 commit a3c1836

File tree

2 files changed

+83
-48
lines changed

2 files changed

+83
-48
lines changed

src/encoding/base32/base32.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
271271
// of an input buffer of length n.
272272
func (enc *Encoding) EncodedLen(n int) int {
273273
if enc.padChar == NoPadding {
274-
return (n*8 + 4) / 5
274+
return n/5*8 + (n%5*8+4)/5
275275
}
276276
return (n + 4) / 5 * 8
277277
}
@@ -545,8 +545,7 @@ func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
545545
// corresponding to n bytes of base32-encoded data.
546546
func (enc *Encoding) DecodedLen(n int) int {
547547
if enc.padChar == NoPadding {
548-
return n * 5 / 8
548+
return n/8*5 + n%8*5/8
549549
}
550-
551550
return n / 8 * 5
552551
}

src/encoding/base32/base32_test.go

Lines changed: 81 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"bytes"
99
"errors"
1010
"io"
11+
"math"
12+
"strconv"
1113
"strings"
1214
"testing"
1315
)
@@ -679,52 +681,86 @@ func TestBufferedDecodingPadding(t *testing.T) {
679681
}
680682
}
681683

682-
func TestEncodedDecodedLen(t *testing.T) {
684+
func TestEncodedLen(t *testing.T) {
685+
var rawStdEncoding = StdEncoding.WithPadding(NoPadding)
683686
type test struct {
684-
in int
685-
wantEnc int
686-
wantDec int
687-
}
688-
data := bytes.Repeat([]byte("x"), 100)
689-
for _, test := range []struct {
690-
name string
691-
enc *Encoding
692-
cases []test
693-
}{
694-
{"StdEncoding", StdEncoding, []test{
695-
{0, 0, 0},
696-
{1, 8, 5},
697-
{5, 8, 5},
698-
{6, 16, 10},
699-
{10, 16, 10},
700-
}},
701-
{"NoPadding", StdEncoding.WithPadding(NoPadding), []test{
702-
{0, 0, 0},
703-
{1, 2, 1},
704-
{2, 4, 2},
705-
{5, 8, 5},
706-
{6, 10, 6},
707-
{7, 12, 7},
708-
{10, 16, 10},
709-
{11, 18, 11},
710-
}},
711-
} {
712-
t.Run(test.name, func(t *testing.T) {
713-
for _, tc := range test.cases {
714-
encLen := test.enc.EncodedLen(tc.in)
715-
decLen := test.enc.DecodedLen(encLen)
716-
enc := test.enc.EncodeToString(data[:tc.in])
717-
if len(enc) != encLen {
718-
t.Fatalf("EncodedLen(%d) = %d but encoded to %q (%d)", tc.in, encLen, enc, len(enc))
719-
}
720-
if encLen != tc.wantEnc {
721-
t.Fatalf("EncodedLen(%d) = %d; want %d", tc.in, encLen, tc.wantEnc)
722-
}
723-
if decLen != tc.wantDec {
724-
t.Fatalf("DecodedLen(%d) = %d; want %d", encLen, decLen, tc.wantDec)
725-
}
726-
}
727-
})
687+
enc *Encoding
688+
n int
689+
want int64
690+
}
691+
tests := []test{
692+
{StdEncoding, 0, 0},
693+
{StdEncoding, 1, 8},
694+
{StdEncoding, 2, 8},
695+
{StdEncoding, 3, 8},
696+
{StdEncoding, 4, 8},
697+
{StdEncoding, 5, 8},
698+
{StdEncoding, 6, 16},
699+
{StdEncoding, 10, 16},
700+
{StdEncoding, 11, 24},
701+
{rawStdEncoding, 0, 0},
702+
{rawStdEncoding, 1, 2},
703+
{rawStdEncoding, 2, 4},
704+
{rawStdEncoding, 3, 5},
705+
{rawStdEncoding, 4, 7},
706+
{rawStdEncoding, 5, 8},
707+
{rawStdEncoding, 6, 10},
708+
{rawStdEncoding, 7, 12},
709+
{rawStdEncoding, 10, 16},
710+
{rawStdEncoding, 11, 18},
711+
}
712+
// check overflow
713+
switch strconv.IntSize {
714+
case 32:
715+
tests = append(tests, test{rawStdEncoding, (math.MaxInt-4)/8 + 1, 429496730})
716+
tests = append(tests, test{rawStdEncoding, math.MaxInt/8*5 + 4, math.MaxInt})
717+
case 64:
718+
tests = append(tests, test{rawStdEncoding, (math.MaxInt-4)/8 + 1, 1844674407370955162})
719+
tests = append(tests, test{rawStdEncoding, math.MaxInt/8*5 + 4, math.MaxInt})
720+
}
721+
for _, tt := range tests {
722+
if got := tt.enc.EncodedLen(tt.n); int64(got) != tt.want {
723+
t.Errorf("EncodedLen(%d): got %d, want %d", tt.n, got, tt.want)
724+
}
725+
}
726+
}
727+
728+
func TestDecodedLen(t *testing.T) {
729+
var rawStdEncoding = StdEncoding.WithPadding(NoPadding)
730+
type test struct {
731+
enc *Encoding
732+
n int
733+
want int64
734+
}
735+
tests := []test{
736+
{StdEncoding, 0, 0},
737+
{StdEncoding, 8, 5},
738+
{StdEncoding, 16, 10},
739+
{StdEncoding, 24, 15},
740+
{rawStdEncoding, 0, 0},
741+
{rawStdEncoding, 2, 1},
742+
{rawStdEncoding, 4, 2},
743+
{rawStdEncoding, 5, 3},
744+
{rawStdEncoding, 7, 4},
745+
{rawStdEncoding, 8, 5},
746+
{rawStdEncoding, 10, 6},
747+
{rawStdEncoding, 12, 7},
748+
{rawStdEncoding, 16, 10},
749+
{rawStdEncoding, 18, 11},
750+
}
751+
// check overflow
752+
switch strconv.IntSize {
753+
case 32:
754+
tests = append(tests, test{rawStdEncoding, math.MaxInt/5 + 1, 268435456})
755+
tests = append(tests, test{rawStdEncoding, math.MaxInt, 1342177279})
756+
case 64:
757+
tests = append(tests, test{rawStdEncoding, math.MaxInt/5 + 1, 1152921504606846976})
758+
tests = append(tests, test{rawStdEncoding, math.MaxInt, 5764607523034234879})
759+
}
760+
for _, tt := range tests {
761+
if got := tt.enc.DecodedLen(tt.n); int64(got) != tt.want {
762+
t.Errorf("DecodedLen(%d): got %d, want %d", tt.n, got, tt.want)
763+
}
728764
}
729765
}
730766

0 commit comments

Comments
 (0)