Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First reading empty compressed data doesnt return io.EOF #52

Open
newacorn opened this issue Jul 28, 2024 · 1 comment
Open

First reading empty compressed data doesnt return io.EOF #52

newacorn opened this issue Jul 28, 2024 · 1 comment

Comments

@newacorn
Copy link

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)
				}
			}
		})

	}
}
@andybalholm
Copy link
Owner

I think the current behavior makes about as much sense as is possible for a basically meaningless operation like reading 0 bytes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants