From bdd7495551ff324c3d417cc2358d6b040d4c2ea8 Mon Sep 17 00:00:00 2001 From: Sangbum Kim Date: Tue, 4 Mar 2025 21:36:59 +0900 Subject: [PATCH 1/2] applied fix from See https://go-review.googlesource.com/c/go/+/653675. --- strutil/chunk.go | 9 ++-- strutil/chunk_test.go | 95 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 strutil/chunk_test.go diff --git a/strutil/chunk.go b/strutil/chunk.go index 4b67921..1407e97 100644 --- a/strutil/chunk.go +++ b/strutil/chunk.go @@ -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,7 +29,7 @@ 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]) if err != nil { return } @@ -40,12 +41,14 @@ func (l *LineBreaker) Write(b []byte) (n int, err error) { return } - n, err = l.Out.Write(nl) + _, err = l.Out.Write(nl) if err != nil { return } - return l.Out.Write(b[excess:]) + var nn int + nn, err = l.Write(b[excess:]) + return n + nn, err } // Close flushes any pending output from the writer. diff --git a/strutil/chunk_test.go b/strutil/chunk_test.go new file mode 100644 index 0000000..4c067ef --- /dev/null +++ b/strutil/chunk_test.go @@ -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) + } + }) +} From 36fe8dfa7f2010bde99f2dbcc035e3b6a7ef7bf4 Mon Sep 17 00:00:00 2001 From: Sangbum Kim Date: Tue, 4 Mar 2025 21:38:19 +0900 Subject: [PATCH 2/2] applied fix from See https://go-review.googlesource.com/c/go/+/653676. --- strutil/chunk.go | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/strutil/chunk.go b/strutil/chunk.go index 1407e97..b885616 100644 --- a/strutil/chunk.go +++ b/strutil/chunk.go @@ -29,26 +29,32 @@ func (l *LineBreaker) Write(b []byte) (n int, err error) { return len(b), nil } - _, err = l.Out.Write(l.line[0:l.used]) - if err != nil { - return - } - excess := pemLineLength - l.used - l.used = 0 - - n, err = l.Out.Write(b[0:excess]) - if err != nil { - return - } - - _, err = l.Out.Write(nl) + _, err = l.Out.Write(l.line[0:l.used:l.used]) if err != nil { return } + brk := pemLineLength - l.used var nn int - nn, err = l.Write(b[excess:]) - return n + nn, err + 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 + } + + l.used = len(b) + copy(l.line[:], b) + n += len(b) + return } // Close flushes any pending output from the writer.