Browse Source

DecodeBlock: handle case in shortcut2 where the destination buffer is shorter than 18 bytes. Fixes #51.

Pierre Curto 6 years ago
parent
commit
bf524fc723
3 changed files with 34 additions and 2 deletions
  1. 8 2
      decode_other.go
  2. BIN
      testdata/issue51.data
  3. 26 0
      writer_test.go

+ 8 - 2
decode_other.go

@@ -19,7 +19,7 @@ func decodeBlock(dst, src []byte) (ret int) {
 		// Literals.
 		// Literals.
 		if lLen := b >> 4; lLen > 0 {
 		if lLen := b >> 4; lLen > 0 {
 			switch {
 			switch {
-			case lLen < 0xF && di+18 < len(dst) && si+16 < len(src):
+			case lLen < 0xF && si+16 < len(src):
 				// Shortcut 1
 				// Shortcut 1
 				// if we have enough room in src and dst, and the literals length
 				// if we have enough room in src and dst, and the literals length
 				// is small enough (0..14) then copy all 16 bytes, even if not all
 				// is small enough (0..14) then copy all 16 bytes, even if not all
@@ -34,7 +34,13 @@ func decodeBlock(dst, src []byte) (ret int) {
 					mLen += 4
 					mLen += 4
 					if offset := int(src[si]) | int(src[si+1])<<8; mLen <= offset {
 					if offset := int(src[si]) | int(src[si+1])<<8; mLen <= offset {
 						i := di - offset
 						i := di - offset
-						copy(dst[di:], dst[i:i+18])
+						end := i + 18
+						if end >= len(dst) {
+							// The remaining buffer may not hold 18 bytes.
+							// See https://github.com/pierrec/lz4/issues/51.
+							end = len(dst)
+						}
+						copy(dst[di:], dst[i:end])
 						si += 2
 						si += 2
 						di += mLen
 						di += mLen
 						continue
 						continue

BIN
testdata/issue51.data


+ 26 - 0
writer_test.go

@@ -122,3 +122,29 @@ func TestIssue43(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 }
 }
+
+func TestIssue51(t *testing.T) {
+	data, err := ioutil.ReadFile("testdata/issue51.data")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	zbuf := make([]byte, 8192)
+	ht := make([]int, htSize)
+
+	n, err := lz4.CompressBlock(data, zbuf, ht)
+	if err != nil {
+		t.Fatal(err)
+	}
+	zbuf = zbuf[:n]
+
+	buf := make([]byte, 8192)
+	n, err = lz4.UncompressBlock(zbuf, buf)
+	if err != nil {
+		t.Fatal(err)
+	}
+	buf = buf[:n]
+	if !bytes.Equal(data, buf) {
+		t.Fatal("processed data does not match input")
+	}
+}