You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2018/07/11 16:52:50 UTC

[1/6] commons-compress git commit: Fix writing of multibyte name entries

Repository: commons-compress
Updated Branches:
  refs/heads/master f5330f7e6 -> 430e12676


Fix writing of multibyte name entries


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/1fbb16b0
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/1fbb16b0
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/1fbb16b0

Branch: refs/heads/master
Commit: 1fbb16b037e62c6af90ab89ab3ac8d3633c59a90
Parents: 9e80104
Author: Jens Reimann <jr...@redhat.com>
Authored: Wed Jul 11 09:20:44 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Wed Jul 11 18:05:49 2018 +0200

----------------------------------------------------------------------
 .../archivers/cpio/CpioArchiveEntry.java        | 26 ++++++++++++++++++--
 .../archivers/cpio/CpioArchiveOutputStream.java |  5 ++--
 2 files changed, 27 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/1fbb16b0/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java
----------------------------------------------------------------------
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 3ad7c87..0266da1 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
@@ -19,6 +19,7 @@
 package org.apache.commons.compress.archivers.cpio;
 
 import java.io.File;
+import java.nio.charset.Charset;
 import java.util.Date;
 
 import org.apache.commons.compress.archivers.ArchiveEntry;
@@ -466,11 +467,32 @@ public class CpioArchiveEntry implements CpioConstants, ArchiveEntry {
     /**
      * Get the number of bytes needed to pad the header to the alignment boundary.
      *
+     * @deprecated This method doesn't properly work for multi-byte encodings. And
+     *             creates corrupt archives. Use {@link #getHeaderPadCount(Charset)}
+     *             or {@link #getHeaderPadCount(long)} in any case.
      * @return the number of bytes needed to pad the header (0,1,2,3)
      */
+    @Deprecated
     public int getHeaderPadCount(){
-        long namesize = name != null ? name.length() : 0;
-        return getHeaderPadCount(namesize);
+        return getHeaderPadCount(null);
+    }
+
+    /**
+     * Get the number of bytes needed to pad the header to the alignment boundary.
+     *
+     * @param charset
+     *             The character set used to encode the entry name in the stream. 
+     * @return the number of bytes needed to pad the header (0,1,2,3)
+     * @since 1.18
+     */
+    public int getHeaderPadCount(Charset charset){
+        if (name==null) {
+            return 0;
+        }
+        if (charset==null) {
+            return getHeaderPadCount(name.length());
+        }
+        return getHeaderPadCount(name.getBytes(charset).length);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/1fbb16b0/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
index c0e04c4..07fd53a 100644
--- a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
@@ -22,6 +22,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
 import java.util.HashMap;
 
 import org.apache.commons.compress.archivers.ArchiveEntry;
@@ -302,7 +303,7 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
         writeAsciiLong(entry.getName().length() + 1L, 8, 16);
         writeAsciiLong(entry.getChksum(), 8, 16);
         writeCString(entry.getName());
-        pad(entry.getHeaderPadCount());
+        pad(entry.getHeaderPadCount(Charset.forName(encoding)));
     }
 
     private void writeOldAsciiEntry(final CpioArchiveEntry entry)
@@ -363,7 +364,7 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
         writeBinaryLong(entry.getName().length() + 1L, 2, swapHalfWord);
         writeBinaryLong(entry.getSize(), 4, swapHalfWord);
         writeCString(entry.getName());
-        pad(entry.getHeaderPadCount());
+        pad(entry.getHeaderPadCount(Charset.forName(encoding)));
     }
 
     /*(non-Javadoc)


[5/6] commons-compress git commit: COMPRESS-459 use ZipEncoding consistently

Posted by bo...@apache.org.
COMPRESS-459 use ZipEncoding consistently


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/c8ee9f78
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/c8ee9f78
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/c8ee9f78

Branch: refs/heads/master
Commit: c8ee9f781900f874b075433141de779723b3e110
Parents: 72bfc12
Author: Stefan Bodewig <bo...@apache.org>
Authored: Wed Jul 11 18:50:01 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Wed Jul 11 18:50:01 2018 +0200

----------------------------------------------------------------------
 .../archivers/cpio/CpioArchiveEntry.java        | 22 +++++++++++++-------
 .../archivers/cpio/CpioArchiveOutputStream.java |  5 ++---
 2 files changed, 17 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/c8ee9f78/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java
----------------------------------------------------------------------
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 79e7542..6aeb7ce 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
@@ -18,11 +18,13 @@
  */
 package org.apache.commons.compress.archivers.cpio;
 
+import java.nio.ByteBuffer;
 import java.io.File;
-import java.nio.charset.Charset;
+import java.io.IOException;
 import java.util.Date;
 
 import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipEncoding;
 
 /**
  * A cpio archive consists of a sequence of files. There are several types of
@@ -468,7 +470,7 @@ public class CpioArchiveEntry implements CpioConstants, ArchiveEntry {
      * Get the number of bytes needed to pad the header to the alignment boundary.
      *
      * @deprecated This method doesn't properly work for multi-byte encodings. And
-     *             creates corrupt archives. Use {@link #getHeaderPadCount(Charset)}
+     *             creates corrupt archives. Use {@link #getHeaderPadCount(ZipEncoding)}
      *             or {@link #getHeaderPadCount(long)} in any case.
      * @return the number of bytes needed to pad the header (0,1,2,3)
      */
@@ -480,19 +482,25 @@ public class CpioArchiveEntry implements CpioConstants, ArchiveEntry {
     /**
      * Get the number of bytes needed to pad the header to the alignment boundary.
      *
-     * @param charset
-     *             The character set used to encode the entry name in the stream.
+     * @param encoding
+     *             The encoding used to encode the entry name in the stream.
      * @return the number of bytes needed to pad the header (0,1,2,3)
      * @since 1.18
      */
-    public int getHeaderPadCount(Charset charset) {
+    public int getHeaderPadCount(ZipEncoding encoding) {
         if (name == null) {
             return 0;
         }
-        if (charset == null) {
+        if (encoding == null) {
             return getHeaderPadCount(name.length());
         }
-        return getHeaderPadCount(name.getBytes(charset).length);
+        try {
+            final ByteBuffer buf = encoding.encode(name);
+            return getHeaderPadCount(buf.limit() - buf.position());
+        } catch (IOException ex) {
+            // won't happen as the output stream has already encoded the name without error
+            throw new RuntimeException("cannot encode " + name, ex);
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/c8ee9f78/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
index afb57a2..73cf714 100644
--- a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
@@ -22,7 +22,6 @@ import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
 import java.util.Arrays;
 import java.util.HashMap;
 
@@ -305,7 +304,7 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
         writeAsciiLong(name.length + 1L, 8, 16);
         writeAsciiLong(entry.getChksum(), 8, 16);
         writeCString(name);
-        pad(entry.getHeaderPadCount(Charset.forName(encoding)));
+        pad(entry.getHeaderPadCount(zipEncoding));
     }
 
     private void writeOldAsciiEntry(final CpioArchiveEntry entry)
@@ -368,7 +367,7 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
         writeBinaryLong(name.length + 1L, 2, swapHalfWord);
         writeBinaryLong(entry.getSize(), 4, swapHalfWord);
         writeCString(name);
-        pad(entry.getHeaderPadCount(Charset.forName(encoding)));
+        pad(entry.getHeaderPadCount(zipEncoding));
     }
 
     /*(non-Javadoc)


[3/6] commons-compress git commit: whitespace

Posted by bo...@apache.org.
whitespace


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/17575b88
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/17575b88
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/17575b88

Branch: refs/heads/master
Commit: 17575b8836ba18201ac7b839aeb432421b0c89bf
Parents: 1fbb16b
Author: Stefan Bodewig <bo...@apache.org>
Authored: Wed Jul 11 18:09:42 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Wed Jul 11 18:09:42 2018 +0200

----------------------------------------------------------------------
 .../compress/archivers/cpio/CpioArchiveEntry.java     | 14 +++++++-------
 .../archivers/cpio/CpioArchiveInputStream.java        |  4 ++--
 2 files changed, 9 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/17575b88/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java
----------------------------------------------------------------------
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 0266da1..79e7542 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
@@ -481,15 +481,15 @@ public class CpioArchiveEntry implements CpioConstants, ArchiveEntry {
      * Get the number of bytes needed to pad the header to the alignment boundary.
      *
      * @param charset
-     *             The character set used to encode the entry name in the stream. 
+     *             The character set used to encode the entry name in the stream.
      * @return the number of bytes needed to pad the header (0,1,2,3)
      * @since 1.18
      */
-    public int getHeaderPadCount(Charset charset){
-        if (name==null) {
+    public int getHeaderPadCount(Charset charset) {
+        if (name == null) {
             return 0;
         }
-        if (charset==null) {
+        if (charset == null) {
             return getHeaderPadCount(name.length());
         }
         return getHeaderPadCount(name.getBytes(charset).length);
@@ -502,17 +502,17 @@ public class CpioArchiveEntry implements CpioConstants, ArchiveEntry {
      *            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){
+    public int getHeaderPadCount(long namesize) {
         if (this.alignmentBoundary == 0) { return 0; }
         int size = this.headerSize + 1;  // Name has terminating null
         if (name != null) {
             size += namesize;
         }
         final int remain = size % this.alignmentBoundary;
-        if (remain > 0){
+        if (remain > 0) {
             return this.alignmentBoundary - remain;
         }
         return 0;

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/17575b88/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java
----------------------------------------------------------------------
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 b64d091..bdfc802 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(namesize-1));
+        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(namesize-1));
+        skip(ret.getHeaderPadCount(namesize - 1));
 
         return ret;
     }


[6/6] commons-compress git commit: COMPRESS-459 record change

Posted by bo...@apache.org.
COMPRESS-459 record change

closes #67


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/430e1267
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/430e1267
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/430e1267

Branch: refs/heads/master
Commit: 430e1267633bf2db0ee1c833c0c5f61f4a45702d
Parents: c8ee9f7
Author: Stefan Bodewig <bo...@apache.org>
Authored: Wed Jul 11 18:52:16 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Wed Jul 11 18:52:16 2018 +0200

----------------------------------------------------------------------
 src/changes/changes.xml | 5 +++++
 1 file changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/430e1267/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 82cf229..de587a0 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -64,6 +64,11 @@ The <action> type attribute can be add,update,fix,remove.
         used in signed Android APK files and treats it as an "end of
         archive" marker.
       </action>
+      <action issue="COMPRESS-459" type="fix" date="2018-07-11"
+              due-to="Jens Reimann">
+        The cpio stream didn't handle archives using a multi-byte
+        encoding properly.
+      </action>
     </release>
     <release version="1.17" date="2018-06-03"
              description="Release 1.17">


[4/6] commons-compress git commit: COMPRESS-459 fix writing of multibyte names and add a test as proof

Posted by bo...@apache.org.
COMPRESS-459 fix writing of multibyte names and add a test as proof


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/72bfc124
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/72bfc124
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/72bfc124

Branch: refs/heads/master
Commit: 72bfc1247553bdd2711d6bb27a7179be86ded4f1
Parents: 17575b8
Author: Stefan Bodewig <bo...@apache.org>
Authored: Wed Jul 11 18:42:57 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Wed Jul 11 18:42:57 2018 +0200

----------------------------------------------------------------------
 .../archivers/cpio/CpioArchiveOutputStream.java | 35 ++++++---
 .../archivers/cpio/CpioArchiveTest.java         | 74 ++++++++++++++++++++
 2 files changed, 99 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/72bfc124/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
index 07fd53a..afb57a2 100644
--- a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
+import java.util.Arrays;
 import java.util.HashMap;
 
 import org.apache.commons.compress.archivers.ArchiveEntry;
@@ -300,9 +301,10 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
         writeAsciiLong(devMin, 8, 16);
         writeAsciiLong(entry.getRemoteDeviceMaj(), 8, 16);
         writeAsciiLong(entry.getRemoteDeviceMin(), 8, 16);
-        writeAsciiLong(entry.getName().length() + 1L, 8, 16);
+        byte[] name = encode(entry.getName());
+        writeAsciiLong(name.length + 1L, 8, 16);
         writeAsciiLong(entry.getChksum(), 8, 16);
-        writeCString(entry.getName());
+        writeCString(name);
         pad(entry.getHeaderPadCount(Charset.forName(encoding)));
     }
 
@@ -331,9 +333,10 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
         writeAsciiLong(entry.getNumberOfLinks(), 6, 8);
         writeAsciiLong(entry.getRemoteDevice(), 6, 8);
         writeAsciiLong(entry.getTime(), 11, 8);
-        writeAsciiLong(entry.getName().length() + 1L, 6, 8);
+        byte[] name = encode(entry.getName());
+        writeAsciiLong(name.length + 1L, 6, 8);
         writeAsciiLong(entry.getSize(), 11, 8);
-        writeCString(entry.getName());
+        writeCString(name);
     }
 
     private void writeOldBinaryEntry(final CpioArchiveEntry entry,
@@ -361,9 +364,10 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
         writeBinaryLong(entry.getNumberOfLinks(), 2, swapHalfWord);
         writeBinaryLong(entry.getRemoteDevice(), 2, swapHalfWord);
         writeBinaryLong(entry.getTime(), 4, swapHalfWord);
-        writeBinaryLong(entry.getName().length() + 1L, 2, swapHalfWord);
+        byte[] name = encode(entry.getName());
+        writeBinaryLong(name.length + 1L, 2, swapHalfWord);
         writeBinaryLong(entry.getSize(), 4, swapHalfWord);
-        writeCString(entry.getName());
+        writeCString(name);
         pad(entry.getHeaderPadCount(Charset.forName(encoding)));
     }
 
@@ -537,16 +541,27 @@ public class CpioArchiveOutputStream extends ArchiveOutputStream implements
     }
 
     /**
-     * Writes an ASCII string to the stream followed by \0
+     * Encodes the given string using the configured encoding.
+     *
      * @param str the String to write
      * @throws IOException if the string couldn't be written
+     * @return result of encoding the string
      */
-    private void writeCString(final String str) throws IOException {
+    private byte[] encode(final String str) throws IOException {
         final ByteBuffer buf = zipEncoding.encode(str);
         final int len = buf.limit() - buf.position();
-        out.write(buf.array(), buf.arrayOffset(), len);
+        return Arrays.copyOfRange(buf.array(), buf.arrayOffset(), buf.arrayOffset() + len);
+    }
+
+    /**
+     * Writes an encoded string to the stream followed by \0
+     * @param str the String to write
+     * @throws IOException if the string couldn't be written
+     */
+    private void writeCString(byte[] str) throws IOException {
+        out.write(str);
         out.write('\0');
-        count(len + 1);
+        count(str.length + 1);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/72bfc124/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveTest.java b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveTest.java
new file mode 100644
index 0000000..0dac090
--- /dev/null
+++ b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveTest.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.commons.compress.archivers.cpio;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import org.apache.commons.compress.utils.IOUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class CpioArchiveTest {
+
+    @Parameters(name = "using {0}")
+    public static Collection<Object[]> factory() {
+        return Arrays.asList(new Object[][] {
+                new Object[]  { CpioConstants.FORMAT_NEW },
+                new Object[]  { CpioConstants.FORMAT_NEW_CRC },
+                new Object[]  { CpioConstants.FORMAT_OLD_ASCII },
+                new Object[]  { CpioConstants.FORMAT_OLD_BINARY },
+            });
+    }
+
+    private final short format;
+
+    public CpioArchiveTest(short format) {
+        this.format = format;
+    }
+
+    @Test
+    public void utf18RoundtripTest() throws Exception {
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            try (CpioArchiveOutputStream os = new CpioArchiveOutputStream(baos, format, CpioConstants.BLOCK_SIZE,
+                "UTF-16LE")) {
+                CpioArchiveEntry entry = new CpioArchiveEntry(format, "T\u00e4st.txt", 4);
+                if (format == CpioConstants.FORMAT_NEW_CRC) {
+                    entry.setChksum(10);
+                }
+                os.putArchiveEntry(entry);
+                os.write(new byte[] { 1, 2, 3, 4 });
+                os.closeArchiveEntry();
+            }
+            baos.close();
+            try (ByteArrayInputStream bin = new ByteArrayInputStream(baos.toByteArray());
+                 CpioArchiveInputStream in = new CpioArchiveInputStream(bin, "UTF-16LE")) {
+                CpioArchiveEntry entry = (CpioArchiveEntry) in.getNextEntry();
+                Assert.assertNotNull(entry);
+                Assert.assertEquals("T\u00e4st.txt", entry.getName());
+                Assert.assertArrayEquals(new byte[] { 1, 2, 3, 4 }, IOUtils.toByteArray(in));
+            }
+        }
+    }
+}


[2/6] commons-compress git commit: Fix reading of multibyte name entries

Posted by bo...@apache.org.
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.


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/9e80104b
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/9e80104b
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/9e80104b

Branch: refs/heads/master
Commit: 9e80104befc54daaa097870b857e1bc334521490
Parents: f5330f7
Author: Jens Reimann <jr...@redhat.com>
Authored: Mon Jul 9 11:41:43 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Wed Jul 11 18:05:49 2018 +0200

----------------------------------------------------------------------
 .../compress/archivers/cpio/CpioArchiveEntry.java |  17 ++++++++++++++++-
 .../archivers/cpio/CpioArchiveInputStream.java    |   4 ++--
 .../cpio/CpioArchiveInputStreamTest.java          |  16 ++++++++++++++++
 src/test/resources/COMPRESS-459.cpio              | Bin 0 -> 512 bytes
 4 files changed, 34 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9e80104b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java
----------------------------------------------------------------------
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 28e5823..3ad7c87 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){

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9e80104b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java
----------------------------------------------------------------------
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 ad8e125..b64d091 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;
     }

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9e80104b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java
----------------------------------------------------------------------
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 f174405..762d464 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);
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9e80104b/src/test/resources/COMPRESS-459.cpio
----------------------------------------------------------------------
diff --git a/src/test/resources/COMPRESS-459.cpio b/src/test/resources/COMPRESS-459.cpio
new file mode 100644
index 0000000..8ae1662
Binary files /dev/null and b/src/test/resources/COMPRESS-459.cpio differ