]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/base32: handle NoPadding in NewDecoder
authorGustav Westling <zegl@westling.xyz>
Wed, 16 May 2018 16:35:58 +0000 (16:35 +0000)
committerIan Lance Taylor <iant@golang.org>
Wed, 16 May 2018 21:15:03 +0000 (21:15 +0000)
This change adds functionality to properly handle NoPadding in NewDecoder.

Removes the following expectations when using NoPadding:

* the input message length is a multiple of 8
* the input message length is 0, or longer than 7 characters

Fixes #25332

Change-Id: I7c38160df23f7e8da4f85a5629530016e7bf71f3
GitHub-Last-Rev: 68ab8d2291df5c69e647620f8ef82cc90e06db28
GitHub-Pull-Request: golang/go#25394
Reviewed-on: https://go-review.googlesource.com/113215
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/encoding/base32/base32.go
src/encoding/base32/base32_test.go

index 09e90eab5fff35ba1c6b36e132cbcf4f7a7d4d9e..fdf42e5df395f37d6e78ebf1fd4dfdb064e9b4cd 100644 (file)
@@ -404,7 +404,7 @@ type decoder struct {
        outbuf [1024 / 8 * 5]byte
 }
 
-func readEncodedData(r io.Reader, buf []byte, min int) (n int, err error) {
+func readEncodedData(r io.Reader, buf []byte, min int, expectsPadding bool) (n int, err error) {
        for n < min && err == nil {
                var nn int
                nn, err = r.Read(buf[n:])
@@ -415,7 +415,9 @@ func readEncodedData(r io.Reader, buf []byte, min int) (n int, err error) {
                err = io.ErrUnexpectedEOF
        }
        // no data was read, the buffer already contains some data
-       if min < 8 && n == 0 && err == io.EOF {
+       // when padding is disabled this is not an error, as the message can be of
+       // any length
+       if expectsPadding && min < 8 && n == 0 && err == io.EOF {
                err = io.ErrUnexpectedEOF
        }
        return
@@ -445,15 +447,32 @@ func (d *decoder) Read(p []byte) (n int, err error) {
                nn = len(d.buf)
        }
 
-       nn, d.err = readEncodedData(d.r, d.buf[d.nbuf:nn], 8-d.nbuf)
+       // Minimum amount of bytes that needs to be read each cycle
+       var min int
+       var expectsPadding bool
+       if d.enc.padChar == NoPadding {
+               min = 1
+               expectsPadding = false
+       } else {
+               min = 8 - d.nbuf
+               expectsPadding = true
+       }
+
+       nn, d.err = readEncodedData(d.r, d.buf[d.nbuf:nn], min, expectsPadding)
        d.nbuf += nn
-       if d.nbuf < 8 {
+       if d.nbuf < min {
                return 0, d.err
        }
 
        // Decode chunk into p, or d.out and then p if p is too small.
-       nr := d.nbuf / 8 * 8
-       nw := d.nbuf / 8 * 5
+       var nr int
+       if d.enc.padChar == NoPadding {
+               nr = d.nbuf
+       } else {
+               nr = d.nbuf / 8 * 8
+       }
+       nw := d.enc.DecodedLen(d.nbuf)
+
        if nw > len(p) {
                nw, d.end, err = d.enc.decode(d.outbuf[0:], d.buf[0:nr])
                d.out = d.outbuf[0:nw]
index fdd862dc499a49d20f14fe55e64fbeba70b952da..c5506ed4de70d40ae463a85a66f8866ef54e2fa0 100644 (file)
@@ -686,3 +686,66 @@ func TestWithoutPaddingClose(t *testing.T) {
                }
        }
 }
+
+func TestDecodeReadAll(t *testing.T) {
+       encodings := []*Encoding{
+               StdEncoding,
+               StdEncoding.WithPadding(NoPadding),
+       }
+
+       for _, pair := range pairs {
+               for encIndex, encoding := range encodings {
+                       encoded := pair.encoded
+                       if encoding.padChar == NoPadding {
+                               encoded = strings.Replace(encoded, "=", "", -1)
+                       }
+
+                       decReader, err := ioutil.ReadAll(NewDecoder(encoding, strings.NewReader(encoded)))
+                       if err != nil {
+                               t.Errorf("NewDecoder error: %v", err)
+                       }
+
+                       if pair.decoded != string(decReader) {
+                               t.Errorf("Expected %s got %s; Encoding %d", pair.decoded, decReader, encIndex)
+                       }
+               }
+       }
+}
+
+func TestDecodeSmallBuffer(t *testing.T) {
+       encodings := []*Encoding{
+               StdEncoding,
+               StdEncoding.WithPadding(NoPadding),
+       }
+
+       for bufferSize := 1; bufferSize < 200; bufferSize++ {
+               for _, pair := range pairs {
+                       for encIndex, encoding := range encodings {
+                               encoded := pair.encoded
+                               if encoding.padChar == NoPadding {
+                                       encoded = strings.Replace(encoded, "=", "", -1)
+                               }
+
+                               decoder := NewDecoder(encoding, strings.NewReader(encoded))
+
+                               var allRead []byte
+
+                               for {
+                                       buf := make([]byte, bufferSize)
+                                       n, err := decoder.Read(buf)
+                                       allRead = append(allRead, buf[0:n]...)
+                                       if err == io.EOF {
+                                               break
+                                       }
+                                       if err != nil {
+                                               t.Error(err)
+                                       }
+                               }
+
+                               if pair.decoded != string(allRead) {
+                                       t.Errorf("Expected %s got %s; Encoding %d; bufferSize %d", pair.decoded, allRead, encIndex, bufferSize)
+                               }
+                       }
+               }
+       }
+}