diff --git a/fse/decompress.go b/fse/decompress.go index fde6cf4caf..413ec3b3cd 100644 --- a/fse/decompress.go +++ b/fse/decompress.go @@ -281,8 +281,12 @@ func (s *Scratch) decompress() error { tmp[off+2] = s1.nextFast() tmp[off+3] = s2.nextFast() off += 4 + // When off is 0, we have overflowed and should write. if off == 0 { s.Out = append(s.Out, tmp...) + if len(s.Out) >= s.DecompressLimit { + return fmt.Errorf("output size (%d) > DecompressLimit (%d)", len(s.Out), s.DecompressLimit) + } } } } else { @@ -296,7 +300,7 @@ func (s *Scratch) decompress() error { off += 4 if off == 0 { s.Out = append(s.Out, tmp...) - off = 0 + // When off is 0, we have overflowed and should write. if len(s.Out) >= s.DecompressLimit { return fmt.Errorf("output size (%d) > DecompressLimit (%d)", len(s.Out), s.DecompressLimit) } diff --git a/fse/fse_test.go b/fse/fse_test.go index a18292a4f5..9bcc088c2c 100644 --- a/fse/fse_test.go +++ b/fse/fse_test.go @@ -63,6 +63,7 @@ var decTestfiles = []struct { {name: "crash4", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash4.bin") }, err: "symbolLen (1) too small"}, {name: "crash5", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/crash5.bin") }, err: "symbolLen (1) too small"}, {name: "crash6", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/dec-crash6.bin") }, err: "newState (32768) outside table size (32768)"}, + {name: "something", fn: func() ([]byte, error) { return ioutil.ReadFile("../testdata/fse-artifact3.bin") }, err: "output size (1048576) > DecompressLimit (1048576)"}, } func TestCompress(t *testing.T) { @@ -107,6 +108,7 @@ func TestDecompress(t *testing.T) { for _, test := range decTestfiles { t.Run(test.name, func(t *testing.T) { var s Scratch + s.DecompressLimit = 1 << 20 buf0, err := test.fn() if err != nil { t.Fatal(err) diff --git a/testdata/fse-artifact3.bin b/testdata/fse-artifact3.bin new file mode 100644 index 0000000000..0607a9e74e Binary files /dev/null and b/testdata/fse-artifact3.bin differ