Index: src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java	(revision 7a8f3c379fdb17fc57484123a5a81b4aeb4cb234)
+++ src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java	(date 1523485337000)
@@ -19,6 +19,9 @@
 
 package org.apache.commons.compress.archivers.zip;
 
+import org.apache.commons.compress.utils.CountingInputStream;
+import org.apache.commons.compress.utils.InputStreamStatistics;
+
 import java.io.IOException;
 import java.io.InputStream;
 
@@ -34,7 +37,7 @@
  * @author Emmanuel Bourg
  * @since 1.7
  */
-class ExplodingInputStream extends InputStream {
+class ExplodingInputStream extends InputStream implements InputStreamStatistics {
 
     /** The underlying stream containing the compressed data */
     private final InputStream in;
@@ -62,6 +65,8 @@
     /** Output buffer holding the decompressed data */
     private final CircularBuffer buffer = new CircularBuffer(32 * 1024);
 
+    private long uncompressedCount = 0;
+
     /**
      * Create a new stream decompressing the content of the specified stream
      * using the explode algorithm.
@@ -107,7 +112,21 @@
             fillBuffer();
         }
 
-        return buffer.get();
+        final int ret = buffer.get();
+        if (ret > -1) {
+            uncompressedCount++;
+        }
+        return ret;
+    }
+
+    @Override
+    public long getCompressedCount() {
+        return bits.getBytesRead();
+    }
+
+    @Override
+    public long getUncompressedCount() {
+        return uncompressedCount;
     }
 
     /**
Index: src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java	(revision 7a8f3c379fdb17fc57484123a5a81b4aeb4cb234)
+++ src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java	(date 1523564103000)
@@ -32,14 +32,15 @@
 import org.apache.commons.compress.compressors.CompressorInputStream;
 import org.apache.commons.compress.utils.BitInputStream;
 import org.apache.commons.compress.utils.CloseShieldFilterInputStream;
+import org.apache.commons.compress.utils.InputStreamStatistics;
 
 /**
  * An input stream that decompresses from the BZip2 format to be read as any other stream.
  *
  * @NotThreadSafe
  */
-public class BZip2CompressorInputStream extends CompressorInputStream implements
-                                                                          BZip2Constants {
+public class BZip2CompressorInputStream extends CompressorInputStream
+implements BZip2Constants, InputStreamStatistics {
 
     /**
      * Index of the last char in the block, so the block size == last + 1.
@@ -181,6 +182,16 @@
         return (destOffs == offs) ? -1 : (destOffs - offs);
     }
 
+    @Override
+    public long getCompressedCount() {
+        return bin.getBytesRead();
+    }
+
+    @Override
+    public long getUncompressedCount() {
+        return getBytesRead();
+    }
+
     private void makeMaps() {
         final boolean[] inUse = this.data.inUse;
         final byte[] seqToUnseq = this.data.seqToUnseq;
Index: src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java	(revision 7a8f3c379fdb17fc57484123a5a81b4aeb4cb234)
+++ src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java	(date 1523702606000)
@@ -37,6 +37,7 @@
 import org.apache.commons.compress.compressors.deflate64.Deflate64CompressorInputStream;
 import org.apache.commons.compress.utils.ArchiveUtils;
 import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.compress.utils.InputStreamStatistics;
 
 import static org.apache.commons.compress.archivers.zip.ZipConstants.DWORD;
 import static org.apache.commons.compress.archivers.zip.ZipConstants.SHORT;
@@ -75,7 +76,7 @@
  * @see ZipFile
  * @NotThreadSafe
  */
-public class ZipArchiveInputStream extends ArchiveInputStream {
+public class ZipArchiveInputStream extends ArchiveInputStream implements InputStreamStatistics {
 
     /** The zip encoding to use for filenames and the file comment. */
     private final ZipEncoding zipEncoding;
@@ -114,6 +115,9 @@
     /** Whether the stream will try to read STORED entries that use a data descriptor. */
     private boolean allowStoredEntriesWithDataDescriptor = false;
 
+    /** Count decompressed bytes for current entry */
+    private long uncompressedCount = 0;
+
     private static final int LFH_LEN = 30;
     /*
       local file header signature     WORD
@@ -218,6 +222,8 @@
     }
 
     public ZipArchiveEntry getNextZipEntry() throws IOException {
+        uncompressedCount = 0;
+
         boolean firstEntry = true;
         if (closed || hitCentralDirectory) {
             return null;
@@ -460,11 +466,23 @@
 
         if (read >= 0) {
             current.crc.update(buffer, offset, read);
+            uncompressedCount += read;
         }
 
         return read;
     }
 
+    @Override
+    public long getCompressedCount() {
+        final long infBytes = inf.getBytesRead();
+        return (infBytes > 0) ? infBytes : current.bytesReadFromStream;
+    }
+
+    @Override
+    public long getUncompressedCount() {
+        return uncompressedCount;
+    }
+
     /**
      * Implementation of read for STORED entries.
      */
Index: src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java	(revision 7a8f3c379fdb17fc57484123a5a81b4aeb4cb234)
+++ src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java	(date 1523481720000)
@@ -25,6 +25,7 @@
 import org.apache.commons.compress.MemoryLimitException;
 import org.apache.commons.compress.compressors.CompressorInputStream;
 import org.apache.commons.compress.utils.BitInputStream;
+import org.apache.commons.compress.utils.InputStreamStatistics;
 
 /**
  * <p>Generic LZW implementation. It is used internally for
@@ -34,7 +35,7 @@
  * @NotThreadSafe
  * @since 1.10
  */
-public abstract class LZWInputStream extends CompressorInputStream {
+public abstract class LZWInputStream extends CompressorInputStream implements InputStreamStatistics {
     protected static final int DEFAULT_CODE_SIZE = 9;
     protected static final int UNUSED_PREFIX = -1;
 
@@ -87,6 +88,14 @@
         return bytesRead;
     }
 
+    public long getCompressedCount() {
+        return in.getBytesRead();
+    }
+
+    public long getUncompressedCount() {
+        return getBytesRead();
+    }
+
     /**
      * Read the next code and expand it.
      * @return the expanded next code
Index: src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java	(revision 7a8f3c379fdb17fc57484123a5a81b4aeb4cb234)
+++ src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java	(date 1523481720000)
@@ -40,7 +40,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.zip.Inflater;
-import java.util.zip.InflaterInputStream;
 import java.util.zip.ZipException;
 
 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
Index: src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java	(revision 7a8f3c379fdb17fc57484123a5a81b4aeb4cb234)
+++ src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java	(date 1523731092000)
@@ -27,9 +27,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
+import java.util.*;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipException;
 
@@ -42,6 +40,7 @@
 import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.apache.commons.compress.archivers.zip.ZipMethod;
 import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.compress.utils.InputStreamStatistics;
 import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
 import org.junit.Assert;
 import org.junit.Test;
@@ -598,4 +597,56 @@
             rmdir(tmp[0]);
         }
     }
+
+    @Test
+    public void testInputStreamStatistics() throws IOException, ArchiveException {
+        final File input = getFile("zipbomb.xlsx");
+
+        final Map<String,List<List<Long>>> map = new HashMap<>();
+
+        // stream access
+        try (final FileInputStream fis = new FileInputStream(input);
+            final ArchiveInputStream in = new ArchiveStreamFactory().createArchiveInputStream("zip", fis)) {
+            for (ArchiveEntry entry; (entry = in.getNextEntry()) != null; ) {
+                readStream(in, entry, map);
+            }
+        }
+
+        // file access
+        try (final ZipFile zf = new ZipFile(input)) {
+            final Enumeration<ZipArchiveEntry> entries = zf.getEntries();
+            while (entries.hasMoreElements()) {
+                final ZipArchiveEntry zae = entries.nextElement();
+                try (InputStream in = zf.getInputStream(zae)) {
+                    readStream(in, zae, map);
+                }
+            }
+        }
+
+        assertEquals(Arrays.asList(8390036L, 8600L), map.get("[Content_Types].xml").get(0));
+        assertEquals(Arrays.asList(1348L, 508L), map.get("xl/worksheets/sheet1.xml").get(0));
+
+        // compare statistics of stream / file access
+        for (Map.Entry<String,List<List<Long>>> me : map.entrySet()) {
+            assertEquals("Mismatch of stats for: "+me.getKey(), me.getValue().get(0), me.getValue().get(1));
+        }
+    }
+
+    private void readStream(final InputStream in, final ArchiveEntry entry, final Map<String,List<List<Long>>> map) throws IOException {
+        final byte[] buf = new byte[4096];
+        final InputStreamStatistics stats = (InputStreamStatistics)in;
+        while (in.read(buf) != -1);
+
+        final String name = entry.getName();
+        final List<List<Long>> l;
+        if (map.containsKey(name)) {
+            l = map.get(name);
+        } else {
+            map.put(name, l = new ArrayList<>());
+        }
+
+        final long t = stats.getUncompressedCount();
+        final long b = stats.getCompressedCount();
+        l.add(Arrays.asList(t, b));
+    }
 }
Index: src/main/java/org/apache/commons/compress/archivers/zip/InflaterInputStream.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/archivers/zip/InflaterInputStream.java	(date 1523702607000)
+++ src/main/java/org/apache/commons/compress/archivers/zip/InflaterInputStream.java	(date 1523702607000)
@@ -0,0 +1,80 @@
+/*
+ *  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.archivers.zip;
+
+import org.apache.commons.compress.utils.InputStreamStatistics;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.Inflater;
+
+/**
+ * Helper class to provide statistics
+ */
+/* package */ class InflaterInputStream extends java.util.zip.InflaterInputStream
+    implements InputStreamStatistics {
+    private long compressedCount = 0;
+    private long uncompressedCount = 0;
+
+    public InflaterInputStream(InputStream in) {
+        super(in);
+    }
+
+    public InflaterInputStream(InputStream in, Inflater inf) {
+        super(in, inf);
+    }
+
+    public InflaterInputStream(InputStream in, Inflater inf, int size) {
+        super(in, inf, size);
+    }
+
+    @Override
+    protected void fill() throws IOException {
+        super.fill();
+        compressedCount += inf.getRemaining();
+    }
+
+    @Override
+    public int read() throws IOException {
+        final int b = super.read();
+        if (b > -1) {
+            uncompressedCount++;
+        }
+        return b;
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        final int bytes = super.read(b, off, len);
+        if (bytes > -1) {
+            uncompressedCount += bytes;
+        }
+        return bytes;
+    }
+
+    @Override
+    public long getCompressedCount() {
+        return compressedCount;
+    }
+
+    @Override
+    public long getUncompressedCount() {
+        return uncompressedCount;
+    }
+}
Index: src/main/java/org/apache/commons/compress/utils/BitInputStream.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/utils/BitInputStream.java	(revision 7a8f3c379fdb17fc57484123a5a81b4aeb4cb234)
+++ src/main/java/org/apache/commons/compress/utils/BitInputStream.java	(date 1523485337000)
@@ -38,7 +38,7 @@
         }
     }
 
-    private final InputStream in;
+    private final CountingInputStream in;
     private final ByteOrder byteOrder;
     private long bitsCached = 0;
     private int bitsCachedSize = 0;
@@ -50,7 +50,7 @@
      *      either BIG_ENDIAN (aaaaabbb bb000000) or LITTLE_ENDIAN (bbbaaaaa 000000bb)
      */
     public BitInputStream(final InputStream in, final ByteOrder byteOrder) {
-        this.in = in;
+        this.in = new CountingInputStream(in);
         this.byteOrder = byteOrder;
     }
 
@@ -187,4 +187,9 @@
         }
         return false;
     }
+
+
+    public long getBytesRead() {
+        return in.getBytesRead();
+    }
 }
Index: src/main/java/org/apache/commons/compress/utils/InputStreamStatistics.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/utils/InputStreamStatistics.java	(date 1523702607000)
+++ src/main/java/org/apache/commons/compress/utils/InputStreamStatistics.java	(date 1523702607000)
@@ -0,0 +1,36 @@
+/*
+ *  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.utils;
+
+/**
+ * This interface provides statistics on the current decompression stream.
+ * The stream consumer can use that statistics to handle abnormal
+ * compression ratios, i.e. to prevent zip bombs.
+ */
+public interface InputStreamStatistics {
+    /**
+     * @return the amount of raw or compressed bytes read by the stream
+     */
+    long getCompressedCount();
+
+    /**
+    * @return the amount of decompressed bytes returned by the stream
+     */
+    long getUncompressedCount();
+}
Index: src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java	(revision 7a8f3c379fdb17fc57484123a5a81b4aeb4cb234)
+++ src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java	(date 1523564103000)
@@ -155,6 +155,10 @@
         return -1;
     }
 
+    public long getBytesRead() {
+        return reader.getBytesRead();
+    }
+
     private void switchToUncompressedState() throws IOException {
         reader.alignWithByteBoundary();
         long bLen = readBits(16);
Index: src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStream.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
--- src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStream.java	(revision 7a8f3c379fdb17fc57484123a5a81b4aeb4cb234)
+++ src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStream.java	(date 1523564103000)
@@ -21,6 +21,8 @@
 import java.io.InputStream;
 
 import org.apache.commons.compress.compressors.CompressorInputStream;
+import org.apache.commons.compress.utils.InputStreamStatistics;
+
 import static org.apache.commons.compress.utils.IOUtils.closeQuietly;
 
 /**
@@ -29,7 +31,7 @@
  * @since 1.16
  * @NotThreadSafe
  */
-public class Deflate64CompressorInputStream extends CompressorInputStream {
+public class Deflate64CompressorInputStream extends CompressorInputStream implements InputStreamStatistics {
     private InputStream originalStream;
     private HuffmanDecoder decoder;
     private final byte[] oneByte = new byte[1];
@@ -98,6 +100,16 @@
         }
     }
 
+    @Override
+    public long getCompressedCount() {
+        return decoder.getBytesRead();
+    }
+
+    @Override
+    public long getUncompressedCount() {
+        return getBytesRead();
+    }
+
     private void closeDecoder() {
         closeQuietly(decoder);
         decoder = null;
diff --git src/test/resources/zipbomb.xlsx src/test/resources/zipbomb.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..46a4211cdff2d9bdd921f3e7ef4c1e82ec013fbf
GIT binary patch
literal 18348
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

