This is an automated email from the ASF dual-hosted git repository.

bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git


The following commit(s) were added to refs/heads/master by this push:
     new 5c5f8a8  COMPRESS-569 ensure sizes read for archive entries are 
non-negative
5c5f8a8 is described below

commit 5c5f8a89e91b95c0ba984549b5804289f55b8200
Author: Stefan Bodewig <bode...@apache.org>
AuthorDate: Sat Mar 6 20:32:00 2021 +0100

    COMPRESS-569 ensure sizes read for archive entries are non-negative
---
 src/changes/changes.xml                            |  7 +++++++
 .../compress/archivers/ar/ArArchiveEntry.java      |  3 +++
 .../archivers/ar/ArArchiveInputStream.java         |  4 ++++
 .../compress/archivers/sevenz/SevenZFile.java      |  3 +++
 .../compress/archivers/tar/TarArchiveEntry.java    |  3 +++
 .../commons/compress/archivers/zip/ZipFile.java    | 24 ++++++++++++++++++----
 6 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 86bd225..06b3cff 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -317,6 +317,13 @@ The <action> type attribute can be add,update,fix,remove.
       <action type="update" due-to="Dependabot" dev="ggregory">
         Bump mockito-core from 1.10.19 to 3.8.0, #161, #170.
       </action>
+      <action issue="COMPRESS-569" type="fix" date="2021-03-06">
+        Checked the sizes read for archive entries and reject archives
+        as broken with negative entry sizes.
+
+        Fixes an infinite loop in the new TarFile class but affects
+        several formats.
+      </action>
     </release>
     <release version="1.20" date="2020-02-08"
              description="Release 1.20 (Java 7)">
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveEntry.java 
b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveEntry.java
index ea0e753..e5eeab4 100644
--- a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveEntry.java
+++ b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveEntry.java
@@ -104,6 +104,9 @@ public class ArArchiveEntry implements ArchiveEntry {
     public ArArchiveEntry(final String name, final long length, final int 
userId, final int groupId,
                           final int mode, final long lastModified) {
         this.name = name;
+        if (length < 0) {
+            throw new IllegalArgumentException("length must not be negative");
+        }
         this.length = length;
         this.userId = userId;
         this.groupId = groupId;
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
 
b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
index c1b46de..b696555 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
@@ -171,6 +171,10 @@ public class ArArchiveInputStream extends 
ArchiveInputStream {
             entryOffset += nameLen;
         }
 
+        if (len < 0) {
+            throw new IOException("broken archive, entry with negative size");
+        }
+
         currentEntry = new ArArchiveEntry(temp, len,
                                           asInt(metaData, USER_ID_OFFSET, 
USER_ID_LEN, true),
                                           asInt(metaData, GROUP_ID_OFFSET, 
GROUP_ID_LEN, true),
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java 
b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
index 5c34386..ba6e719 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
@@ -1096,6 +1096,9 @@ public class SevenZFile implements Closeable {
                 
entryAtIndex.setHasCrc(archive.subStreamsInfo.hasCrc.get(nonEmptyFileCounter));
                 
entryAtIndex.setCrcValue(archive.subStreamsInfo.crcs[nonEmptyFileCounter]);
                 
entryAtIndex.setSize(archive.subStreamsInfo.unpackSizes[nonEmptyFileCounter]);
+                if (entryAtIndex.getSize() < 0) {
+                    throw new IOException("broken archive, entry with negative 
size");
+                }
                 ++nonEmptyFileCounter;
             } else {
                 entryAtIndex.setDirectory(isEmptyFile == null || 
!isEmptyFile.get(emptyFileCounter));
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java 
b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
index 2e81a91..7522ad9 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
@@ -1538,6 +1538,9 @@ public class TarArchiveEntry implements ArchiveEntry, 
TarConstants, EntryStreamO
         groupId = (int) parseOctalOrBinary(header, offset, GIDLEN, lenient);
         offset += GIDLEN;
         size = TarUtils.parseOctalOrBinary(header, offset, SIZELEN);
+        if (size < 0) {
+            throw new IOException("broken archive, entry with negative size");
+        }
         offset += SIZELEN;
         modTime = parseOctalOrBinary(header, offset, MODTIMELEN, lenient);
         offset += MODTIMELEN;
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java 
b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
index c8e366b..9adb8b1 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
@@ -775,10 +775,18 @@ public class ZipFile implements Closeable {
         ze.setCrc(ZipLong.getValue(cfhBuf, off));
         off += WORD;
 
-        ze.setCompressedSize(ZipLong.getValue(cfhBuf, off));
+        long size = ZipLong.getValue(cfhBuf, off);
+        if (size < 0) {
+            throw new IOException("broken archive, entry with negative 
compressed size");
+        }
+        ze.setCompressedSize(size);
         off += WORD;
 
-        ze.setSize(ZipLong.getValue(cfhBuf, off));
+        size = ZipLong.getValue(cfhBuf, off);
+        if (size < 0) {
+            throw new IOException("broken archive, entry with negative size");
+        }
+        ze.setSize(size);
         off += WORD;
 
         final int fileNameLen = ZipShort.getValue(cfhBuf, off);
@@ -858,13 +866,21 @@ public class ZipFile implements Closeable {
                                             hasDiskStart);
 
             if (hasUncompressedSize) {
-                ze.setSize(z64.getSize().getLongValue());
+                final long size = z64.getSize().getLongValue();
+                if (size < 0) {
+                    throw new IOException("broken archive, entry with negative 
size");
+                }
+                ze.setSize(size);
             } else if (hasCompressedSize) {
                 z64.setSize(new ZipEightByteInteger(ze.getSize()));
             }
 
             if (hasCompressedSize) {
-                ze.setCompressedSize(z64.getCompressedSize().getLongValue());
+                final long size = z64.getCompressedSize().getLongValue();
+                if (size < 0) {
+                    throw new IOException("broken archive, entry with negative 
compressed size");
+                }
+                ze.setCompressedSize(size);
             } else if (hasUncompressedSize) {
                 z64.setCompressedSize(new 
ZipEightByteInteger(ze.getCompressedSize()));
             }

Reply via email to