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/01 11:46:57 UTC
[1/2] commons-compress git commit: COMPRESS-455 handle APK Signing
Block
Repository: commons-compress
Updated Branches:
refs/heads/master 53f6d42f7 -> 22b0d0629
COMPRESS-455 handle APK Signing Block
Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/af6fe141
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/af6fe141
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/af6fe141
Branch: refs/heads/master
Commit: af6fe141036d30bfd1613758b7a9fb413bf2bafc
Parents: 53f6d42
Author: Stefan Bodewig <bo...@apache.org>
Authored: Sun Jul 1 13:45:56 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Sun Jul 1 13:45:56 2018 +0200
----------------------------------------------------------------------
src/changes/changes.xml | 5 ++
.../archivers/zip/ZipArchiveInputStream.java | 71 ++++++++++++++++++--
2 files changed, 72 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/af6fe141/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 5a620cb..82cf229 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -59,6 +59,11 @@ The <action> type attribute can be add,update,fix,remove.
ensure all held resources get closed even if exceptions are
thrown during the closing the stream.
</action>
+ <action issue="COMPRESS-455" type="fix" date="2018-07-01">
+ ZipArchiveInputStream can now detect the APK Signing Block
+ used in signed Android APK files and treats it as an "end of
+ archive" marker.
+ </action>
</release>
<release version="1.17" date="2018-06-03"
description="Release 1.17">
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/af6fe141/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
index 729d92e..77d6d70 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
@@ -24,7 +24,9 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
+import java.math.BigInteger;
import java.nio.ByteBuffer;
+import java.util.Arrays;
import java.util.zip.CRC32;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
@@ -249,12 +251,12 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
}
final ZipLong sig = new ZipLong(lfhBuf);
- if (sig.equals(ZipLong.CFH_SIG) || sig.equals(ZipLong.AED_SIG)) {
+ if (!sig.equals(ZipLong.LFH_SIG)) {
+ if (sig.equals(ZipLong.CFH_SIG) || sig.equals(ZipLong.AED_SIG) || isApkSigningBlock(lfhBuf)) {
hitCentralDirectory = true;
skipRemainderOfArchive();
return null;
}
- if (!sig.equals(ZipLong.LFH_SIG)) {
throw new ZipException(String.format("Unexpected record signature: 0X%X", sig.getValue()));
}
@@ -789,9 +791,14 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
}
private void readFully(final byte[] b) throws IOException {
- final int count = IOUtils.readFully(in, b);
+ readFully(b, 0);
+ }
+
+ private void readFully(final byte[] b, final int off) throws IOException {
+ final int len = b.length - off;
+ final int count = IOUtils.readFully(in, b, off, len);
count(count);
- if (count < b.length) {
+ if (count < len) {
throw new EOFException();
}
}
@@ -1087,6 +1094,62 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
return b == ZipArchiveOutputStream.EOCD_SIG[0];
}
+ private static final byte[] APK_SIGNING_BLOCK_MAGIC = new byte[] {
+ 'A', 'P', 'K', ' ', 'S', 'i', 'g', ' ', 'B', 'l', 'o', 'c', 'k', ' ', '4', '2',
+ };
+ private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE);
+
+ /**
+ * Checks whether this might be an APK Signing Block.
+ *
+ * <p>Unfortunately the APK signing block does not start with some kind of signature, it rather ends with one. It
+ * starts with a length, so what we do is parse the suspect length, skip ahead far enough, look for the signature
+ * and if we've found it, return true.</p>
+ *
+ * @param suspectLocalFileHeader the bytes read from the underlying stream in the expectation that they would hold
+ * the local file header of the next entry.
+ *
+ * @return true if this looks like a APK signing block
+ *
+ * @see <a href="https://source.android.com/security/apksigning/v2">https://source.android.com/security/apksigning/v2</a>
+ */
+ private boolean isApkSigningBlock(byte[] suspectLocalFileHeader) throws IOException {
+ // length of block excluding the size field itself
+ BigInteger len = ZipEightByteInteger.getValue(suspectLocalFileHeader);
+ // LFH has already been read and all but the first eight bytes contain (part of) the APK signing block,
+ // also subtract 16 bytes in order to position us at the magic string
+ BigInteger toSkip = len.add(BigInteger.valueOf(DWORD - suspectLocalFileHeader.length
+ - APK_SIGNING_BLOCK_MAGIC.length));
+ byte[] magic = new byte[APK_SIGNING_BLOCK_MAGIC.length];
+
+ try {
+ if (toSkip.signum() < 0) {
+ // suspectLocalFileHeader contains the start of suspect magic string
+ int off = suspectLocalFileHeader.length + toSkip.intValue();
+ // length was shorter than magic length
+ if (off < DWORD) {
+ return false;
+ }
+ int bytesInBuffer = Math.abs(toSkip.intValue());
+ System.arraycopy(suspectLocalFileHeader, off, magic, 0, Math.min(bytesInBuffer, magic.length));
+ if (bytesInBuffer < magic.length) {
+ readFully(magic, bytesInBuffer);
+ }
+ } else {
+ while (toSkip.compareTo(LONG_MAX) > 0) {
+ realSkip(Long.MAX_VALUE);
+ toSkip = toSkip.add(LONG_MAX.negate());
+ }
+ realSkip(toSkip.longValue());
+ readFully(magic);
+ }
+ } catch (EOFException ex) {
+ // length was invalid
+ return false;
+ }
+ return Arrays.equals(magic, APK_SIGNING_BLOCK_MAGIC);
+ }
+
/**
* Structure collecting information for the entry that is
* currently being read.
[2/2] 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/22b0d062
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/22b0d062
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/22b0d062
Branch: refs/heads/master
Commit: 22b0d0629267b88749f78412caea672d6539a5b6
Parents: af6fe14
Author: Stefan Bodewig <bo...@apache.org>
Authored: Sun Jul 1 13:46:45 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Sun Jul 1 13:46:45 2018 +0200
----------------------------------------------------------------------
.../compress/archivers/zip/ZipArchiveInputStream.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/22b0d062/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
index 77d6d70..0a2c1aa 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
@@ -253,10 +253,10 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
final ZipLong sig = new ZipLong(lfhBuf);
if (!sig.equals(ZipLong.LFH_SIG)) {
if (sig.equals(ZipLong.CFH_SIG) || sig.equals(ZipLong.AED_SIG) || isApkSigningBlock(lfhBuf)) {
- hitCentralDirectory = true;
- skipRemainderOfArchive();
- return null;
- }
+ hitCentralDirectory = true;
+ skipRemainderOfArchive();
+ return null;
+ }
throw new ZipException(String.format("Unexpected record signature: 0X%X", sig.getValue()));
}