brotli
brotli copied to clipboard
First reading empty compressed data doesnt return io.EOF
Description
The gzip package and strings.NewReader always return io.EOF when calling their Read methods with any size slice if the data is empty. However, the brotli Read method requires using a non-empty slice to read first for empty compressed data, and only subsequent reads can return io.EOF. If you continuously use an empty slice to read, io.EOF is never returned, potentially causing an infinite loop in certain scenarios.
Test
brotil first read never io.EOF for empty compressed data.
func TestBrotliReaderEmptyData(t *testing.T) {
readPLen := [][]int{{0, 1, 0, 2, 4}, {2, 3, 0, 4}}
for _, pLen := range readPLen {
tmp := pLen
t.Run("read p len order: "+fmt.Sprintf("%v", pLen), func(t *testing.T) {
buf := bytes.Buffer{}
w := brotli.NewWriterV2(&buf, 4)
err := w.Close()
if err != nil {
t.Fatal(err)
}
r := brotli.NewReader(&buf)
for _, l1 := range tmp {
p := make([]byte, l1)
n1, err1 := r.Read(p)
if n1 != 0 {
t.Fatalf("expected %d but got %d", 0, n1)
}
if err1 != io.EOF {
t.Fatal(err1)
}
}
})
}
}
Gzip success with any order.
func TestGzipReaderEmptyData(t *testing.T) {
readPLen := [][]int{{0, 1, 0, 2, 4}, {2, 3, 0, 4}}
for _, pLen := range readPLen {
tmp := pLen
t.Run("read p len order: "+fmt.Sprintf("%v", pLen), func(t *testing.T) {
buf := bytes.Buffer{}
w, _ := gzip.NewWriterLevel(&buf, 4)
err := w.Close()
if err != nil {
t.Fatal(err)
}
r, _ := gzip.NewReader(&buf)
for _, l1 := range tmp {
p := make([]byte, l1)
n1, err1 := r.Read(p)
if n1 != 0 {
t.Fatalf("expected %d but got %d", 0, n1)
}
if err1 != io.EOF {
t.Fatal(err1)
}
}
})
}
}
I think the current behavior makes about as much sense as is possible for a basically meaningless operation like reading 0 bytes.