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

commit 1a694c20e9b378d2801f5a156aa86021e5f0c354
Author: Gary D. Gregory <[email protected]>
AuthorDate: Sun Aug 3 17:04:10 2025 -0400

    Add org.apache.commons.compress.archivers.ArchiveException.addExact(int,
    int)
    
    Use org.apache.commons.compress.archivers.ArchiveException.addExact(long,
    long)
---
 src/changes/changes.xml                            |  1 +
 .../compress/archivers/ArchiveException.java       | 19 ++++++++++++
 .../compress/archivers/sevenz/SevenZFile.java      | 34 +++++++++++-----------
 .../archivers/ar/ArArchiveInputStreamTest.java     | 16 ++++++++++
 4 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index f28c848d2..ba2464418 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -74,6 +74,7 @@ The <action> type attribute can be add,update,fix,remove.
       <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
org.apache.commons.compress.MemoryLimitException.checkBytes(int, long).</action>
       <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
org.apache.commons.compress.MemoryLimitException.checkKiB(long, long).</action>
       <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
org.apache.commons.compress.archivers.ArchiveException.addExact(long, 
long).</action>
+      <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
org.apache.commons.compress.archivers.ArchiveException.addExact(int, 
int).</action>
       <!-- UPDATE -->
     </release>
     <release version="1.28.0" date="2025-07-26" description="This is a feature 
and maintenance release. Java 8 or later is required.">
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/ArchiveException.java 
b/src/main/java/org/apache/commons/compress/archivers/ArchiveException.java
index 0da2edcc2..fad5fac36 100644
--- a/src/main/java/org/apache/commons/compress/archivers/ArchiveException.java
+++ b/src/main/java/org/apache/commons/compress/archivers/ArchiveException.java
@@ -30,6 +30,24 @@ public class ArchiveException extends CompressException {
     /** Serial. */
     private static final long serialVersionUID = 2772690708123267100L;
 
+    /**
+     * Delegates to {@link Math#addExact(int, int)} wrapping its {@link 
ArithmeticException} in our {@link ArchiveException}.
+     *
+     * @param x the first value.
+     * @param y the second value.
+     * @return the result.
+     * @throws ArchiveException if the result overflows a long.
+     * @see Math#addExact(int, int)
+     * @since 1.29.0
+     */
+    public static int addExact(final int x, final int y) throws 
ArchiveException {
+        try {
+            return Math.addExact(x, y);
+        } catch (final ArithmeticException e) {
+            throw new ArchiveException(e);
+        }
+    }
+
     /**
      * Delegates to {@link Math#addExact(long, long)} wrapping its {@link 
ArithmeticException} in our {@link ArchiveException}.
      *
@@ -37,6 +55,7 @@ public class ArchiveException extends CompressException {
      * @param y the second value.
      * @return the result.
      * @throws ArchiveException if the result overflows a long.
+     * @see Math#addExact(long, long)
      * @since 1.29.0
      */
     public static long addExact(final long x, final long y) throws 
ArchiveException {
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 bd953fcf3..6c809ed93 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
@@ -779,8 +779,8 @@ private InputStream buildDecoderStack(final Folder folder, 
final long folderOffs
         channel.position(folderOffset);
         InputStream inputStreamStack = new FilterInputStream(
                 new BufferedInputStream(new 
BoundedSeekableByteChannelInputStream(channel, 
archive.packSizes[firstPackStreamIndex]))) {
-            private void count(final int c) {
-                compressedBytesReadFromCurrentEntry = 
Math.addExact(compressedBytesReadFromCurrentEntry, c);
+            private void count(final int c) throws ArchiveException {
+                compressedBytesReadFromCurrentEntry = 
ArchiveException.addExact(compressedBytesReadFromCurrentEntry, c);
             }
 
             @Override
@@ -916,14 +916,14 @@ private void calculateStreamMap(final Archive archive) 
throws IOException {
         final int[] folderFirstPackStreamIndex = new int[numFolders];
         for (int i = 0; i < numFolders; i++) {
             folderFirstPackStreamIndex[i] = nextFolderPackStreamIndex;
-            nextFolderPackStreamIndex = 
Math.addExact(nextFolderPackStreamIndex, 
archive.folders[i].packedStreams.length);
+            nextFolderPackStreamIndex = 
ArchiveException.addExact(nextFolderPackStreamIndex, 
archive.folders[i].packedStreams.length);
         }
         long nextPackStreamOffset = 0;
         final int numPackSizes = archive.packSizes.length;
         final long[] packStreamOffsets = new long[numPackSizes];
         for (int i = 0; i < numPackSizes; i++) {
             packStreamOffsets[i] = nextPackStreamOffset;
-            nextPackStreamOffset = Math.addExact(nextPackStreamOffset, 
archive.packSizes[i]);
+            nextPackStreamOffset = 
ArchiveException.addExact(nextPackStreamOffset, archive.packSizes[i]);
         }
         final int[] folderFirstFileIndex = new int[numFolders];
         final int[] fileFolderIndex = new int[archive.files.length];
@@ -1206,7 +1206,7 @@ public int read(final byte[] b, final int off, final int 
len) throws IOException
         @SuppressWarnings("resource") // does not allocate
         final int current = getCurrentStream().read(b, off, len);
         if (current > 0) {
-            uncompressedBytesReadFromCurrentEntry = 
Math.addExact(uncompressedBytesReadFromCurrentEntry, current);
+            uncompressedBytesReadFromCurrentEntry = 
ArchiveException.addExact(uncompressedBytesReadFromCurrentEntry, current);
         }
         return current;
     }
@@ -1464,8 +1464,8 @@ private Folder readFolder(final ByteBuffer header) throws 
IOException {
                 numInStreams = readUint64(header);
                 numOutStreams = readUint64(header);
             }
-            totalInStreams = Math.addExact(totalInStreams, numInStreams);
-            totalOutStreams = Math.addExact(totalOutStreams, numOutStreams);
+            totalInStreams = ArchiveException.addExact(totalInStreams, 
numInStreams);
+            totalOutStreams = ArchiveException.addExact(totalOutStreams, 
numOutStreams);
             byte[] properties = null;
             if (hasAttributes) {
                 final long propertiesSize = readUint64(header);
@@ -1660,7 +1660,7 @@ private void readSubStreamsInfo(final ByteBuffer header, 
final Archive archive)
             for (final Folder folder : archive.folders) {
                 final long numStreams = readUint64(header);
                 folder.numUnpackSubStreams = (int) numStreams;
-                unpackStreamsCount = Math.addExact(unpackStreamsCount, 
numStreams);
+                unpackStreamsCount = 
ArchiveException.addExact(unpackStreamsCount, numStreams);
             }
             nid = getUnsignedByte(header);
         }
@@ -1675,7 +1675,7 @@ private void readSubStreamsInfo(final ByteBuffer header, 
final Archive archive)
                 for (int i = 0; i < folder.numUnpackSubStreams - 1; i++) {
                     final long size = readUint64(header);
                     subStreamsInfo.unpackSizes[nextUnpackStream++] = size;
-                    sum = Math.addExact(sum, size);
+                    sum = ArchiveException.addExact(sum, size);
                 }
             }
             if (sum > folder.getUnpackSize()) {
@@ -1689,7 +1689,7 @@ private void readSubStreamsInfo(final ByteBuffer header, 
final Archive archive)
         int numDigests = 0;
         for (final Folder folder : archive.folders) {
             if (folder.numUnpackSubStreams != 1 || !folder.hasCrc) {
-                numDigests = Math.addExact(numDigests, 
folder.numUnpackSubStreams);
+                numDigests = ArchiveException.addExact(numDigests, 
folder.numUnpackSubStreams);
             }
         }
         if (nid == NID.kCRC) {
@@ -1929,7 +1929,7 @@ private int sanityCheckFolder(final ByteBuffer header, 
final ArchiveStatistics s
         if (numCoders == 0) {
             throw new ArchiveException("Folder without coders");
         }
-        stats.numberOfCoders = Math.addExact(stats.numberOfCoders, numCoders);
+        stats.numberOfCoders = ArchiveException.addExact(stats.numberOfCoders, 
numCoders);
         long totalOutStreams = 0;
         long totalInStreams = 0;
         for (int i = 0; i < numCoders; i++) {
@@ -1946,8 +1946,8 @@ private int sanityCheckFolder(final ByteBuffer header, 
final ArchiveStatistics s
                 totalInStreams++;
                 totalOutStreams++;
             } else {
-                totalInStreams = Math.addExact(totalInStreams, 
assertFitsIntoNonNegativeInt("numInStreams", readUint64(header)));
-                totalOutStreams = Math.addExact(totalOutStreams, 
assertFitsIntoNonNegativeInt("numOutStreams", readUint64(header)));
+                totalInStreams = ArchiveException.addExact(totalInStreams, 
assertFitsIntoNonNegativeInt("numInStreams", readUint64(header)));
+                totalOutStreams = ArchiveException.addExact(totalOutStreams, 
assertFitsIntoNonNegativeInt("numOutStreams", readUint64(header)));
             }
             if (hasAttributes) {
                 final int propertiesSize = 
assertFitsIntoNonNegativeInt("propertiesSize", readUint64(header));
@@ -1958,8 +1958,8 @@ private int sanityCheckFolder(final ByteBuffer header, 
final ArchiveStatistics s
         }
         assertFitsIntoNonNegativeInt("totalInStreams", totalInStreams);
         assertFitsIntoNonNegativeInt("totalOutStreams", totalOutStreams);
-        stats.numberOfOutStreams = Math.addExact(stats.numberOfOutStreams, 
totalOutStreams);
-        stats.numberOfInStreams = Math.addExact(stats.numberOfInStreams, 
totalInStreams);
+        stats.numberOfOutStreams = 
ArchiveException.addExact(stats.numberOfOutStreams, totalOutStreams);
+        stats.numberOfInStreams = 
ArchiveException.addExact(stats.numberOfInStreams, totalInStreams);
         if (totalOutStreams == 0) {
             throw new ArchiveException("Total output streams can't be 0");
         }
@@ -2007,7 +2007,7 @@ private void sanityCheckPackInfo(final ByteBuffer header, 
final ArchiveStatistic
             long totalPackSizes = 0;
             for (int i = 0; i < stats.numberOfPackedStreams; i++) {
                 final long packSize = readUint64(header);
-                totalPackSizes = Math.addExact(totalPackSizes, packSize);
+                totalPackSizes = ArchiveException.addExact(totalPackSizes, 
packSize);
                 final long endOfPackStreams = SIGNATURE_HEADER_SIZE + packPos 
+ totalPackSizes;
                 if (packSize < 0 || endOfPackStreams > channel.size() || 
endOfPackStreams < packPos) {
                     throw new ArchiveException("packSize (%,d) is out of 
range", packSize);
@@ -2080,7 +2080,7 @@ private void sanityCheckSubStreamsInfo(final ByteBuffer 
header, final ArchiveSta
             int folderIdx = 0;
             for (final int numUnpackSubStreams : numUnpackSubStreamsPerFolder) 
{
                 if (numUnpackSubStreams != 1 || stats.folderHasCrc == null || 
!stats.folderHasCrc.get(folderIdx++)) {
-                    numDigests = Math.addExact(numDigests, 
numUnpackSubStreams);
+                    numDigests = ArchiveException.addExact(numDigests, 
numUnpackSubStreams);
                 }
             }
         }
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java
 
b/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java
index 8325f756c..d6190f5d4 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java
@@ -27,11 +27,15 @@
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 
 import org.apache.commons.compress.AbstractTest;
 import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveException;
 import org.apache.commons.compress.utils.ArchiveUtils;
 import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
@@ -99,6 +103,18 @@ private void testCompress661(final boolean 
checkMarkReadReset) throws IOExceptio
         }
     }
 
+    /**
+     * Depending on your setup, this test may need a small stack size {@code 
-Xss1m}.
+     */
+    @Test
+    @Disabled
+    void testGetNextArEntry() throws IOException {
+        try (ArArchiveInputStream inputStream = new ArArchiveInputStream(
+                
Files.newInputStream(Paths.get("src/test/resources/org/apache/commons/compress/ar/getNextArEntry.bin"))))
 {
+            assertThrows(ArchiveException.class, inputStream::getNextEntry);
+        }
+    }
+
     @Test
     void testInvalidBadTableLength() throws Exception {
         try (InputStream in = 
newInputStream("org/apache/commons/compress/ar/number_parsing/bad_table_length_gnu-fail.ar");

Reply via email to