From 57434b509141a6ee9681116b8d552069126e615f Mon Sep 17 00:00:00 2001 From: Andy Balholm Date: Mon, 29 Jul 2024 09:56:04 -0700 Subject: [PATCH] Encoder: check for empty block Fixes #51 --- brotli_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ encoder.go | 9 +++++++++ go.mod | 2 ++ go.sum | 2 ++ 4 files changed, 57 insertions(+) diff --git a/brotli_test.go b/brotli_test.go index 5928a57..15b996e 100644 --- a/brotli_test.go +++ b/brotli_test.go @@ -14,10 +14,12 @@ import ( "math" "math/rand" "os" + "strconv" "testing" "time" "github.com/andybalholm/brotli/matchfinder" + "github.com/xyproto/randomstring" ) func checkCompressedData(compressedData, wantOriginalData []byte) error { @@ -740,3 +742,45 @@ func TestEncodeM0Lazy(t *testing.T) { func BenchmarkEncodeM0Lazy(b *testing.B) { benchmark(b, "testdata/Isaac.Newton-Opticks.txt", matchfinder.M0{Lazy: true}, 1<<16) } + +func TestIssue51(t *testing.T) { + for i := 65536; i <= 65536*4; i += 65536 { + t.Run("compress data length: "+strconv.Itoa(i)+"bytes", func(t *testing.T) { + dataStr := randomstring.HumanFriendlyString(i) + dataBytes := []byte(dataStr) + buf := bytes.Buffer{} + w := NewWriterV2(&buf, 4) + + n, err := w.Write(dataBytes) + if err != nil { + t.Fatalf("Error while compressing data: %v", err) + } + if n != len(dataBytes) { + t.Fatalf("Bytes written (%d) != len(databytes) (%d)", n, len(dataBytes)) + } + err = w.Close() + if err != nil { + t.Fatalf("Error closing writer: %v", err) + } + + r := NewReader(&buf) + dst := make([]byte, len(dataBytes)+100) + p := dst + total := 0 + for { + n1, err1 := r.Read(p) + if err1 != nil { + if err1 != io.EOF { + t.Fatal(err1) + } + break + } + total += n1 + p = p[n1:] + } + if !bytes.Equal(dst[:total], dataBytes) { + t.Fatal("Decompressed bytes don't match") + } + }) + } +} diff --git a/encoder.go b/encoder.go index 650d1e4..1928382 100644 --- a/encoder.go +++ b/encoder.go @@ -21,6 +21,15 @@ func (e *Encoder) Encode(dst []byte, src []byte, matches []matchfinder.Match, la e.wroteHeader = true } + if len(src) == 0 { + if lastBlock { + e.bw.writeBits(2, 3) // islast + isempty + e.bw.jumpToByteBoundary() + return e.bw.dst + } + return dst + } + var literalHisto [256]uint32 var commandHisto [704]uint32 var distanceHisto [64]uint32 diff --git a/go.mod b/go.mod index 50324ea..982814a 100644 --- a/go.mod +++ b/go.mod @@ -3,3 +3,5 @@ module github.com/andybalholm/brotli go 1.13 retract v1.0.1 // occasional panics and data corruption + +require github.com/xyproto/randomstring v1.0.5 // indirect diff --git a/go.sum b/go.sum index e69de29..505973d 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=