You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2021/06/06 05:42:50 UTC

[commons-compress] 01/01: turn RuntimeExceptions into IOExceptions

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

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

commit 6cb3167e9bdc92b96eed309f938fa1ec76c19444
Author: Stefan Bodewig <bo...@apache.org>
AuthorDate: Sun Jun 6 07:36:08 2021 +0200

    turn RuntimeExceptions into IOExceptions
---
 .../commons/compress/UnhandledInputException.java  | 59 ++++++++++++++++++++++
 .../compress/archivers/sevenz/SevenZFile.java      | 19 ++++++-
 .../commons/compress/archivers/tar/TarFile.java    | 13 +++++
 .../commons/compress/archivers/zip/ZipFile.java    | 14 ++++-
 4 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/apache/commons/compress/UnhandledInputException.java b/src/main/java/org/apache/commons/compress/UnhandledInputException.java
new file mode 100644
index 0000000..920c538
--- /dev/null
+++ b/src/main/java/org/apache/commons/compress/UnhandledInputException.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.commons.compress;
+
+import java.io.IOException;
+
+/**
+ * Thrown if reading from an archive or compressed stream results in a RuntimeException.
+ *
+ * <p>Usually this means the input has been corrupt in a way Compress'
+ * code didn't detect by itself. If the input is not corrupt then
+ * you've found a bug in Compress and we ask you to report it.</p>
+ *
+ * @since 1.21
+ */
+public class UnhandledInputException extends IOException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Wraps an unhandled RuntimeException for an input of unknown name.
+     */
+    public UnhandledInputException(final RuntimeException ex) {
+        this(ex, null);
+    }
+
+    /**
+     * Wraps an unhandled RuntimeException for an input with a known name.
+     *
+     * @param ex the unhandled excetion
+     * @param inputName name of the input
+     */
+    public UnhandledInputException(final RuntimeException ex, final String inputName) {
+        super(buildMessage(inputName), ex);
+    }
+
+    private static String buildMessage(final String name) {
+        return "Either the input"
+            + (name == null ? "" : " " + name)
+            + " is corrupt or you have found a bug in Apache Commons Compress. Please report it at"
+            + " https://issues.apache.org/jira/browse/COMPRESS if you think this is a bug.";
+    }
+}
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 f4bec6c..351a858 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
@@ -45,6 +45,7 @@ import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.zip.CRC32;
 
+import org.apache.commons.compress.UnhandledInputException;
 import org.apache.commons.compress.utils.BoundedInputStream;
 import org.apache.commons.compress.utils.ByteUtils;
 import org.apache.commons.compress.utils.CRC32VerifyingInputStream;
@@ -346,6 +347,8 @@ public class SevenZFile implements Closeable {
                 this.password = null;
             }
             succeeded = true;
+        } catch (RuntimeException ex) {
+            throw new UnhandledInputException(ex, fileName);
         } finally {
             if (!succeeded && closeOnError) {
                 this.channel.close();
@@ -410,7 +413,11 @@ public class SevenZFile implements Closeable {
         if (entry.getName() == null && options.getUseDefaultNameForUnnamedEntries()) {
             entry.setName(getDefaultName());
         }
-        buildDecodingStream(currentEntryIndex, false);
+        try {
+            buildDecodingStream(currentEntryIndex, false);
+        } catch (RuntimeException ex) {
+            throw new UnhandledInputException(ex);
+        }
         uncompressedBytesReadFromCurrentEntry = compressedBytesReadFromCurrentEntry = 0;
         return entry;
     }
@@ -510,7 +517,7 @@ public class SevenZFile implements Closeable {
                     if (result.packSizes.length > 0 && result.files.length > 0) {
                         return result;
                     }
-                } catch (final Exception ignore) {
+                } catch (Exception ignore) {
                     // Wrong guess...
                 }
             }
@@ -1899,11 +1906,15 @@ public class SevenZFile implements Closeable {
      *             if an I/O error has occurred
      */
     public int read() throws IOException {
+        try {
         final int b = getCurrentStream().read();
         if (b >= 0) {
             uncompressedBytesReadFromCurrentEntry++;
         }
         return b;
+        } catch (RuntimeException ex) {
+            throw new UnhandledInputException(ex, fileName);
+        }
     }
 
     private InputStream getCurrentStream() throws IOException {
@@ -1981,6 +1992,7 @@ public class SevenZFile implements Closeable {
      *             if an I/O error has occurred
      */
     public int read(final byte[] b, final int off, final int len) throws IOException {
+        try {
         if (len == 0) {
             return 0;
         }
@@ -1989,6 +2001,9 @@ public class SevenZFile implements Closeable {
             uncompressedBytesReadFromCurrentEntry += cnt;
         }
         return cnt;
+        } catch (RuntimeException ex) {
+            throw new UnhandledInputException(ex, fileName);
+        }
     }
 
     /**
diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/TarFile.java b/src/main/java/org/apache/commons/compress/archivers/tar/TarFile.java
index e79d390..d1822e1 100644
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarFile.java
@@ -32,6 +32,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.compress.UnhandledInputException;
 import org.apache.commons.compress.archivers.zip.ZipEncoding;
 import org.apache.commons.compress.archivers.zip.ZipEncodingHelper;
 import org.apache.commons.compress.utils.ArchiveUtils;
@@ -239,6 +240,14 @@ public class TarFile implements Closeable {
             return null;
         }
 
+        try {
+            return getNextTarEntryInternal();
+        } catch (RuntimeException ex) {
+            throw new UnhandledInputException(ex);
+        }
+    }
+
+    private TarArchiveEntry getNextTarEntryInternal() throws IOException {
         if (currEntry != null) {
             // Skip to the end of the entry
             repositionForwardTo(currEntry.getDataOffset() + currEntry.getSize());
@@ -678,11 +687,15 @@ public class TarFile implements Closeable {
             }
 
             final int totalRead;
+            try {
             if (entry.isSparse()) {
                 totalRead = readSparse(entryOffset, buf, buf.limit());
             } else {
                 totalRead = readArchive(pos, buf);
             }
+            } catch (RuntimeException ex) {
+                throw new UnhandledInputException(ex);
+            }
 
             if (totalRead == -1) {
                 if (buf.array().length > 0) {
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 8792563..cd1b01a 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
@@ -42,6 +42,7 @@ import java.util.Map;
 import java.util.zip.Inflater;
 import java.util.zip.ZipException;
 
+import org.apache.commons.compress.UnhandledInputException;
 import org.apache.commons.compress.archivers.EntryStreamOffsets;
 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
 import org.apache.commons.compress.compressors.deflate64.Deflate64CompressorInputStream;
@@ -376,6 +377,8 @@ public class ZipFile implements Closeable {
             }
             fillNameMap();
             success = true;
+        } catch (RuntimeException ex) {
+            throw new UnhandledInputException(ex, archiveName);
         } catch (final IOException e) {
             throw new IOException("Error on ZipFile " + archiveName, e);
         } finally {
@@ -564,7 +567,16 @@ public class ZipFile implements Closeable {
         if (!(ze instanceof Entry)) {
             return null;
         }
-        // cast validity is checked just above
+        try {
+            // cast validity is checked just above
+            return getInputStreamInternal((Entry) ze);
+        } catch (RuntimeException ex) {
+            throw new UnhandledInputException(ex);
+        }
+    }
+
+    private InputStream getInputStreamInternal(final Entry ze)
+        throws IOException {
         ZipUtil.checkRequestedFeatures(ze);
         final long start = getDataOffset(ze);