2727import org .apache .commons .compress .archivers .zip .UnicodePathExtraField ;
2828import org .apache .commons .compress .archivers .zip .ZipArchiveEntry ;
2929import org .apache .commons .compress .archivers .zip .ZipFile ;
30+ import org .apache .commons .io .input .BoundedInputStream ;
31+ import org .apache .commons .io .input .CountingInputStream ;
3032import org .codehaus .plexus .archiver .AbstractUnArchiver ;
3133import org .codehaus .plexus .archiver .ArchiverException ;
3234import org .codehaus .plexus .components .io .resources .PlexusIoResource ;
@@ -42,6 +44,8 @@ public abstract class AbstractZipUnArchiver
4244
4345 private String encoding = "UTF8" ;
4446
47+ private long maxOutputSize = Long .MAX_VALUE ;
48+
4549 public AbstractZipUnArchiver ()
4650 {
4751 }
@@ -66,6 +70,21 @@ public void setEncoding( String encoding )
6670 this .encoding = encoding ;
6771 }
6872
73+ /**
74+ * Set maximum allowed size of the produced output.
75+ *
76+ * It may be used as a protection against <a href="https://en.wikipedia.org/wiki/Zip_bomb">zip bombs</a>.
77+ *
78+ * @param maxOutputSize max size of the produced output, in bytes. Must be greater than 0
79+ * @throws IllegalArgumentException if specified output size is less or equal to 0
80+ */
81+ public void setMaxOutputSize ( long maxOutputSize ) {
82+ if ( maxOutputSize <= 0 ) {
83+ throw new IllegalArgumentException ( "Invalid max output size specified: " + maxOutputSize );
84+ }
85+ this .maxOutputSize = maxOutputSize ;
86+ }
87+
6988 private static class ZipEntryFileInfo
7089 implements PlexusIoResource
7190 {
@@ -181,6 +200,7 @@ protected void execute( final String path, final File outputDirectory )
181200 getLogger ().debug ( "Expanding: " + getSourceFile () + " into " + outputDirectory );
182201 try ( ZipFile zipFile = new ZipFile ( getSourceFile (), encoding , true ) )
183202 {
203+ long remainingSpace = maxOutputSize ;
184204 final Enumeration <ZipArchiveEntry > e = zipFile .getEntriesInPhysicalOrder ();
185205
186206 while ( e .hasMoreElements () )
@@ -196,10 +216,18 @@ protected void execute( final String path, final File outputDirectory )
196216 {
197217 try ( InputStream in = zipFile .getInputStream ( ze ) )
198218 {
199- extractFile ( getSourceFile (), outputDirectory , in ,
219+ BoundedInputStream bis = new BoundedInputStream ( in , remainingSpace + 1 );
220+ CountingInputStream cis = new CountingInputStream ( bis );
221+ extractFile ( getSourceFile (), outputDirectory , cis ,
200222 ze .getName (), new Date ( ze .getTime () ), ze .isDirectory (),
201223 ze .getUnixMode () != 0 ? ze .getUnixMode () : null ,
202224 resolveSymlink ( zipFile , ze ), getFileMappers () );
225+
226+ remainingSpace -= cis .getByteCount ();
227+ if ( remainingSpace < 0 )
228+ {
229+ throw new ArchiverException ( "Maximum output size limit reached" );
230+ }
203231 }
204232 }
205233 }
0 commit comments