fix calculation of self-copy boundaries when expanding back-references
Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/5ce60be9 Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/5ce60be9 Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/5ce60be9 Branch: refs/heads/master Commit: 5ce60be9d55c62b72262680249ad933850aaa064 Parents: 62202d2 Author: Stefan Bodewig <bode...@apache.org> Authored: Thu Apr 6 15:18:00 2017 +0200 Committer: Stefan Bodewig <bode...@apache.org> Committed: Thu Apr 6 15:18:00 2017 +0200 ---------------------------------------------------------------------- .../lz4/BlockLZ4CompressorOutputStream.java | 4 ++-- .../lz4/BlockLZ4CompressorOutputStreamTest.java | 23 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-compress/blob/5ce60be9/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java b/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java index dfce36e..71ca713 100644 --- a/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java +++ b/src/main/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStream.java @@ -264,9 +264,9 @@ public class BlockLZ4CompressorOutputStream extends CompressorOutputStream { copyOffset = blockOffset + block.length - offsetRemaining; copyLen = Math.min(lengthRemaining, block.length - copyOffset); } else { - // offsetRemaining is negative and points into the expanded bytes + // offsetRemaining is negative or 0 and points into the expanded bytes block = expanded; - copyOffset = writeOffset + offsetRemaining; + copyOffset = -offsetRemaining; copyLen = Math.min(lengthRemaining, writeOffset + offsetRemaining); } System.arraycopy(block, copyOffset, expanded, writeOffset, copyLen); http://git-wip-us.apache.org/repos/asf/commons-compress/blob/5ce60be9/src/test/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStreamTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStreamTest.java b/src/test/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStreamTest.java index 45bf684..fca3f88 100644 --- a/src/test/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStreamTest.java +++ b/src/test/java/org/apache/commons/compress/compressors/lz4/BlockLZ4CompressorOutputStreamTest.java @@ -319,6 +319,29 @@ public class BlockLZ4CompressorOutputStreamTest { Assert.assertArrayEquals(expected, compressed); } + @Test + public void rewritingWithFinalBackreferenceAndOffsetBiggerThan1() throws IOException { + // this caused trouble when expandFromList() fell into the "offsetRemaining is negative" self-copy case as the + // calculation of copyOffset was wrong + byte[] toCompress = prepareExpected(25); + for (int i = 0; i < toCompress.length; i += 4) { + toCompress[i] = 1; + } + // LZ77Compressor creates a four byte literal and a back-reference with offset 4 and length 21 + // we'll need to split the back-reference and chop off the last 12 bytes + byte[] compressed = compress(toCompress); + byte[] expected = prepareExpected(1 + 4 + 2 + 1 + 12); + expected[0] = (byte) ((4<<4) | 5); + expected[1] = 1; + expected[5] = 4; + expected[6] = 0; + expected[7] = (byte) (12<<4); + for (int i = 11; i < expected.length; i += 4) { + expected[i] = 1; + } + Assert.assertArrayEquals(expected, compressed); + } + private byte[] compress(int length) throws IOException { return compress(length, 0); }