From 6594a2d66f7f060dafcbbf094dd60676db19a842 Mon Sep 17 00:00:00 2001
From: Stefan Bodewig <bodewig@apache.org>
Date: Sat, 10 Jul 2021 11:10:12 +0200
Subject: [PATCH] port some fixes from Commons Compress

---
 .../org/apache/tools/tar/TarInputStream.java  |  7 +++++--
 .../org/apache/tools/zip/AsiExtraField.java   | 12 +++++++----
 src/main/org/apache/tools/zip/ZipFile.java    | 20 ++++++++++++++++++-
 3 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/src/main/org/apache/tools/tar/TarInputStream.java b/src/main/org/apache/tools/tar/TarInputStream.java
index 0477d5c..71e4cc0 100644
--- a/src/main/org/apache/tools/tar/TarInputStream.java
+++ b/src/main/org/apache/tools/tar/TarInputStream.java
@@ -436,11 +436,13 @@ public class TarInputStream extends FilterInputStream {
                             String keyword = coll.toString("UTF-8");
                             // Get rest of entry
                             final int restLen = len - read;
-                            byte[] rest = new byte[restLen];
+                            ByteArrayOutputStream bos = new ByteArrayOutputStream();
                             int got = 0;
                             while (got < restLen && (ch = i.read()) != -1) {
-                                rest[got++] = (byte) ch;
+                                bos.write((byte) ch);
+                                got++;
                             }
+                            bos.close();
                             if (got != restLen) {
                                 throw new IOException("Failed to read "
                                                       + "Paxheader. Expected "
@@ -448,6 +450,7 @@ public class TarInputStream extends FilterInputStream {
                                                       + " bytes, read "
                                                       + got);
                             }
+                            byte[] rest = bos.toByteArray();
                             // Drop trailing NL
                             String value = new String(rest, 0,
                                                       restLen - 1, StandardCharsets.UTF_8);
diff --git a/src/main/org/apache/tools/zip/AsiExtraField.java b/src/main/org/apache/tools/zip/AsiExtraField.java
index 8afddb5..fdd81c6 100644
--- a/src/main/org/apache/tools/zip/AsiExtraField.java
+++ b/src/main/org/apache/tools/zip/AsiExtraField.java
@@ -307,14 +307,18 @@ public class AsiExtraField implements ZipExtraField, UnixStat, Cloneable {
 
         int newMode = ZipShort.getValue(tmp, 0);
         // CheckStyle:MagicNumber OFF
-        byte[] linkArray = new byte[(int) ZipLong.getValue(tmp, 2)];
+        final int linkArrayLength = (int) ZipLong.getValue(tmp, 2);
+        if (linkArrayLength < 0 || linkArrayLength > tmp.length - 10) {
+            throw new ZipException("Bad symbolic link name length " + linkArrayLength
+                + " in ASI extra field");
+        }
         uid = ZipShort.getValue(tmp, 6);
         gid = ZipShort.getValue(tmp, 8);
-
-        if (linkArray.length == 0) {
+        if (linkArrayLength == 0) {
             link = "";
         } else {
-            System.arraycopy(tmp, 10, linkArray, 0, linkArray.length);
+            final byte[] linkArray = new byte[linkArrayLength];
+            System.arraycopy(tmp, 10, linkArray, 0, linkArrayLength);
             link = new String(linkArray); // Uses default charset - see class Javadoc
         }
         // CheckStyle:MagicNumber ON
diff --git a/src/main/org/apache/tools/zip/ZipFile.java b/src/main/org/apache/tools/zip/ZipFile.java
index dfb6bcf..8806ae7 100644
--- a/src/main/org/apache/tools/zip/ZipFile.java
+++ b/src/main/org/apache/tools/zip/ZipFile.java
@@ -541,6 +541,9 @@ public class ZipFile implements Closeable {
         ze.setExternalAttributes(ZipLong.getValue(CFH_BUF, off));
         off += WORD;
 
+        if (archive.length() - archive.getFilePointer() < fileNameLen) {
+            throw new EOFException();
+        }
         final byte[] fileName = new byte[fileNameLen];
         archive.readFully(fileName);
         ze.setName(entryEncoding.decode(fileName), fileName);
@@ -550,12 +553,18 @@ public class ZipFile implements Closeable {
         // data offset will be filled later
         entries.add(ze);
 
+        if (archive.length() - archive.getFilePointer() < extraLen) {
+            throw new EOFException();
+        }
         final byte[] cdExtraData = new byte[extraLen];
         archive.readFully(cdExtraData);
         ze.setCentralDirectoryExtra(cdExtraData);
 
         setSizesAndOffsetFromZip64Extra(ze, offset, diskStart);
 
+        if (archive.length() - archive.getFilePointer() < commentLen) {
+            throw new EOFException();
+        }
         final byte[] comment = new byte[commentLen];
         archive.readFully(comment);
         ze.setComment(entryEncoding.decode(comment));
@@ -881,9 +890,18 @@ public class ZipFile implements Closeable {
                 }
                 lenToSkip -= skipped;
             }
+            if (archive.length() - archive.getFilePointer() < extraFieldLen) {
+                throw new EOFException();
+            }
             final byte[] localExtraData = new byte[extraFieldLen];
             archive.readFully(localExtraData);
-            ze.setExtra(localExtraData);
+            try {
+                ze.setExtra(localExtraData);
+            } catch (RuntimeException ex) {
+                final ZipException z = new ZipException("Invalid extra data in entry " + ze.getName());
+                z.initCause(ex);
+                throw z;
+            }
             offsetEntry.dataOffset = offset + LFH_OFFSET_FOR_FILENAME_LENGTH
                 + SHORT + SHORT + fileNameLen + extraFieldLen;
 
-- 
2.27.0

