You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2023/03/16 15:15:55 UTC

[commons-compress] branch master updated: COMPRESS-642 Integer overflow ArithmeticException in TarArchiveOutputStream (#368)

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

ggregory 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 f5365de7 COMPRESS-642 Integer overflow ArithmeticException in TarArchiveOutputStream (#368)
f5365de7 is described below

commit f5365de7849a076003e0fb7df9c65b3560617cea
Author: Anton Klarén <an...@neotechnology.com>
AuthorDate: Thu Mar 16 16:15:47 2023 +0100

    COMPRESS-642 Integer overflow ArithmeticException in TarArchiveOutputStream (#368)
    
    * COMPRESS-642 Integer overflow ArithmeticException in TarArchiveOutputStream
    
    Tar files technically supports unlimited file size. For practical purposes it should be enough with a long.
    
    * * Remove useless parenthesis
    * Add test for integer overflow. Disabled by default since it's very slow.
---
 .../archivers/tar/TarArchiveOutputStream.java      |  6 +++---
 .../archivers/tar/TarArchiveOutputStreamTest.java  | 23 ++++++++++++++++++++++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
index 80f08bff..bc98332e 100644
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
@@ -107,7 +107,7 @@ public class TarArchiveOutputStream extends ArchiveOutputStream {
     private int longFileMode = LONGFILE_ERROR;
     private int bigNumberMode = BIGNUMBER_ERROR;
 
-    private int recordsWritten;
+    private long recordsWritten;
 
     private final int recordsPerBlock;
 
@@ -348,7 +348,7 @@ public class TarArchiveOutputStream extends ArchiveOutputStream {
                 + "' before the '" + currSize
                 + "' bytes specified in the header were written");
         }
-        recordsWritten = ExactMath.add(recordsWritten, (currSize / RECORD_SIZE));
+        recordsWritten += currSize / RECORD_SIZE;
 
         if (0 != currSize % RECORD_SIZE) {
             recordsWritten++;
@@ -535,7 +535,7 @@ public class TarArchiveOutputStream extends ArchiveOutputStream {
     }
 
     private void padAsNeeded() throws IOException {
-        final int start = recordsWritten % recordsPerBlock;
+        final int start = Math.toIntExact(recordsWritten % recordsPerBlock);
         if (start != 0) {
             for (int i = start; i < recordsPerBlock; i++) {
                 writeEOFRecord();
diff --git a/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java b/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java
index ba14b712..ffa98eac 100644
--- a/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java
@@ -48,6 +48,8 @@ import org.apache.commons.compress.archivers.ArchiveEntry;
 import org.apache.commons.compress.archivers.ArchiveOutputStream;
 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
 import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.io.output.NullOutputStream;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 public class TarArchiveOutputStreamTest extends AbstractTestCase {
@@ -768,4 +770,25 @@ public class TarArchiveOutputStreamTest extends AbstractTestCase {
         return bos.toByteArray();
     }
 
+    /**
+     * @see "https://issues.apache.org/jira/browse/COMPRESS-642"
+     */
+    @Disabled("The test needs to write 1.1 TB in chunks of 512 bytes which takes a long time. So it's disabled by default")
+    @Test
+    public void testWritingBigFile() throws Exception {
+        final TarArchiveEntry t = new TarArchiveEntry("foo");
+        t.setSize((Integer.MAX_VALUE + 1L) * TarConstants.DEFAULT_RCDSIZE);
+        final TarArchiveOutputStream tos = new TarArchiveOutputStream(NullOutputStream.NULL_OUTPUT_STREAM);
+        tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
+        tos.putArchiveEntry(t);
+
+        byte[] bytes = new byte[TarConstants.DEFAULT_RCDSIZE];
+        for (int i = 0; i < Integer.MAX_VALUE; i++) {
+            tos.write(bytes);
+        }
+        tos.write(bytes);
+        tos.closeArchiveEntry();
+        tos.close();
+    }
+
 }