diff options
author | Jens Reimann <jreimann@redhat.com> | 2018-07-09 11:41:43 +0200 |
---|---|---|
committer | Stefan Bodewig <bodewig@apache.org> | 2018-07-11 18:05:49 +0200 |
commit | 9e80104befc54daaa097870b857e1bc334521490 (patch) | |
tree | 1e3bd3bd420c6fa51bd6ef2292d2f6cbfceb05d5 | |
parent | f5330f7e667f5a7245c8a5f3007cda04554c5fe2 (diff) | |
download | apache-commons-compress-9e80104befc54daaa097870b857e1bc334521490.tar.gz |
Fix reading of multibyte name entries
This fixes COMPRESS-459 by using the name number of bytes from the field
in the stream instead of relying on the assumption that each character
is exactly one byte, which isn't true for UTF-8, UTF-16 or other
multi-byte character encodings.
4 files changed, 34 insertions, 3 deletions
diff --git a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java index 28e58238c..3ad7c87da 100644 --- a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java +++ b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java @@ -469,10 +469,25 @@ public class CpioArchiveEntry implements CpioConstants, ArchiveEntry { * @return the number of bytes needed to pad the header (0,1,2,3) */ public int getHeaderPadCount(){ + long namesize = name != null ? name.length() : 0; + return getHeaderPadCount(namesize); + } + + /** + * Get the number of bytes needed to pad the header to the alignment boundary. + * + * @param namesize + * The length of the name in bytes, as read in the stream. + * Without the trailing zero byte. + * @return the number of bytes needed to pad the header (0,1,2,3) + * + * @since 1.18 + */ + public int getHeaderPadCount(long namesize){ if (this.alignmentBoundary == 0) { return 0; } int size = this.headerSize + 1; // Name has terminating null if (name != null) { - size += name.length(); + size += namesize; } final int remain = size % this.alignmentBoundary; if (remain > 0){ diff --git a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java index ad8e125a9..b64d09104 100644 --- a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java +++ b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java @@ -393,7 +393,7 @@ public class CpioArchiveInputStream extends ArchiveInputStream implements + ArchiveUtils.sanitize(name) + " Occured at byte: " + getBytesRead()); } - skip(ret.getHeaderPadCount()); + skip(ret.getHeaderPadCount(namesize-1)); return ret; } @@ -449,7 +449,7 @@ public class CpioArchiveInputStream extends ArchiveInputStream implements + ArchiveUtils.sanitize(name) + "Occured at byte: " + getBytesRead()); } - skip(ret.getHeaderPadCount()); + skip(ret.getHeaderPadCount(namesize-1)); return ret; } diff --git a/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java index f1744053c..762d4648e 100644 --- a/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java @@ -65,4 +65,20 @@ public class CpioArchiveInputStreamTest extends AbstractTestCase { assertEquals(count, 1); } + + @Test + public void testCpioUnarchiveMultibyteCharName() throws Exception { + final CpioArchiveInputStream in = + new CpioArchiveInputStream(new FileInputStream(getFile("COMPRESS-459.cpio")), "UTF-8"); + CpioArchiveEntry entry= null; + + int count = 0; + while ((entry = (CpioArchiveEntry) in.getNextEntry()) != null) { + count++; + assertNotNull(entry); + } + in.close(); + + assertEquals(2, count); + } } diff --git a/src/test/resources/COMPRESS-459.cpio b/src/test/resources/COMPRESS-459.cpio Binary files differnew file mode 100644 index 000000000..8ae1662a0 --- /dev/null +++ b/src/test/resources/COMPRESS-459.cpio |