Merge pull request #2 from spi-ca/ISSUE-1
Issue 1 - fixes Short writes in strutil.LineBreaker
This commit is contained in:
commit
3363710364
|
@ -7,6 +7,7 @@ import (
|
|||
const pemLineLength = 64
|
||||
|
||||
// LineBreaker is an io.Writer that advances a newline if one line exceeds 64 bytes.
|
||||
// this source originally comes from the url(https://cs.opensource.google/go/go/+/refs/tags/go1.24.0:src/encoding/pem/pem.go;l=89)
|
||||
type LineBreaker struct {
|
||||
// Out os
|
||||
Out io.Writer
|
||||
|
@ -28,24 +29,32 @@ func (l *LineBreaker) Write(b []byte) (n int, err error) {
|
|||
return len(b), nil
|
||||
}
|
||||
|
||||
n, err = l.Out.Write(l.line[0:l.used])
|
||||
_, err = l.Out.Write(l.line[0:l.used:l.used])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
excess := pemLineLength - l.used
|
||||
l.used = 0
|
||||
brk := pemLineLength - l.used
|
||||
|
||||
n, err = l.Out.Write(b[0:excess])
|
||||
if err != nil {
|
||||
return
|
||||
var nn int
|
||||
for len(b) >= brk {
|
||||
nn, err = l.Out.Write(b[0:brk:brk])
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = l.Out.Write(nl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
b = b[brk:]
|
||||
brk = pemLineLength
|
||||
}
|
||||
|
||||
n, err = l.Out.Write(nl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return l.Out.Write(b[excess:])
|
||||
l.used = len(b)
|
||||
copy(l.line[:], b)
|
||||
n += len(b)
|
||||
return
|
||||
}
|
||||
|
||||
// Close flushes any pending output from the writer.
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package strutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type lineBreakerTest struct {
|
||||
in, out string
|
||||
}
|
||||
|
||||
const sixtyFourCharString = "0123456789012345678901234567890123456789012345678901234567890123"
|
||||
|
||||
var lineBreakerTests = []lineBreakerTest{
|
||||
{"", ""},
|
||||
{"a", "a\n"},
|
||||
{"ab", "ab\n"},
|
||||
{sixtyFourCharString, sixtyFourCharString + "\n"},
|
||||
{sixtyFourCharString + "X", sixtyFourCharString + "\nX\n"},
|
||||
{sixtyFourCharString + sixtyFourCharString, sixtyFourCharString + "\n" + sixtyFourCharString + "\n"},
|
||||
}
|
||||
|
||||
func TestLineBreaker(t *testing.T) {
|
||||
for i, test := range lineBreakerTests {
|
||||
buf := new(strings.Builder)
|
||||
var breaker LineBreaker
|
||||
breaker.Out = buf
|
||||
_, err := breaker.Write([]byte(test.in))
|
||||
if err != nil {
|
||||
t.Errorf("#%d: error from Write: %s", i, err)
|
||||
continue
|
||||
}
|
||||
err = breaker.Close()
|
||||
if err != nil {
|
||||
t.Errorf("#%d: error from Close: %s", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if got := buf.String(); got != test.out {
|
||||
t.Errorf("#%d: got:%s want:%s", i, got, test.out)
|
||||
}
|
||||
}
|
||||
|
||||
for i, test := range lineBreakerTests {
|
||||
buf := new(strings.Builder)
|
||||
var breaker LineBreaker
|
||||
breaker.Out = buf
|
||||
|
||||
for i := 0; i < len(test.in); i++ {
|
||||
_, err := breaker.Write([]byte(test.in[i : i+1]))
|
||||
if err != nil {
|
||||
t.Errorf("#%d: error from Write (byte by byte): %s", i, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
err := breaker.Close()
|
||||
if err != nil {
|
||||
t.Errorf("#%d: error from Close (byte by byte): %s", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if got := buf.String(); got != test.out {
|
||||
t.Errorf("#%d: (byte by byte) got:%s want:%s", i, got, test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func FuzzLineBreaker(f *testing.F) {
|
||||
for _, test := range lineBreakerTests {
|
||||
f.Add(test.in, len(test.in))
|
||||
f.Add(test.in, 1)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, in string, chunkSize int) {
|
||||
if chunkSize <= 0 || chunkSize > len(in)+1 {
|
||||
return
|
||||
}
|
||||
var out strings.Builder
|
||||
var l LineBreaker
|
||||
l.Out = &out
|
||||
chunk := make([]byte, chunkSize)
|
||||
n, err := io.CopyBuffer(&l, strings.NewReader(in), chunk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != int64(len(in)) {
|
||||
t.Errorf("invalid written count: got %d, expected %d", n, len(in))
|
||||
}
|
||||
l.Close()
|
||||
if len(in) > 0 && out.Len() != len(in)+1+(len(in)-1)/pemLineLength {
|
||||
t.Fatalf("invalid final size: got %d, expected %d", out.Len(), len(in)+1+(len(in)-1)/pemLineLength)
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue