Browse Source

Merge pull request #37 from edwingeng/master

fix: CompressBlock/UncompressBlock does not return error under certain circumstances
Pierre Curto 6 years ago
parent
commit
473cd7ce01
3 changed files with 41 additions and 6 deletions
  1. 6 6
      block.go
  2. 35 0
      block_test.go
  3. BIN
      testdata/upperbound.data

+ 6 - 6
block.go

@@ -61,7 +61,7 @@ func UncompressBlock(src, dst []byte) (si int, err error) {
 			}
 			i := si
 			si += lLen
-			di += copy(dst[di:], src[i:si])
+			di += copy(dst[di:di+si-i], src[i:si])
 
 			if si >= sn {
 				return di, nil
@@ -97,7 +97,7 @@ func UncompressBlock(src, dst []byte) (si int, err error) {
 			di += bytesToCopy
 			mLen -= bytesToCopy
 		}
-		di += copy(dst[di:], dst[i:i+mLen])
+		di += copy(dst[di:di+mLen], dst[i:i+mLen])
 	}
 }
 
@@ -186,7 +186,7 @@ func CompressBlock(src, dst []byte, hashTable []int) (di int, err error) {
 		di++
 
 		// Literals.
-		copy(dst[di:], src[anchor:anchor+lLen])
+		copy(dst[di:di+lLen], src[anchor:anchor+lLen])
 		di += lLen + 2
 		anchor = si
 
@@ -230,7 +230,7 @@ func CompressBlock(src, dst []byte, hashTable []int) (di int, err error) {
 		// Incompressible.
 		return 0, nil
 	}
-	di += copy(dst[di:], src[anchor:])
+	di += copy(dst[di:di+len(src)-anchor], src[anchor:])
 	return di, nil
 }
 
@@ -347,7 +347,7 @@ func CompressBlockHC(src, dst []byte, depth int) (di int, err error) {
 		di++
 
 		// Literals.
-		copy(dst[di:], src[anchor:anchor+lLen])
+		copy(dst[di:di+lLen], src[anchor:anchor+lLen])
 		di += lLen
 		anchor = si
 
@@ -392,6 +392,6 @@ func CompressBlockHC(src, dst []byte, depth int) (di int, err error) {
 		// Incompressible.
 		return 0, nil
 	}
-	di += copy(dst[di:], src[anchor:])
+	di += copy(dst[di:di+len(src)-anchor], src[anchor:])
 	return di, nil
 }

+ 35 - 0
block_test.go

@@ -96,3 +96,38 @@ func TestCompressUncompressBlock(t *testing.T) {
 		fmt.Printf("%-40s: %8d / %8d / %8d\n", tc.file, n, nhc, len(src))
 	}
 }
+
+func TestCompressCornerCase_CopyDstUpperBound(t *testing.T) {
+	type compressor func(s, d []byte) (int, error)
+
+	run := func(src []byte, compress compressor) {
+		t.Helper()
+
+		// Compress the data.
+		zbuf := make([]byte, int(float64(len(src))*0.85))
+		_, err := compress(src, zbuf)
+		if err != lz4.ErrInvalidSourceShortBuffer {
+			t.Fatal("err should be ErrInvalidSourceShortBuffer")
+		}
+	}
+
+	file := "testdata/upperbound.data"
+	src, err := ioutil.ReadFile(file)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	t.Run(file, func(t *testing.T) {
+		t.Parallel()
+		run(src, func(src, dst []byte) (int, error) {
+			var ht [1 << 16]int
+			return lz4.CompressBlock(src, dst, ht[:])
+		})
+	})
+	t.Run(fmt.Sprintf("%s HC", file), func(t *testing.T) {
+		t.Parallel()
+		run(src, func(src, dst []byte) (int, error) {
+			return lz4.CompressBlockHC(src, dst, -1)
+		})
+	})
+}

BIN
testdata/upperbound.data