[Git][java-team/zip4j][upstream] New upstream version 2.10.0
Andrius Merkys (@merkys)
gitlab at salsa.debian.org
Fri Apr 1 10:21:56 BST 2022
Andrius Merkys pushed to branch upstream at Debian Java Maintainers / zip4j
Commits:
ac1a59b6 by Andrius Merkys at 2022-04-01T04:44:06-04:00
New upstream version 2.10.0
- - - - -
25 changed files:
- + .github/workflows/maven.yml
- − .travis.yml
- README.md
- pom.xml
- src/main/java/net/lingala/zip4j/headers/HeaderReader.java
- src/main/java/net/lingala/zip4j/headers/HeaderUtil.java
- src/main/java/net/lingala/zip4j/io/inputstream/AesCipherInputStream.java
- src/main/java/net/lingala/zip4j/io/inputstream/ZipEntryInputStream.java
- src/main/java/net/lingala/zip4j/io/inputstream/ZipInputStream.java
- src/main/java/net/lingala/zip4j/io/outputstream/ZipOutputStream.java
- src/main/java/net/lingala/zip4j/model/ZipParameters.java
- src/main/java/net/lingala/zip4j/model/enums/AesVersion.java
- src/main/java/net/lingala/zip4j/model/enums/CompressionLevel.java
- src/main/java/net/lingala/zip4j/tasks/AbstractExtractFileTask.java
- src/main/java/net/lingala/zip4j/util/RawIO.java
- src/main/java/net/lingala/zip4j/util/Zip4jUtil.java
- src/test/java/net/lingala/zip4j/CreateZipFileIT.java
- src/test/java/net/lingala/zip4j/headers/HeaderReaderIT.java
- src/test/java/net/lingala/zip4j/io/inputstream/ZipInputStreamIT.java
- src/test/java/net/lingala/zip4j/io/outputstream/ZipOutputStreamIT.java
- src/test/java/net/lingala/zip4j/util/Zip4jUtilTest.java
- + src/test/resources/test-archives/file_name_size_is_0_in_local_file_header
- + src/test/resources/test-archives/invalid_aes_extra_data_record_length_in_header
- + src/test/resources/test-archives/null-aes-key-strength-in-aes-extra-data-record
- + src/test/resources/test-archives/unexpected-eof-when-reading-stream
Changes:
=====================================
.github/workflows/maven.yml
=====================================
@@ -0,0 +1,23 @@
+name: Verify Build
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout at v2
+ - name: Set up JDK 11
+ uses: actions/setup-java at v2
+ with:
+ java-version: '11'
+ distribution: 'temurin'
+ cache: maven
+ - name: Build with Maven
+ run: mvn -B clean verify --file pom.xml
=====================================
.travis.yml deleted
=====================================
@@ -1,11 +0,0 @@
-language: java
-
-before_script:
- - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash trigger-android-build.sh ${CIRCLE_CI_TOKEN} || travis_terminate 1; fi'
-
-script:
- - travis_wait 45 mvn clean verify
-
-cache:
- directories:
- - $HOME/.m2
=====================================
README.md
=====================================
@@ -1,7 +1,7 @@
[![javadoc](https://javadoc.io/badge2/net.lingala.zip4j/zip4j/javadoc.svg)](https://javadoc.io/doc/net.lingala.zip4j/zip4j)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.lingala.zip4j/zip4j/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.lingala.zip4j/zip4j)
-[![Build Status](https://travis-ci.com/srikanth-lingala/zip4j.svg?branch=master)](https://travis-ci.com/srikanth-lingala/zip4j)
+[![Build Status](https://github.com/srikanth-lingala/zip4j/actions/workflows/maven.yml/badge.svg)](https://github.com/srikanth-lingala/zip4j/actions/workflows/maven.yml)
[![Android Build Status](https://circleci.com/gh/srikanth-lingala/zip4j-android-test.svg?style=svg)](https://circleci.com/gh/srikanth-lingala/zip4j-android-test)
[![Known Vulnerabilities](https://snyk.io//test/github/srikanth-lingala/zip4j/badge.svg?targetFile=pom.xml)](https://snyk.io//test/github/srikanth-lingala/zip4j?targetFile=pom.xml)
@@ -71,7 +71,7 @@ Zip4j supports JDK 7 as well. In cases where the feature/class from JDK 8 is mis
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
- <version>2.9.0</version>
+ <version>2.10.0</version>
</dependency>
```
=====================================
pom.xml
=====================================
@@ -6,7 +6,7 @@
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
- <version>2.9.1-SNAPSHOT</version>
+ <version>2.10.0</version>
<name>Zip4j</name>
<description>Zip4j - A Java library for zip files and streams</description>
=====================================
src/main/java/net/lingala/zip4j/headers/HeaderReader.java
=====================================
@@ -19,6 +19,7 @@ package net.lingala.zip4j.headers;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.inputstream.NumberedSplitRandomAccessFile;
import net.lingala.zip4j.model.AESExtraDataRecord;
+import net.lingala.zip4j.model.AbstractFileHeader;
import net.lingala.zip4j.model.CentralDirectory;
import net.lingala.zip4j.model.DataDescriptor;
import net.lingala.zip4j.model.DigitalSignature;
@@ -193,7 +194,7 @@ public class HeaderReader {
String fileName = decodeStringWithCharset(fileNameBuff, fileHeader.isFileNameUTF8Encoded(), charset);
fileHeader.setFileName(fileName);
} else {
- fileHeader.setFileName(null);
+ throw new ZipException("Invalid entry name in file header");
}
fileHeader.setDirectory(isDirectory(fileHeader.getExternalFileAttributes(), fileHeader.getFileName()));
@@ -558,7 +559,7 @@ public class HeaderReader {
localFileHeader.setFileName(fileName);
localFileHeader.setDirectory(fileName.endsWith("/") || fileName.endsWith("\\"));
} else {
- localFileHeader.setFileName(null);
+ throw new ZipException("Invalid entry name in local file header");
}
readExtraDataRecords(inputStream, localFileHeader);
@@ -612,7 +613,7 @@ public class HeaderReader {
return dataDescriptor;
}
- private void readAesExtraDataRecord(FileHeader fileHeader, RawIO rawIO) throws ZipException {
+ private void readAesExtraDataRecord(AbstractFileHeader fileHeader, RawIO rawIO) throws ZipException {
if (fileHeader.getExtraDataRecords() == null || fileHeader.getExtraDataRecords().size() <= 0) {
return;
}
@@ -624,18 +625,6 @@ public class HeaderReader {
}
}
- private void readAesExtraDataRecord(LocalFileHeader localFileHeader, RawIO rawIO) throws ZipException {
- if (localFileHeader.getExtraDataRecords() == null || localFileHeader.getExtraDataRecords().size() <= 0) {
- return;
- }
-
- AESExtraDataRecord aesExtraDataRecord = readAesExtraDataRecord(localFileHeader.getExtraDataRecords(), rawIO);
- if (aesExtraDataRecord != null) {
- localFileHeader.setAesExtraDataRecord(aesExtraDataRecord);
- localFileHeader.setEncryptionMethod(EncryptionMethod.AES);
- }
- }
-
private AESExtraDataRecord readAesExtraDataRecord(List<ExtraDataRecord> extraDataRecords, RawIO rawIO)
throws ZipException {
@@ -650,7 +639,8 @@ public class HeaderReader {
if (extraDataRecord.getHeader() == HeaderSignature.AES_EXTRA_DATA_RECORD.getValue()) {
- if (extraDataRecord.getData() == null) {
+ byte[] aesExtraDataRecordBytes = extraDataRecord.getData();
+ if (aesExtraDataRecordBytes == null || aesExtraDataRecordBytes.length != 7) {
throw new ZipException("corrupt AES extra data records");
}
=====================================
src/main/java/net/lingala/zip4j/headers/HeaderUtil.java
=====================================
@@ -5,13 +5,11 @@ import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.util.InternalZipConstants;
-import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import static net.lingala.zip4j.util.InternalZipConstants.ZIP4J_DEFAULT_CHARSET;
-import static net.lingala.zip4j.util.InternalZipConstants.ZIP_STANDARD_CHARSET_NAME;
import static net.lingala.zip4j.util.Zip4jUtil.isStringNotNullAndNotEmpty;
public class HeaderUtil {
@@ -41,11 +39,7 @@ public class HeaderUtil {
return new String(data, InternalZipConstants.CHARSET_UTF_8);
}
- try {
- return new String(data, ZIP_STANDARD_CHARSET_NAME);
- } catch (UnsupportedEncodingException e) {
- return new String(data);
- }
+ return new String(data, ZIP4J_DEFAULT_CHARSET);
}
public static byte[] getBytesFromString(String string, Charset charset) {
=====================================
src/main/java/net/lingala/zip4j/io/inputstream/AesCipherInputStream.java
=====================================
@@ -158,6 +158,11 @@ class AesCipherInputStream extends CipherInputStream<AESDecrypter> {
}
AESExtraDataRecord aesExtraDataRecord = localFileHeader.getAesExtraDataRecord();
+
+ if (aesExtraDataRecord.getAesKeyStrength() == null) {
+ throw new IOException("Invalid aes key strength in aes extra data record");
+ }
+
byte[] saltBytes = new byte[aesExtraDataRecord.getAesKeyStrength().getSaltLength()];
readRaw(saltBytes);
return saltBytes;
=====================================
src/main/java/net/lingala/zip4j/io/inputstream/ZipEntryInputStream.java
=====================================
@@ -58,6 +58,10 @@ class ZipEntryInputStream extends InputStream {
int readLen = inputStream.read(b);
+ if (readLen == -1) {
+ throw new IOException("Unexpected EOF reached when trying to read stream");
+ }
+
if (readLen != b.length) {
readLen = readUntilBufferIsFull(b, readLen);
=====================================
src/main/java/net/lingala/zip4j/io/inputstream/ZipInputStream.java
=====================================
@@ -16,12 +16,10 @@
package net.lingala.zip4j.io.inputstream;
-import static net.lingala.zip4j.util.InternalZipConstants.MIN_BUFF_SIZE;
-import static net.lingala.zip4j.util.Zip4jUtil.getCompressionMethod;
-
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.headers.HeaderReader;
import net.lingala.zip4j.headers.HeaderSignature;
+import net.lingala.zip4j.model.AESExtraDataRecord;
import net.lingala.zip4j.model.DataDescriptor;
import net.lingala.zip4j.model.ExtraDataRecord;
import net.lingala.zip4j.model.FileHeader;
@@ -40,6 +38,9 @@ import java.nio.charset.Charset;
import java.util.List;
import java.util.zip.CRC32;
+import static net.lingala.zip4j.util.InternalZipConstants.MIN_BUFF_SIZE;
+import static net.lingala.zip4j.util.Zip4jUtil.getCompressionMethod;
+
public class ZipInputStream extends InputStream {
private PushbackInputStream inputStream;
@@ -262,7 +263,7 @@ public class ZipInputStream extends InputStream {
}
private DecompressedInputStream initializeDecompressorForThisEntry(CipherInputStream cipherInputStream,
- LocalFileHeader localFileHeader) {
+ LocalFileHeader localFileHeader) throws ZipException {
CompressionMethod compressionMethod = getCompressionMethod(localFileHeader);
if (compressionMethod == CompressionMethod.DEFLATE) {
@@ -335,7 +336,7 @@ public class ZipInputStream extends InputStream {
return entryName.endsWith("/") || entryName.endsWith("\\");
}
- private long getCompressedSize(LocalFileHeader localFileHeader) {
+ private long getCompressedSize(LocalFileHeader localFileHeader) throws ZipException {
if (getCompressionMethod(localFileHeader).equals(CompressionMethod.STORE)) {
return localFileHeader.getUncompressedSize();
}
@@ -347,14 +348,13 @@ public class ZipInputStream extends InputStream {
return localFileHeader.getCompressedSize() - getEncryptionHeaderSize(localFileHeader);
}
- private int getEncryptionHeaderSize(LocalFileHeader localFileHeader) {
+ private int getEncryptionHeaderSize(LocalFileHeader localFileHeader) throws ZipException {
if (!localFileHeader.isEncrypted()) {
return 0;
}
if (localFileHeader.getEncryptionMethod().equals(EncryptionMethod.AES)) {
- return InternalZipConstants.AES_AUTH_LENGTH + InternalZipConstants.AES_PASSWORD_VERIFIER_LENGTH
- + localFileHeader.getAesExtraDataRecord().getAesKeyStrength().getSaltLength();
+ return getAesEncryptionHeaderSize(localFileHeader.getAesExtraDataRecord());
} else if (localFileHeader.getEncryptionMethod().equals(EncryptionMethod.ZIP_STANDARD)) {
return InternalZipConstants.STD_DEC_HDR_SIZE;
} else {
@@ -377,6 +377,15 @@ public class ZipInputStream extends InputStream {
this.entryEOFReached = true;
}
+ private int getAesEncryptionHeaderSize(AESExtraDataRecord aesExtraDataRecord) throws ZipException {
+ if (aesExtraDataRecord == null || aesExtraDataRecord.getAesKeyStrength() == null) {
+ throw new ZipException("AesExtraDataRecord not found or invalid for Aes encrypted entry");
+ }
+
+ return InternalZipConstants.AES_AUTH_LENGTH + InternalZipConstants.AES_PASSWORD_VERIFIER_LENGTH
+ + aesExtraDataRecord.getAesKeyStrength().getSaltLength();
+ }
+
private boolean isEncryptionMethodZipStandard(LocalFileHeader localFileHeader) {
return localFileHeader.isEncrypted() && EncryptionMethod.ZIP_STANDARD.equals(localFileHeader.getEncryptionMethod());
}
=====================================
src/main/java/net/lingala/zip4j/io/outputstream/ZipOutputStream.java
=====================================
@@ -14,6 +14,7 @@ import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.util.InternalZipConstants;
import net.lingala.zip4j.util.RawIO;
+import net.lingala.zip4j.util.Zip4jUtil;
import java.io.IOException;
import java.io.OutputStream;
@@ -79,6 +80,7 @@ public class ZipOutputStream extends OutputStream {
clonedZipParameters.setWriteExtendedLocalFileHeader(false);
clonedZipParameters.setCompressionMethod(CompressionMethod.STORE);
clonedZipParameters.setEncryptFiles(false);
+ clonedZipParameters.setEntrySize(0);
}
initializeAndWriteFileHeader(clonedZipParameters);
@@ -226,6 +228,10 @@ public class ZipOutputStream extends OutputStream {
}
private void verifyZipParameters(ZipParameters zipParameters) {
+ if (Zip4jUtil.isStringNullOrEmpty(zipParameters.getFileNameInZip())) {
+ throw new IllegalArgumentException("fileNameInZip is null or empty");
+ }
+
if (zipParameters.getCompressionMethod() == CompressionMethod.STORE
&& zipParameters.getEntrySize() < 0
&& !isZipEntryDirectory(zipParameters.getFileNameInZip())
=====================================
src/main/java/net/lingala/zip4j/model/ZipParameters.java
=====================================
@@ -34,11 +34,11 @@ public class ZipParameters {
/**
* Add only the symbolic link itself, not the target file or its contents
*/
- INCLUDE_LINK_ONLY,
+ INCLUDE_LINK_ONLY,
/**
* Add only the target file and its contents, using the filename of the symbolic link
*/
- INCLUDE_LINKED_FILE_ONLY,
+ INCLUDE_LINKED_FILE_ONLY,
/**
* Add the symbolic link itself and the target file with its original filename and its contents
*/
@@ -72,7 +72,7 @@ public class ZipParameters {
* CompressionMethod.DEFLATE, CompressionLevel.NORMAL, EncryptionMethod.NONE,
* AesKeyStrength.KEY_STRENGTH_256, AesVerson.Two, SymbolicLinkAction.INCLUDE_LINKED_FILE_ONLY,
* readHiddenFiles is true, readHiddenFolders is true, includeRootInFolder is true,
- * writeExtendedLocalFileHeader is true, overrideExistingFilesInZip is true
+ * writeExtendedLocalFileHeader is true, overrideExistingFilesInZip is true
*/
public ZipParameters() {
}
@@ -113,7 +113,7 @@ public class ZipParameters {
return compressionMethod;
}
- /**
+ /**
* Set the ZIP compression method
* @param compressionMethod the ZIP compression method
*/
@@ -171,31 +171,31 @@ public void setEncryptFiles(boolean encryptFiles) {
/**
* Test if hidden files will be included during folder recursion
- *
+ *
* @return true if hidden files will be included when adding folders to the zip
*/
public boolean isReadHiddenFiles() {
return readHiddenFiles;
}
-
+
/**
* Indicate if hidden files will be included during folder recursion
- *
+ *
* @param readHiddenFiles if true, hidden files will be included when adding folders to the zip
*/
public void setReadHiddenFiles(boolean readHiddenFiles) {
this.readHiddenFiles = readHiddenFiles;
}
-
+
/**
* Test if hidden folders will be included during folder recursion
- *
+ *
* @return true if hidden folders will be included when adding folders to the zip
*/
public boolean isReadHiddenFolders() {
return readHiddenFolders;
}
-
+
/**
* Indicate if hidden folders will be included during folder recursion
* @param readHiddenFolders if true, hidden folders will be included when added folders to the zip
@@ -217,7 +217,7 @@ public void setEncryptFiles(boolean encryptFiles) {
}
/**
- * Set the key strength of the AES encryption key
+ * Set the key strength of the AES encryption key
* @param aesKeyStrength the key strength of the AES encryption key
*/
public void setAesKeyStrength(AesKeyStrength aesKeyStrength) {
@@ -279,10 +279,10 @@ public void setEncryptFiles(boolean encryptFiles) {
/**
* Set the filename that will be used to include a file into the ZIP file to a different name
* that given by the source filename added to the ZIP file. The filenameInZip must
- * adhere to the ZIP filename specification, including the use of forward slash '/' as the
- * directory separator, and it must also be a relative file. If the filenameInZip given is not null and
- * not empty, the value specified by setRootFolderNameInZip() will be ignored.
- *
+ * adhere to the ZIP filename specification, including the use of forward slash '/' as the
+ * directory separator, and it must also be a relative file. If the filenameInZip given is not null and
+ * not empty, the value specified by setRootFolderNameInZip() will be ignored.
+ *
* @param fileNameInZip the filename to set in the ZIP. Use null or an empty String to set the default behavior
*/
public void setFileNameInZip(String fileNameInZip) {
@@ -290,7 +290,7 @@ public void setEncryptFiles(boolean encryptFiles) {
}
/**
- * Get the last modified time to be used for files written to the ZIP
+ * Get the last modified time to be used for files written to the ZIP
* @return the last modified time in milliseconds since the epoch
*/
public long getLastModifiedFileTime() {
@@ -345,7 +345,7 @@ public void setEncryptFiles(boolean encryptFiles) {
/**
* Set the folder name that will be prepended to the filename in the ZIP. This value is ignored
* if setFileNameInZip() is specified with a non-null, non-empty string.
- *
+ *
* @param rootFolderNameInZip the name of the folder to be prepended to the filename
* in the ZIP archive
*/
=====================================
src/main/java/net/lingala/zip4j/model/enums/AesVersion.java
=====================================
@@ -1,16 +1,18 @@
package net.lingala.zip4j.model.enums;
+import net.lingala.zip4j.exception.ZipException;
+
/**
* Indicates the AES format used
*/
public enum AesVersion {
/**
- * Version 1 of the AES format
+ * Version 1 of the AES format
*/
ONE(1),
/**
- * Version 2 of the AES format
+ * Version 2 of the AES format
*/
TWO(2);
@@ -32,13 +34,13 @@ public enum AesVersion {
* @return the AESVersion instance for a given version
* @throws IllegalArgumentException if an unsupported version is given
*/
- public static AesVersion getFromVersionNumber(int versionNumber) {
+ public static AesVersion getFromVersionNumber(int versionNumber) throws ZipException {
for (AesVersion aesVersion : values()) {
if (aesVersion.versionNumber == versionNumber) {
return aesVersion;
}
}
- throw new IllegalArgumentException("Unsupported Aes version");
+ throw new ZipException("Unsupported Aes version");
}
}
=====================================
src/main/java/net/lingala/zip4j/model/enums/CompressionLevel.java
=====================================
@@ -6,6 +6,10 @@ package net.lingala.zip4j.model.enums;
*/
public enum CompressionLevel {
+ /**
+ * Level 0 - No compression
+ */
+ NO_COMPRESSION(0),
/**
* Level 1 Deflate compression. Fastest compression.
*/
@@ -43,7 +47,7 @@ public enum CompressionLevel {
*/
ULTRA(9);
- private int level;
+ private final int level;
CompressionLevel(int level) {
this.level = level;
=====================================
src/main/java/net/lingala/zip4j/tasks/AbstractExtractFileTask.java
=====================================
@@ -48,12 +48,7 @@ public abstract class AbstractExtractFileTask<T> extends AsyncZipTask<T> {
File outputFile = determineOutputFile(fileHeader, outputPath, newFileName);
progressMonitor.setFileName(outputFile.getAbsolutePath());
- // make sure no file is extracted outside of the target directory (a.k.a zip slip)
- String outputCanonicalPath = (new File(outputPath).getCanonicalPath()) + File.separator;
- if (!outputFile.getCanonicalPath().startsWith(outputCanonicalPath)) {
- throw new ZipException("illegal file name that breaks out of the target directory: "
- + fileHeader.getFileName());
- }
+ assertCanonicalPathsAreSame(outputFile, outputPath, fileHeader);
verifyNextEntry(zipInputStream, fileHeader);
@@ -73,6 +68,22 @@ public abstract class AbstractExtractFileTask<T> extends AsyncZipTask<T> {
UnzipUtil.applyFileAttributes(fileHeader, outputFile);
}
+ private void assertCanonicalPathsAreSame(File outputFile, String outputPath, FileHeader fileHeader)
+ throws IOException {
+
+ String outputFileCanonicalPath = outputFile.getCanonicalPath();
+ if (outputFile.isDirectory() && !outputFileCanonicalPath.endsWith(FILE_SEPARATOR)) {
+ outputFileCanonicalPath = outputFileCanonicalPath + FILE_SEPARATOR;
+ }
+
+ // make sure no file is extracted outside the target directory (a.k.a. zip slip)
+ String outputCanonicalPath = (new File(outputPath).getCanonicalPath()) + File.separator;
+ if (!outputFileCanonicalPath.startsWith(outputCanonicalPath)) {
+ throw new ZipException("illegal file name that breaks out of the target directory: "
+ + fileHeader.getFileName());
+ }
+ }
+
private boolean isSymbolicLink(FileHeader fileHeader) {
byte[] externalFileAttributes = fileHeader.getExternalFileAttributes();
=====================================
src/main/java/net/lingala/zip4j/util/RawIO.java
=====================================
@@ -56,7 +56,7 @@ public class RawIO {
if (array.length - pos < 8) {
resetBytes(longBuff);
}
- System.arraycopy(array, pos, longBuff, 0, array.length < 8 ? array.length - pos : 8);
+ System.arraycopy(array, pos, longBuff, 0, Math.min(array.length - pos, 8));
long temp = 0;
temp |= longBuff[7] & 0xff;
=====================================
src/main/java/net/lingala/zip4j/util/Zip4jUtil.java
=====================================
@@ -32,6 +32,10 @@ public class Zip4jUtil {
private static final long DOSTIME_BEFORE_1980 = (1 << 21) | (1 << 16);
private static final int MAX_RAW_READ_FULLY_RETRY_ATTEMPTS = 15;
+ public static boolean isStringNullOrEmpty(String str) {
+ return str == null || str.trim().length() == 0;
+ }
+
public static boolean isStringNotNullAndNotEmpty(String str) {
return str != null && str.trim().length() > 0;
}
@@ -112,13 +116,13 @@ public class Zip4jUtil {
}
}
- public static CompressionMethod getCompressionMethod(AbstractFileHeader localFileHeader) {
+ public static CompressionMethod getCompressionMethod(AbstractFileHeader localFileHeader) throws ZipException {
if (localFileHeader.getCompressionMethod() != CompressionMethod.AES_INTERNAL_ONLY) {
return localFileHeader.getCompressionMethod();
}
if (localFileHeader.getAesExtraDataRecord() == null) {
- throw new RuntimeException("AesExtraDataRecord not present in local header for aes encrypted data");
+ throw new ZipException("AesExtraDataRecord not present in local header for aes encrypted data");
}
return localFileHeader.getAesExtraDataRecord().getCompressionMethod();
@@ -128,6 +132,10 @@ public class Zip4jUtil {
int readLen = inputStream.read(bufferToReadInto);
+ if (readLen == -1) {
+ throw new IOException("Unexpected EOF reached when trying to read stream");
+ }
+
if (readLen != bufferToReadInto.length) {
readLen = readUntilBufferIsFull(inputStream, bufferToReadInto, readLen);
@@ -175,6 +183,13 @@ public class Zip4jUtil {
private static int readUntilBufferIsFull(InputStream inputStream, byte[] bufferToReadInto, int readLength)
throws IOException {
+ if (readLength < 0) {
+ throw new IOException("Invalid readLength");
+ }
+
+ if (readLength == 0) {
+ return 0;
+ }
int remainingLength = bufferToReadInto.length - readLength;
int loopReadLength = 0;
=====================================
src/test/java/net/lingala/zip4j/CreateZipFileIT.java
=====================================
@@ -521,6 +521,12 @@ public class CreateZipFileIT extends AbstractIT {
verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 3);
}
+ @Test
+ public void testCreateZipFileWithDeflateNoCompressionLevel() throws IOException {
+ createZipFileWithCompressionLevel(CompressionLevel.NO_COMPRESSION);
+ verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 3);
+ }
+
private void testAddSymlinkThrowsExceptionForMissingTarget(ZipParameters.SymbolicLinkAction symbolicLinkAction)
throws IOException {
File targetFile = Paths.get(temporaryFolder.getRoot().getAbsolutePath(), "foo").toFile();
=====================================
src/test/java/net/lingala/zip4j/headers/HeaderReaderIT.java
=====================================
@@ -117,17 +117,18 @@ public class HeaderReaderIT extends AbstractIT {
}
@Test
- public void testReadAllWithoutFileNameWritesNull() throws IOException {
+ public void testReadAllWithoutFileNameThrowsException() throws IOException {
ZipModel actualZipModel = generateZipModel(1);
actualZipModel.getCentralDirectory().getFileHeaders().get(0).setFileName(null);
File headersFile = writeZipHeaders(actualZipModel);
actualZipModel.setZipFile(headersFile);
- try(RandomAccessFile randomAccessFile = new RandomAccessFile(actualZipModel.getZipFile(),
+ try (RandomAccessFile randomAccessFile = new RandomAccessFile(actualZipModel.getZipFile(),
RandomAccessFileMode.READ.getValue())) {
- ZipModel readZipModel = headerReader.readAllHeaders(randomAccessFile, buildDefaultConfig());
- FileHeader fileHeader = readZipModel.getCentralDirectory().getFileHeaders().get(0);
- assertThat(fileHeader.getFileName()).isNull();
+ headerReader.readAllHeaders(randomAccessFile, HeaderReaderIT.this.buildDefaultConfig());
+ fail("Should throw an exception");
+ } catch (ZipException e) {
+ assertThat(e.getMessage()).isEqualTo("Invalid entry name in file header");
}
}
@@ -143,9 +144,9 @@ public class HeaderReaderIT extends AbstractIT {
}
@Test
- public void testReadAllWithoutUtf8FlagAndWithoutCharsetForJapaneseCharactersDoesNotMatch()
+ public void testReadAllWithoutUtf8FlagAndWithoutCharsetForJapaneseCharactersMatches()
throws IOException {
- testWithoutUtf8FileName("公ゃ的年社", "育ざどろめ", false, true, null);
+ testWithoutUtf8FileName("公ゃ的年社", "育ざどろめ", true, true, null);
}
@Test
=====================================
src/test/java/net/lingala/zip4j/io/inputstream/ZipInputStreamIT.java
=====================================
@@ -301,6 +301,42 @@ public class ZipInputStreamIT extends AbstractIT {
null, InternalZipConstants.BUFF_SIZE, false, 2);
}
+ @Test
+ public void testExtractZipFileWithNullAesExtraDataRecordThrowsException() throws IOException {
+ expectedException.expect(ZipException.class);
+ expectedException.expectMessage("corrupt AES extra data records");
+
+ extractZipFileWithInputStreams(TestUtils.getTestArchiveFromResources("null-aes-key-strength-in-aes-extra-data-record"),
+ null, InternalZipConstants.BUFF_SIZE, false, 1);
+ }
+
+ @Test
+ public void testExtractZipFileWithFileNameLength0ThrowsException() throws IOException {
+ expectedException.expect(IOException.class);
+ expectedException.expectMessage("Invalid entry name in local file header");
+
+ extractZipFileWithInputStreams(TestUtils.getTestArchiveFromResources("file_name_size_is_0_in_local_file_header"),
+ null, InternalZipConstants.BUFF_SIZE, false, 1);
+ }
+
+ @Test
+ public void testExtractZipFileWithInvalidAesExtraDataRecordThrowsException() throws IOException {
+ expectedException.expect(ZipException.class);
+ expectedException.expectMessage("corrupt AES extra data records");
+
+ extractZipFileWithInputStreams(TestUtils.getTestArchiveFromResources("invalid_aes_extra_data_record_length_in_header"),
+ null, InternalZipConstants.BUFF_SIZE, false, 1);
+ }
+
+ @Test
+ public void testExtractZipFileWhenUnexpectedEofReachedThrowsException() throws IOException {
+ expectedException.expect(IOException.class);
+ expectedException.expectMessage("Unexpected EOF reached when trying to read stream");
+
+ extractZipFileWithInputStreams(TestUtils.getTestArchiveFromResources("unexpected-eof-when-reading-stream"),
+ null, InternalZipConstants.BUFF_SIZE, false, 1);
+ }
+
private void extractZipFileWithInputStreams(File zipFile, char[] password) throws IOException {
extractZipFileWithInputStreams(zipFile, password, InternalZipConstants.BUFF_SIZE);
}
=====================================
src/test/java/net/lingala/zip4j/io/outputstream/ZipOutputStreamIT.java
=====================================
@@ -37,6 +37,7 @@ import static net.lingala.zip4j.util.FileUtils.isUnix;
import static net.lingala.zip4j.util.FileUtils.isWindows;
import static net.lingala.zip4j.util.InternalZipConstants.MIN_BUFF_SIZE;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
public class ZipOutputStreamIT extends AbstractIT {
@@ -253,6 +254,39 @@ public class ZipOutputStreamIT extends AbstractIT {
verifyZipFileByExtractingAllFiles(generatedZipFile, outputFolder, 2);
}
+
+ @Test
+ public void testPutNextEntryWithEmptyFileNameInZipParameters() throws IOException {
+ ZipParameters zParams = new ZipParameters();
+ zParams.setFileNameInZip("");
+
+ try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(generatedZipFile))) {
+ try {
+ zos.putNextEntry(zParams);
+ fail("Suppose to throw an exception");
+ } catch (Exception ex) {
+ assertThat(ex).isInstanceOf(IllegalArgumentException.class);
+ assertThat(ex).hasMessageContaining("fileNameInZip is null or empty");
+ }
+ }
+ }
+
+ @Test
+ public void testPutNextEntryWithNullFileNameInZipParameters() throws IOException {
+ ZipParameters zParams = new ZipParameters();
+ zParams.setFileNameInZip(null);
+
+ try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(generatedZipFile))) {
+ try {
+ zos.putNextEntry(zParams);
+ fail("Suppose to throw an exception");
+ } catch (Exception ex) {
+ assertThat(ex).isInstanceOf(IllegalArgumentException.class);
+ assertThat(ex).hasMessageContaining("fileNameInZip is null or empty");
+ }
+ }
+ }
+
private void testZipOutputStream(CompressionMethod compressionMethod, boolean encrypt,
EncryptionMethod encryptionMethod, AesKeyStrength aesKeyStrength,
AesVersion aesVersion)
=====================================
src/test/java/net/lingala/zip4j/util/Zip4jUtilTest.java
=====================================
@@ -147,7 +147,7 @@ public class Zip4jUtilTest {
}
@Test
- public void testGetCompressionMethodForNonAesReturnsAsIs() {
+ public void testGetCompressionMethodForNonAesReturnsAsIs() throws ZipException {
LocalFileHeader localFileHeader = new LocalFileHeader();
localFileHeader.setCompressionMethod(CompressionMethod.DEFLATE);
@@ -155,9 +155,9 @@ public class Zip4jUtilTest {
}
@Test
- public void testGetCompressionMethodForAesWhenAesExtraDataMissingThrowsException() {
+ public void testGetCompressionMethodForAesWhenAesExtraDataMissingThrowsException() throws ZipException {
expectedException.expectMessage("AesExtraDataRecord not present in local header for aes encrypted data");
- expectedException.expect(RuntimeException.class);
+ expectedException.expect(ZipException.class);
LocalFileHeader localFileHeader = new LocalFileHeader();
localFileHeader.setCompressionMethod(CompressionMethod.AES_INTERNAL_ONLY);
@@ -166,7 +166,7 @@ public class Zip4jUtilTest {
}
@Test
- public void testGetCompressionMethidForAesReturnsFromAesExtraDataRecord() {
+ public void testGetCompressionMethidForAesReturnsFromAesExtraDataRecord() throws ZipException {
AESExtraDataRecord aesExtraDataRecord = new AESExtraDataRecord();
aesExtraDataRecord.setCompressionMethod(CompressionMethod.STORE);
@@ -211,7 +211,7 @@ public class Zip4jUtilTest {
ControlledReadInputStream controlledReadInputStream = new ControlledReadInputStream(randomInputStream, 100);
expectedException.expect(IOException.class);
- expectedException.expectMessage("Cannot read fully into byte buffer");
+ expectedException.expectMessage("Unexpected EOF reached when trying to read stream");
assertThat(Zip4jUtil.readFully(controlledReadInputStream, b)).isEqualTo(-1);
}
@@ -306,4 +306,4 @@ public class Zip4jUtilTest {
RandomInputStream randomInputStream = new RandomInputStream(4096);
return new ControlledReadInputStream(randomInputStream, maxLengthToReadAtOnce);
}
-}
\ No newline at end of file
+}
=====================================
src/test/resources/test-archives/file_name_size_is_0_in_local_file_header
=====================================
Binary files /dev/null and b/src/test/resources/test-archives/file_name_size_is_0_in_local_file_header differ
=====================================
src/test/resources/test-archives/invalid_aes_extra_data_record_length_in_header
=====================================
Binary files /dev/null and b/src/test/resources/test-archives/invalid_aes_extra_data_record_length_in_header differ
=====================================
src/test/resources/test-archives/null-aes-key-strength-in-aes-extra-data-record
=====================================
Binary files /dev/null and b/src/test/resources/test-archives/null-aes-key-strength-in-aes-extra-data-record differ
=====================================
src/test/resources/test-archives/unexpected-eof-when-reading-stream
=====================================
Binary files /dev/null and b/src/test/resources/test-archives/unexpected-eof-when-reading-stream differ
View it on GitLab: https://salsa.debian.org/java-team/zip4j/-/commit/ac1a59b66a520b33f37e05b6fd5c56f6bb1e47be
--
View it on GitLab: https://salsa.debian.org/java-team/zip4j/-/commit/ac1a59b66a520b33f37e05b6fd5c56f6bb1e47be
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20220401/0cc17d77/attachment.htm>
More information about the pkg-java-commits
mailing list