Skip to content

Commit 4ad6b9e

Browse files
committed
[COMPRESS-715] ZipArchiveInputStream fails with "Unexpected record
signature: 0x0" Apply Piotr's suggestion: I couldn't find any documentation that describes the process of padding a ZIP file. Therefore, we must assume that the “padding” is just arbitrary data.
1 parent d60f6af commit 4ad6b9e

File tree

1 file changed

+3
-56
lines changed

1 file changed

+3
-56
lines changed

src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java

Lines changed: 3 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@
3030
import java.io.IOException;
3131
import java.io.InputStream;
3232
import java.io.PushbackInputStream;
33-
import java.math.BigInteger;
3433
import java.nio.ByteBuffer;
3534
import java.nio.charset.StandardCharsets;
36-
import java.util.Arrays;
3735
import java.util.function.Function;
3836
import java.util.zip.CRC32;
3937
import java.util.zip.DataFormatException;
@@ -327,8 +325,6 @@ private <T extends InputStream> T checkInputStream() throws ZipException {
327325
private static final byte[] LFH = ZipLong.LFH_SIG.getBytes();
328326
private static final byte[] CFH = ZipLong.CFH_SIG.getBytes();
329327
private static final byte[] DD = ZipLong.DD_SIG.getBytes();
330-
private static final byte[] APK_SIGNING_BLOCK_MAGIC = { 'A', 'P', 'K', ' ', 'S', 'i', 'g', ' ', 'B', 'l', 'o', 'c', 'k', ' ', '4', '2', };
331-
private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE);
332328

333329
/**
334330
* Creates a new builder.
@@ -838,12 +834,9 @@ public ZipArchiveEntry getNextZipEntry() throws IOException {
838834
}
839835
final ZipLong sig = new ZipLong(lfhBuf);
840836
if (!sig.equals(ZipLong.LFH_SIG)) {
841-
if (sig.equals(ZipLong.CFH_SIG) || sig.equals(ZipLong.AED_SIG) || isApkSigningBlock(lfhBuf) || sig.equals(ZipLong.ZERO)) {
842-
hitCentralDirectory = true;
843-
skipRemainderOfArchive();
844-
return null;
845-
}
846-
throw new ZipException(String.format("Unexpected record signature: 0x%x", sig.getValue()));
837+
hitCentralDirectory = true;
838+
skipRemainderOfArchive();
839+
return null;
847840
}
848841
// off: go past the signature
849842
int off = WORD;
@@ -946,52 +939,6 @@ public long getUncompressedCount() {
946939
return uncompressedCount;
947940
}
948941

949-
/**
950-
* Checks whether this might be an APK Signing Block.
951-
* <p>
952-
* 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
953-
* the suspect length, skip ahead far enough, look for the signature and if we've found it, return true.
954-
* </p>
955-
*
956-
* @param suspectLocalFileHeader the bytes read from the underlying stream in the expectation that they would hold the local file header of the next entry.
957-
* @return true if this looks like an APK signing block.
958-
* @see <a href="https://source.android.com/security/apksigning/v2">https://source.android.com/security/apksigning/v2</a>
959-
*/
960-
private boolean isApkSigningBlock(final byte[] suspectLocalFileHeader) throws IOException {
961-
// length of block excluding the size field itself
962-
final BigInteger len = ZipEightByteInteger.getValue(suspectLocalFileHeader);
963-
// LFH has already been read and all but the first eight bytes contain (part of) the APK signing block,
964-
// also subtract 16 bytes in order to position us at the magic string
965-
BigInteger toSkip = len.add(BigInteger.valueOf(DWORD - suspectLocalFileHeader.length - (long) APK_SIGNING_BLOCK_MAGIC.length));
966-
final byte[] magic = new byte[APK_SIGNING_BLOCK_MAGIC.length];
967-
try {
968-
if (toSkip.signum() < 0) {
969-
// suspectLocalFileHeader contains the start of suspect magic string
970-
final int off = suspectLocalFileHeader.length + toSkip.intValue();
971-
// length was shorter than magic length
972-
if (off < DWORD) {
973-
return false;
974-
}
975-
final int bytesInBuffer = Math.abs(toSkip.intValue());
976-
System.arraycopy(suspectLocalFileHeader, off, magic, 0, Math.min(bytesInBuffer, magic.length));
977-
if (bytesInBuffer < magic.length) {
978-
readFully(magic, bytesInBuffer);
979-
}
980-
} else {
981-
while (toSkip.compareTo(LONG_MAX) > 0) {
982-
realSkip(Long.MAX_VALUE);
983-
toSkip = toSkip.add(LONG_MAX.negate());
984-
}
985-
realSkip(toSkip.longValue());
986-
readFully(magic);
987-
}
988-
} catch (final EOFException ex) { // NOSONAR
989-
// length was invalid
990-
return false;
991-
}
992-
return Arrays.equals(magic, APK_SIGNING_BLOCK_MAGIC);
993-
}
994-
995942
private boolean isFirstByteOfEocdSig(final int b) {
996943
return b == ZipArchiveOutputStream.EOCD_SIG[0];
997944
}

0 commit comments

Comments
 (0)