Skip to content

Commit

Permalink
lzma: fix handling of small dictionary sizes
Browse files Browse the repository at this point in the history
As Matt Dainty (@bodgit) reported there is an issue if the header of the
LZMA stream is less than the minimum dictionary size of 4096 byte. The
specification of the LZMA format says that in that case a dictionary
size of 4096 byte should be used, our code returns an error.

This commit changes the behavior and adds a simple test case to test for
the right behavior.

Fixes [#52](#52)
  • Loading branch information
ulikunitz committed Dec 12, 2022
1 parent 0b7c695 commit 4ce6f08
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lzma/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (c ReaderConfig) NewReader(lzma io.Reader) (r *Reader, err error) {
return nil, err
}
if r.h.dictCap < MinDictCap {
return nil, errors.New("lzma: dictionary capacity too small")
r.h.dictCap = MinDictCap
}
dictCap := r.h.dictCap
if c.DictCap > dictCap {
Expand Down
41 changes: 40 additions & 1 deletion lzma/reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ func TestReaderAll(t *testing.T) {
}
}

//
func Example_reader() {
f, err := os.Open("fox.lzma")
if err != nil {
Expand Down Expand Up @@ -310,3 +309,43 @@ func TestReaderErrAgain(t *testing.T) {
}
}
}

func TestMinDictSize(t *testing.T) {
const file = "examples/a.txt"
uncompressed, err := os.ReadFile(file)
if err != nil {
t.Fatalf("os.ReadFile(%q) error %s", file, err)
}
f := bytes.NewReader(uncompressed)

buf := new(bytes.Buffer)
cfg := WriterConfig{DictCap: 4096}
w, err := cfg.NewWriter(buf)
if err != nil {
t.Fatalf("WriterConfig(%+v).NewWriter(buf) error %s", cfg, err)
}
defer w.Close()
if _, err = io.Copy(w, f); err != nil {
t.Fatalf("io.Copy(w, f) error %s", err)
}
if err = w.Close(); err != nil {
t.Fatalf("w.Close() error %s", err)
}

compressed := buf.Bytes()
putUint32LE(compressed[1:5], 0)

z := bytes.NewReader(compressed)
r, err := NewReader(z)
if err != nil {
t.Fatalf("NewReader(z) error %s", err)
}
u, err := io.ReadAll(r)
if err != nil {
t.Fatalf("io.ReadAll(r) error %s", err)
}

if !bytes.Equal(u, uncompressed) {
t.Fatalf("got %q; want %q", u, uncompressed)
}
}

0 comments on commit 4ce6f08

Please sign in to comment.