Author: bodewig
Date: Fri Dec 20 12:13:11 2013
New Revision: 1552608
URL: http://svn.apache.org/r1552608
Log:
COMPRESS-252 off-by-one error writing bitsets that leads to corrupt 7z headers
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java?rev=1552608&r1=1552607&r2=1552608&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java
(original)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java
Fri Dec 20 12:13:11 2013
@@ -636,14 +636,13 @@ public class SevenZOutputFile {
int shift = 7;
for (int i = 0; i < length; i++) {
cache |= ((bits.get(i) ? 1 : 0) << shift);
- --shift;
- if (shift == 0) {
+ if (--shift < 0) {
header.write(cache);
shift = 7;
cache = 0;
}
}
- if (length > 0 && shift > 0) {
+ if (shift != 7) {
header.write(cache);
}
}
Modified:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java?rev=1552608&r1=1552607&r2=1552608&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
(original)
+++
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
Fri Dec 20 12:13:11 2013
@@ -171,4 +171,113 @@ public class SevenZOutputFileTest extend
}
}
+ public void testSixEmptyFiles() throws Exception {
+ testCompress252(6, 0);
+ }
+
+ public void testSixFilesSomeNotEmpty() throws Exception {
+ testCompress252(6, 2);
+ }
+
+ public void testSevenEmptyFiles() throws Exception {
+ testCompress252(7, 0);
+ }
+
+ public void testSevenFilesSomeNotEmpty() throws Exception {
+ testCompress252(7, 2);
+ }
+
+ public void testEightEmptyFiles() throws Exception {
+ testCompress252(8, 0);
+ }
+
+ public void testEightFilesSomeNotEmpty() throws Exception {
+ testCompress252(8, 2);
+ }
+
+ public void testNineEmptyFiles() throws Exception {
+ testCompress252(9, 0);
+ }
+
+ public void testNineFilesSomeNotEmpty() throws Exception {
+ testCompress252(9, 2);
+ }
+
+ private void testCompress252(int numberOfFiles, int numberOfNonEmptyFiles)
+ throws Exception {
+ int nonEmptyModulus = numberOfNonEmptyFiles != 0
+ ? numberOfFiles / numberOfNonEmptyFiles
+ : numberOfFiles + 1;
+ output = new File(dir, "COMPRESS252-" + numberOfFiles + "-" +
numberOfNonEmptyFiles + ".7z");
+ SevenZOutputFile archive = new SevenZOutputFile(output);
+ try {
+ addDir(archive);
+ for (int i = 0; i < numberOfFiles; i++) {
+ addFile(archive, i, (i + 1) % nonEmptyModulus == 0);
+ }
+ } finally {
+ archive.close();
+ }
+ verifyCompress252(output, numberOfFiles, numberOfNonEmptyFiles);
+ }
+
+ private void verifyCompress252(File output, int numberOfFiles, int
numberOfNonEmptyFiles)
+ throws Exception {
+ SevenZFile archive = new SevenZFile(output);
+ int filesFound = 0;
+ int nonEmptyFilesFound = 0;
+ try {
+ verifyDir(archive);
+ Boolean b = verifyFile(archive, filesFound++);
+ while (b != null) {
+ if (Boolean.TRUE.equals(b)) {
+ nonEmptyFilesFound++;
+ }
+ b = verifyFile(archive, filesFound++);
+ }
+ } finally {
+ archive.close();
+ }
+ assertEquals(numberOfFiles + 1, filesFound);
+ assertEquals(numberOfNonEmptyFiles, nonEmptyFilesFound);
+ }
+
+ private void addDir(SevenZOutputFile archive) throws Exception {
+ SevenZArchiveEntry entry = archive.createArchiveEntry(dir, "foo/");
+ archive.putArchiveEntry(entry);
+ archive.closeArchiveEntry();
+ }
+
+ private void verifyDir(SevenZFile archive) throws Exception {
+ SevenZArchiveEntry entry = archive.getNextEntry();
+ assertNotNull(entry);
+ assertEquals("foo/", entry.getName());
+ assertTrue(entry.isDirectory());
+ }
+
+ private void addFile(SevenZOutputFile archive, int index, boolean nonEmpty)
+ throws Exception {
+ SevenZArchiveEntry entry = new SevenZArchiveEntry();
+ entry.setName("foo/" + index + ".txt");
+ archive.putArchiveEntry(entry);
+ archive.write(nonEmpty ? new byte[] { 17 } : new byte[0]);
+ archive.closeArchiveEntry();
+ }
+
+ private Boolean verifyFile(SevenZFile archive, int index) throws Exception
{
+ SevenZArchiveEntry entry = archive.getNextEntry();
+ if (entry == null) {
+ return null;
+ }
+ assertEquals("foo/" + index + ".txt", entry.getName());
+ assertEquals(false, entry.isDirectory());
+ if (entry.getSize() == 0) {
+ return false;
+ }
+ assertEquals(1, entry.getSize());
+ assertEquals(17, archive.read());
+ assertEquals(-1, archive.read());
+ return true;
+ }
+
}