Skip to content

Multiple Calls to zstd.(*Encoder).Close() Write Duplicate CRC Checksums #1016

@Fusl

Description

@Fusl

When invoking .Close() multiple times on a zstd.(*Encoder) instance, the CRC checksum is written to the underlying stream multiple times. This behavior prevents reliable use of defer zstdWr.Close() in conjunction with an explicit zstdWr.Close() mid-function, as it results in duplicate checksum entries.

Other io.WriteCloser implementations, such as Go's standard library gzip.(*Writer).Close(), prevent this issue by setting a closed flag internally, ensuring the Close() method is idempotent.

Steps to Reproduce:

package main

import (
	"bytes"
	"crypto/rand"
	"github.com/klauspost/compress/zstd"
)

func main() {
	buf := bytes.NewBuffer(nil)
	encoder, _ := zstd.NewWriter(buf)
	b := make([]byte, 131072)
	rand.Read(b)
	encoder.Write(b)
	encoder.Close()  // First close
	encoder.Close()  // Second close (shouldn't write checksum again)
	b = buf.Bytes()

	// Compare the last two 4-byte sequences in the buffer (which are the checksums)
	c1 := b[len(b)-4:]
	c2 := b[len(b)-8 : len(b)-4]
	if string(c1) == string(c2) {
		panic("Duplicate CRC checksums written")
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions