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

pjfanning pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/poi.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 702aca1a9f use math multiplyexact for multiplication (#1095)
702aca1a9f is described below

commit 702aca1a9ff230291429eaded36c266254624224
Author: PJ Fanning <[email protected]>
AuthorDate: Wed May 27 21:38:54 2026 +0100

    use math multiplyexact for multiplication (#1095)
    
    * Use Math.multiplyExact to guard against integer overflow in 
multiplications
    
    * int exact
    
    * avoid some casts
    
    * Update Ole10Native.java
    
    * fix test issues
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] 
<[email protected]>
---
 .../src/main/java/org/apache/poi/hemf/record/emf/HemfHeader.java   | 2 +-
 .../src/main/java/org/apache/poi/hemf/record/emf/HemfText.java     | 3 ++-
 .../src/main/java/org/apache/poi/hslf/dev/SlideShowDumper.java     | 2 +-
 .../src/main/java/org/apache/poi/hwmf/draw/HwmfROP3Composite.java  | 2 +-
 .../src/main/java/org/apache/poi/hwmf/record/HwmfBitmap16.java     | 2 +-
 .../src/main/java/org/apache/poi/hwmf/record/HwmfBitmapDib.java    | 7 ++++---
 .../src/main/java/org/apache/poi/hwpf/model/OldTextPieceTable.java | 2 +-
 .../src/main/java/org/apache/poi/hwpf/model/TextPieceTable.java    | 2 +-
 poi/src/main/java/org/apache/poi/hpsf/Property.java                | 4 ++--
 .../java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java  | 4 ++--
 poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java | 5 +++--
 poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java | 5 +++--
 poi/src/main/java/org/apache/poi/util/IOUtils.java                 | 6 ++++--
 .../main/java/org/apache/poi/util/RLEDecompressingInputStream.java | 2 +-
 .../test/java/org/apache/poi/poifs/filesystem/TestPOIFSStream.java | 2 +-
 test-data/poi-integration-exceptions.csv                           | 2 +-
 16 files changed, 29 insertions(+), 23 deletions(-)

diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emf/HemfHeader.java 
b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emf/HemfHeader.java
index cb9ab2ebc5..01b43d613f 100644
--- 
a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emf/HemfHeader.java
+++ 
b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emf/HemfHeader.java
@@ -173,7 +173,7 @@ public class HemfHeader implements HemfRecord {
             if (skip < 0 || descriptionEnd > recordSize + HEADER_SIZE || skip 
+ descriptionBytes > Integer.MAX_VALUE) {
                 throw new RecordFormatException("Invalid EMF header 
description bounds");
             }
-            int maxDescriptionLength = (int)Math.min(recordSize, 
Integer.MAX_VALUE);
+            int maxDescriptionLength = Math.toIntExact(Math.min(recordSize, 
Integer.MAX_VALUE));
             IOUtils.safelyAllocateCheck(descriptionBytes, 
maxDescriptionLength);
             leis.mark((int)(skip + descriptionBytes));
             leis.skipFully((int)skip);
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emf/HemfText.java 
b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emf/HemfText.java
index 3b6aaddd75..efe73fdf90 100644
--- a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emf/HemfText.java
+++ b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emf/HemfText.java
@@ -156,7 +156,8 @@ public class HemfText {
                             //
                             // If ETO_RTLREADING is specified, characters are 
laid right to left instead of left to right.
                             // No other options affect the interpretation of 
this field.
-                            final int maxSize = (int)Math.min((offDx < 
offString) ? (offString-HEADER_SIZE) : recordSize, recordSize);
+                            final int maxSize = Math.toIntExact(Math.min(
+                                    offDx < offString ? 
(offString-HEADER_SIZE) : recordSize, recordSize));
                             while (size <= 
maxSize-LittleEndianConsts.INT_SIZE) {
                                 dx.add((int) leis.readUInt());
                                 size += LittleEndianConsts.INT_SIZE;
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowDumper.java 
b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowDumper.java
index 8b43555d07..cbaa53c824 100644
--- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowDumper.java
+++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowDumper.java
@@ -224,7 +224,7 @@ public final class SlideShowDumper {
                 }
             }
 
-            pos += (int) Math.min(len, Integer.MAX_VALUE);
+            pos += Math.toIntExact(Math.min(len, Integer.MAX_VALUE));
         }
     }
 
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hwmf/draw/HwmfROP3Composite.java 
b/poi-scratchpad/src/main/java/org/apache/poi/hwmf/draw/HwmfROP3Composite.java
index 6cac2a5dca..b176aedbab 100644
--- 
a/poi-scratchpad/src/main/java/org/apache/poi/hwmf/draw/HwmfROP3Composite.java
+++ 
b/poi-scratchpad/src/main/java/org/apache/poi/hwmf/draw/HwmfROP3Composite.java
@@ -56,7 +56,7 @@ public class HwmfROP3Composite implements Composite {
         } else {
             mask_width = bitmap.getWidth();
             mask_height = bitmap.getHeight();
-            mask = new byte[mask_width * mask_height];
+            mask = new byte[Math.multiplyExact(mask_width, mask_height)];
             bitmap.getRaster().getDataElements(0, 0, mask_width, mask_height, 
mask);
         }
         this.background = background.getRGB();
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hwmf/record/HwmfBitmap16.java 
b/poi-scratchpad/src/main/java/org/apache/poi/hwmf/record/HwmfBitmap16.java
index cc103b2c06..cb8315d8ce 100644
--- a/poi-scratchpad/src/main/java/org/apache/poi/hwmf/record/HwmfBitmap16.java
+++ b/poi-scratchpad/src/main/java/org/apache/poi/hwmf/record/HwmfBitmap16.java
@@ -79,7 +79,7 @@ public class HwmfBitmap16 implements GenericRecord {
             size += 18+LittleEndianConsts.INT_SIZE;
         }
 
-        int length = (((width * bitsPixel + 15) >> 4) << 1) * height;
+        int length = Math.multiplyExact(((width * bitsPixel + 15) >> 4) << 1, 
height);
         bitmap = IOUtils.toByteArray(leis, length);
         
         // TODO: this is not implemented ... please provide a sample, if it
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hwmf/record/HwmfBitmapDib.java 
b/poi-scratchpad/src/main/java/org/apache/poi/hwmf/record/HwmfBitmapDib.java
index cfe5804ee3..4a82faf123 100644
--- a/poi-scratchpad/src/main/java/org/apache/poi/hwmf/record/HwmfBitmapDib.java
+++ b/poi-scratchpad/src/main/java/org/apache/poi/hwmf/record/HwmfBitmapDib.java
@@ -246,8 +246,8 @@ public class HwmfBitmapDib implements GenericRecord {
         // The size and format of this data is determined by information in 
the DIBHeaderInfo field. If
         // it is a BitmapCoreHeader, the size in bytes MUST be calculated as 
follows:
 
-        int bodySize = ((((headerWidth * headerPlanes *
-                (headerBitCount == null ? 0 : headerBitCount.flag) + 31) & 
~31) / 8) * Math.abs(headerHeight));
+        long bodySize = ((((long)headerWidth * headerPlanes *
+                (headerBitCount == null ? 0 : headerBitCount.flag) + 31L) & 
~31L) / 8L) * Math.abs((long)headerHeight);
 
         // This formula SHOULD also be used to calculate the size of aData 
when DIBHeaderInfo is a
         // BitmapInfoHeader Object, using values from that object, but only if 
its Compression value is
@@ -260,7 +260,8 @@ public class HwmfBitmapDib implements GenericRecord {
             headerCompression == Compression.BI_RGB ||
             headerCompression == Compression.BI_BITFIELDS ||
             headerCompression == Compression.BI_CMYK) {
-            int fileSize = Math.min(introSize+bodySize,recordSize);
+            int fileSize = Math.toIntExact(
+                    Math.min(introSize + bodySize, recordSize));
             imageData = IOUtils.safelyAllocate(fileSize, 
HwmfPicture.getMaxRecordLength());
             leis.readFully(imageData, 0, introSize);
             leis.skipFully(recordSize-fileSize);
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/OldTextPieceTable.java 
b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/OldTextPieceTable.java
index 384803469e..f82fd32eff 100644
--- 
a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/OldTextPieceTable.java
+++ 
b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/OldTextPieceTable.java
@@ -77,7 +77,7 @@ public class OldTextPieceTable extends TextPieceTable {
 
             // Figure out the length, in bytes and chars
             int textSizeChars = (nodeEndChars - nodeStartChars);
-            int textSizeBytes = textSizeChars * multiple;
+            int textSizeBytes = Math.multiplyExact(textSizeChars, multiple);
 
             // Grab the data that makes up the piece
             byte[] buf = IOUtils.safelyClone(documentStream, start, 
textSizeBytes, getMaxRecordLength());
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/TextPieceTable.java 
b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/TextPieceTable.java
index e011f7f819..aa02c1bf1e 100644
--- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/TextPieceTable.java
+++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/TextPieceTable.java
@@ -112,7 +112,7 @@ public class TextPieceTable implements CharIndexTranslator {
 
             // Figure out the length, in bytes and chars
             int textSizeChars = (nodeEndChars - nodeStartChars);
-            int textSizeBytes = textSizeChars * multiple;
+            int textSizeBytes = Math.multiplyExact(textSizeChars, multiple);
 
             // Grab the data that makes up the piece
             byte[] buf = IOUtils.safelyClone(documentStream, start, 
textSizeBytes, MAX_RECORD_LENGTH);
diff --git a/poi/src/main/java/org/apache/poi/hpsf/Property.java 
b/poi/src/main/java/org/apache/poi/hpsf/Property.java
index fa336345e5..410f517e6d 100644
--- a/poi/src/main/java/org/apache/poi/hpsf/Property.java
+++ b/poi/src/main/java/org/apache/poi/hpsf/Property.java
@@ -145,7 +145,7 @@ public class Property {
         o += LittleEndianConsts.INT_SIZE;
 
         try {
-            value = VariantSupport.read(src, o, length, (int) type, codepage);
+            value = VariantSupport.read(src, o, length, Math.toIntExact(type), 
codepage);
         } catch (UnsupportedVariantTypeException ex) {
             VariantSupport.writeUnsupportedTypeMessage(ex);
             value = ex.getValue();
@@ -179,7 +179,7 @@ public class Property {
         type = leis.readUInt();
 
         try {
-            value = VariantSupport.read(leis, length, (int) type, codepage);
+            value = VariantSupport.read(leis, length, Math.toIntExact(type), 
codepage);
         } catch (UnsupportedVariantTypeException ex) {
             VariantSupport.writeUnsupportedTypeMessage(ex);
             value = ex.getValue();
diff --git 
a/poi/src/main/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java 
b/poi/src/main/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java
index baa2a000df..e75e598e66 100644
--- a/poi/src/main/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java
+++ b/poi/src/main/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java
@@ -104,7 +104,7 @@ public abstract class ChunkedCipherInputStream extends 
LittleEndianInputStream {
                     throw new EncryptedDocumentException(e.getMessage(), e);
                 }
             }
-            int count = (int)(chunk.length - (pos & chunkMask));
+            int count = Math.toIntExact(chunk.length - (pos & chunkMask));
             int avail = remainingBytes();
             if (avail == 0) {
                 return total;
@@ -185,7 +185,7 @@ public abstract class ChunkedCipherInputStream extends 
LittleEndianInputStream {
             lastIndex = index + 1;
         }
 
-        final int todo = (int)Math.min(size, chunk.length);
+        final int todo = Math.toIntExact(Math.min(size, chunk.length));
         int readBytes, totalBytes = 0;
         do {
             readBytes = super.read(plain, totalBytes, todo-totalBytes);
diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java 
b/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java
index 027500dcb5..d59b129128 100644
--- a/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java
+++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java
@@ -289,8 +289,9 @@ public class Ole10Native {
     }
 
     private static String readUtf16(LittleEndianByteArrayInputStream leis) 
throws IOException {
-        int size = leis.readInt();
-        byte[] buf = IOUtils.toByteArray(leis, size * 2L, MAX_STRING_LENGTH);
+        final int size = leis.readInt();
+        final long arraySize = 2L * size;
+        final byte[] buf = IOUtils.toByteArray(leis, arraySize, 
MAX_STRING_LENGTH);
         return StringUtil.getFromUnicodeLE(buf, 0, size);
     }
 
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java 
b/poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java
index a4fac2685e..99362bed8c 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java
@@ -25,6 +25,7 @@ import org.apache.poi.ss.formula.eval.EvaluationException;
 import org.apache.poi.ss.formula.eval.OperandResolver;
 import org.apache.poi.ss.formula.eval.StringEval;
 import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.util.MathUtil;
 
 /**
  * Implementation for Excel COMPLEX () function.
@@ -104,7 +105,7 @@ public class Complex extends Var2or3ArgFunction implements 
FreeRefFunction {
         StringBuilder strb = new StringBuilder();
         if (realNum != 0) {
             if (isDoubleAnInt(realNum)) {
-                strb.append((int)realNum);
+                strb.append(MathUtil.safeDoubleToInt(realNum));
             } else {
                 strb.append(realNum);
             }
@@ -118,7 +119,7 @@ public class Complex extends Var2or3ArgFunction implements 
FreeRefFunction {
 
             if (realINum != 1 && realINum != -1) {
                 if (isDoubleAnInt(realINum)) {
-                    strb.append((int)realINum);
+                    strb.append(MathUtil.safeDoubleToInt(realINum));
                 } else {
                     strb.append(realINum);
                 }
diff --git a/poi/src/main/java/org/apache/poi/util/IOUtils.java 
b/poi/src/main/java/org/apache/poi/util/IOUtils.java
index 2ebbd69e32..1b2d413d5e 100644
--- a/poi/src/main/java/org/apache/poi/util/IOUtils.java
+++ b/poi/src/main/java/org/apache/poi/util/IOUtils.java
@@ -232,8 +232,10 @@ public final class IOUtils {
      * @since 5.4.1
      */
     public static byte[] toByteArray(InputStream stream, final long length, 
final int maxLength) throws IOException {
-        return toByteArray(stream,
-                length > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) length,
+        if (length > Integer.MAX_VALUE) {
+            throwRFE(length, maxLength);
+        }
+        return toByteArray(stream, Math.toIntExact(length),
                 maxLength, true, length != Integer.MAX_VALUE);
     }
 
diff --git 
a/poi/src/main/java/org/apache/poi/util/RLEDecompressingInputStream.java 
b/poi/src/main/java/org/apache/poi/util/RLEDecompressingInputStream.java
index 8a6b9bff82..3c883d0ed2 100644
--- a/poi/src/main/java/org/apache/poi/util/RLEDecompressingInputStream.java
+++ b/poi/src/main/java/org/apache/poi/util/RLEDecompressingInputStream.java
@@ -131,7 +131,7 @@ public class RLEDecompressingInputStream extends 
InputStream {
                     return -1;
                 }
             }
-            int c = (int) Math.min(n, len - (long)pos);
+            int c = Math.toIntExact(Math.min(n, len - pos));
             pos += c;
             length -= c;
         }
diff --git 
a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSStream.java 
b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSStream.java
index 9dd6043ae1..756df2f78e 100644
--- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSStream.java
+++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSStream.java
@@ -2725,7 +2725,7 @@ final class TestPOIFSStream {
         @Override
         public int read(byte[] b, int offset, int len) {
             if (size >= maxSize) return -1;
-            int sz = (int) Math.min(len, maxSize - size);
+            int sz = Math.toIntExact(Math.min(len, maxSize - size));
             for (int i = 0; i < sz; i++) {
                 b[i + offset] = (byte) ((size + i) % 128);
             }
diff --git a/test-data/poi-integration-exceptions.csv 
b/test-data/poi-integration-exceptions.csv
index c3f2806697..e0849f0a0b 100644
--- a/test-data/poi-integration-exceptions.csv
+++ b/test-data/poi-integration-exceptions.csv
@@ -100,7 +100,7 @@ 
spreadsheet/sample.strict.xlsx,extract,OPC,,org.apache.poi.ooxml.POIXMLException
 
spreadsheet/57914.xlsx,"handle,extract",XSSF,,org.apache.poi.ooxml.POIXMLException,"Strict
 OOXML isn't currently supported, please see bug #57699",
 
spreadsheet/57914.xlsx,extract,OPC,,org.apache.poi.ooxml.POIXMLException,"Strict
 OOXML isn't currently supported, please see bug #57699",
 
spreadsheet/poi-fuzz.xls,additional,HSSF,,org.apache.poi.util.RecordFormatException,Not
 enough data (0) to read requested (4) bytes,
-spreadsheet/poi-fuzz.xls,additional,HPSF,,org.apache.poi.util.RecordFormatException,Overflow
 when calculating the number of scalar values,
+spreadsheet/poi-fuzz.xls,additional,HPSF,,java.lang.ArithmeticException,integer
 overflow,
 
spreadsheet/poi-fuzz.xls,handle,HPSF,,org.opentest4j.AssertionFailedError,expected:
 <true> but was: <false>,
 
openxml4j/ContentTypeHasEntities.ooxml,"handle,extract",OPC,,org.apache.poi.openxml4j.exceptions.InvalidFormatException,Can't
 read content types part !,
 ddf/Container.dat,handle,HMEF,,java.lang.IllegalArgumentException,"TNEF 
signature not detected in file, expected 574529400 but got -268435441",


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to