[Git][java-team/zip4j][master] 6 commits: New upstream version 2.10.0

Andrius Merkys (@merkys) gitlab at salsa.debian.org
Fri Apr 1 10:21:45 BST 2022



Andrius Merkys pushed to branch master at Debian Java Maintainers / zip4j


Commits:
ac1a59b6 by Andrius Merkys at 2022-04-01T04:44:06-04:00
New upstream version 2.10.0
- - - - -
eaa3f045 by Andrius Merkys at 2022-04-01T04:44:19-04:00
Update upstream source from tag 'upstream/2.10.0'

Update to upstream version '2.10.0'
with Debian dir b5ef5b562f283cd80872bd8d2b4b2757a8121feb
- - - - -
e5667fe3 by Andrius Merkys at 2022-04-01T04:47:41-04:00
Bump copyright years.

- - - - -
0fab5cd1 by Andrius Merkys at 2022-04-01T04:47:58-04:00
Set upstream metadata fields: Bug-Database, Bug-Submit, Repository, Repository-Browse.

Changes-By: lintian-brush
Fixes: lintian: upstream-metadata-file-is-missing
See-also: https://lintian.debian.org/tags/upstream-metadata-file-is-missing.html
Fixes: lintian: upstream-metadata-missing-bug-tracking
See-also: https://lintian.debian.org/tags/upstream-metadata-missing-bug-tracking.html
Fixes: lintian: upstream-metadata-missing-repository
See-also: https://lintian.debian.org/tags/upstream-metadata-missing-repository.html

- - - - -
6a452c13 by Andrius Merkys at 2022-04-01T04:47:58-04:00
Update standards version to 4.6.0, no changes needed.

Changes-By: lintian-brush
Fixes: lintian: out-of-date-standards-version
See-also: https://lintian.debian.org/tags/out-of-date-standards-version.html

- - - - -
ea6f8fbb by Andrius Merkys at 2022-04-01T04:49:11-04:00
Update changelog for 2.10.0-1 release

- - - - -


29 changed files:

- + .github/workflows/maven.yml
- − .travis.yml
- README.md
- debian/changelog
- debian/control
- debian/copyright
- + debian/upstream/metadata
- 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>
 ```
 


=====================================
debian/changelog
=====================================
@@ -1,3 +1,13 @@
+zip4j (2.10.0-1) unstable; urgency=medium
+
+  * New upstream version 2.10.0
+  * Bump copyright years.
+  * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository,
+    Repository-Browse.
+  * Update standards version to 4.6.0, no changes needed.
+
+ -- Andrius Merkys <merkys at debian.org>  Fri, 01 Apr 2022 04:48:55 -0400
+
 zip4j (2.9.1-1) unstable; urgency=medium
 
   * New upstream version 2.9.1


=====================================
debian/control
=====================================
@@ -9,7 +9,7 @@ Build-Depends:
  default-jdk,
  libmaven-bundle-plugin-java,
  maven-debian-helper (>= 2.1),
-Standards-Version: 4.5.0
+Standards-Version: 4.6.0
 Vcs-Git: https://salsa.debian.org/java-team/zip4j.git
 Vcs-Browser: https://salsa.debian.org/java-team/zip4j
 Homepage: http://www.lingala.net/zip4j


=====================================
debian/copyright
=====================================
@@ -3,11 +3,11 @@ Upstream-Name: zip4j
 Source: https://github.com/srikanth-lingala/zip4j/releases
 
 Files: *
-Copyright: 2019-2021, Srikanth Reddy Lingala <srikanth.mailbox at gmail.com>
+Copyright: 2019-2022, Srikanth Reddy Lingala <srikanth.mailbox at gmail.com>
 License: Apache-2.0
 
 Files: debian/*
-Copyright: 2019-2021, Andrius Merkys <merkys at debian.org>
+Copyright: 2019-2022, Andrius Merkys <merkys at debian.org>
 License: Apache-2.0
 
 License: Apache-2.0


=====================================
debian/upstream/metadata
=====================================
@@ -0,0 +1,5 @@
+---
+Bug-Database: https://github.com/srikanth-lingala/zip4j/issues
+Bug-Submit: https://github.com/srikanth-lingala/zip4j/issues/new
+Repository: https://github.com/srikanth-lingala/zip4j.git
+Repository-Browse: https://github.com/srikanth-lingala/zip4j


=====================================
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/-/compare/55743ecce7abf68b577ae9a6eeade13acde84e0e...ea6f8fbb67fab198343b3115bb259b1077a4e1fa

-- 
View it on GitLab: https://salsa.debian.org/java-team/zip4j/-/compare/55743ecce7abf68b577ae9a6eeade13acde84e0e...ea6f8fbb67fab198343b3115bb259b1077a4e1fa
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/3a9e0463/attachment.htm>


More information about the pkg-java-commits mailing list