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 d290db190b Apply allocation bounds checks to EMF+ path and brush 
element counts (#1104)
d290db190b is described below

commit d290db190bb301bc717f5f568c65f57a3e3ee940
Author: jmestwa-coder <[email protected]>
AuthorDate: Wed Jun 3 19:21:32 2026 +0530

    Apply allocation bounds checks to EMF+ path and brush element counts (#1104)
---
 .../poi/hemf/record/emfplus/HemfPlusBrush.java     |  4 ++
 .../poi/hemf/record/emfplus/HemfPlusPath.java      |  3 ++
 .../poi/hemf/record/emfplus/TestHemfPlusBrush.java | 55 ++++++++++++++++++++++
 .../poi/hemf/record/emfplus/TestHemfPlusPath.java  | 26 ++++++++++
 4 files changed, 88 insertions(+)

diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusBrush.java
 
b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusBrush.java
index 337a77b9de..7237ec4443 100644
--- 
a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusBrush.java
+++ 
b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusBrush.java
@@ -53,6 +53,7 @@ import 
org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
 import org.apache.poi.hemf.record.emfplus.HemfPlusPath.EmfPlusPath;
 import org.apache.poi.hwmf.record.HwmfBrushStyle;
 import org.apache.poi.hwmf.record.HwmfColorRef;
+import org.apache.poi.hwmf.usermodel.HwmfPicture;
 import org.apache.poi.sl.draw.DrawPaint;
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
@@ -735,6 +736,7 @@ public class HemfPlusBrush {
 
             // An array of SurroundingColorCount EmfPlusARGB objects that 
specify the colors for discrete points on the
             // boundary of the brush.
+            IOUtils.safelyAllocateCheck(colorCount, 
HwmfPicture.getMaxRecordLength());
             surroundingColor = new Color[colorCount];
             for (int i = 0; i < colorCount; i++) {
                 surroundingColor[i] = readARGB(leis.readInt());
@@ -757,6 +759,7 @@ public class HemfPlusBrush {
                 size += LittleEndianConsts.INT_SIZE;
 
                 // An array of BoundaryPointCount EmfPlusPointF objects that 
specify the boundary of the brush.
+                IOUtils.safelyAllocateCheck(pointCount, 
HwmfPicture.getMaxRecordLength());
                 boundaryPoints = new Point2D[pointCount];
                 for (int i=0; i<pointCount; i++) {
                     size += readPointF(leis, boundaryPoints[i] = new 
Point2D.Double());
@@ -912,6 +915,7 @@ public class HemfPlusBrush {
         final int count = leis.readInt();
         int size = LittleEndianConsts.INT_SIZE;
 
+        IOUtils.safelyAllocateCheck(count, HwmfPicture.getMaxRecordLength());
         float[] positions = new float[count];
         for (int i=0; i<count; i++) {
             positions[i] = leis.readFloat();
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusPath.java
 
b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusPath.java
index 210e3a5063..cef5968044 100644
--- 
a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusPath.java
+++ 
b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusPath.java
@@ -38,9 +38,11 @@ import 
org.apache.poi.hemf.record.emfplus.HemfPlusDraw.EmfPlusRelativePosition;
 import 
org.apache.poi.hemf.record.emfplus.HemfPlusHeader.EmfPlusGraphicsVersion;
 import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectData;
 import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
+import org.apache.poi.hwmf.usermodel.HwmfPicture;
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
 import org.apache.poi.util.GenericRecordUtil;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.LittleEndianConsts;
 import org.apache.poi.util.LittleEndianInputStream;
 
@@ -119,6 +121,7 @@ public class HemfPlusPath {
                 readPoint = HemfPlusDraw::readPointF;
             }
 
+            IOUtils.safelyAllocateCheck(pointCount, 
HwmfPicture.getMaxRecordLength());
             pathPoints = new Point2D[pointCount];
             for (int i=0; i<pointCount; i++) {
                 pathPoints[i] = new Point2D.Double();
diff --git 
a/poi-scratchpad/src/test/java/org/apache/poi/hemf/record/emfplus/TestHemfPlusBrush.java
 
b/poi-scratchpad/src/test/java/org/apache/poi/hemf/record/emfplus/TestHemfPlusBrush.java
new file mode 100644
index 0000000000..79bc4b5dbe
--- /dev/null
+++ 
b/poi-scratchpad/src/test/java/org/apache/poi/hemf/record/emfplus/TestHemfPlusBrush.java
@@ -0,0 +1,55 @@
+/* ====================================================================
+   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.poi.hemf.record.emfplus;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.ByteArrayInputStream;
+
+import 
org.apache.poi.hemf.record.emfplus.HemfPlusBrush.EmfPlusPathGradientBrushData;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianInputStream;
+import org.apache.poi.util.RecordFormatException;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+class TestHemfPlusBrush {
+
+    /**
+     * EmfPlusPathGradientBrushData reads a 32-bit surrounding-color count 
straight
+     * from the EMF+ stream and allocates the color array before any color 
data is
+     * read. A crafted count (oversized or negative) must be rejected by the
+     * standard allocation check instead of triggering an OutOfMemoryError /
+     * NegativeArraySizeException.
+     */
+    @ParameterizedTest
+    @ValueSource(ints = { Integer.MAX_VALUE, 0xFFFFFFFF })
+    void rejectsInvalidSurroundingColorCount(int colorCount) throws Exception {
+        byte[] data = new byte[24];
+        LittleEndian.putInt(data, 0, 0);             // dataFlags
+        LittleEndian.putInt(data, 4, 0);             // wrapMode -> 
WRAP_MODE_TILE
+        LittleEndian.putInt(data, 8, 0);             // centerColor
+        // bytes 12..19: centerPoint (two floats)
+        LittleEndian.putInt(data, 20, colorCount);   // surrounding color count
+
+        EmfPlusPathGradientBrushData brush = new 
EmfPlusPathGradientBrushData();
+        try (LittleEndianInputStream leis = new LittleEndianInputStream(new 
ByteArrayInputStream(data))) {
+            assertThrows(RecordFormatException.class, () -> brush.init(leis, 
data.length));
+        }
+    }
+}
diff --git 
a/poi-scratchpad/src/test/java/org/apache/poi/hemf/record/emfplus/TestHemfPlusPath.java
 
b/poi-scratchpad/src/test/java/org/apache/poi/hemf/record/emfplus/TestHemfPlusPath.java
index 26792374c4..02706f5d3c 100644
--- 
a/poi-scratchpad/src/test/java/org/apache/poi/hemf/record/emfplus/TestHemfPlusPath.java
+++ 
b/poi-scratchpad/src/test/java/org/apache/poi/hemf/record/emfplus/TestHemfPlusPath.java
@@ -18,6 +18,7 @@
 package org.apache.poi.hemf.record.emfplus;
 
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import java.io.ByteArrayInputStream;
 
@@ -25,7 +26,10 @@ import 
org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
 import org.apache.poi.hemf.record.emfplus.HemfPlusPath.EmfPlusPath;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianInputStream;
+import org.apache.poi.util.RecordFormatException;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 class TestHemfPlusPath {
 
@@ -57,4 +61,26 @@ class TestHemfPlusPath {
             assertDoesNotThrow(() -> path.init(leis, data.length, 
EmfPlusObjectType.PATH, 0));
         }
     }
+
+    /**
+     * EmfPlusPath reads a 32-bit point count straight from the EMF+ stream and
+     * allocates the point/type arrays before any point data is read. A crafted
+     * count (oversized or negative) must be rejected by the standard 
allocation
+     * check instead of triggering an OutOfMemoryError / 
NegativeArraySizeException.
+     */
+    @ParameterizedTest
+    @ValueSource(ints = { Integer.MAX_VALUE, 0xFFFFFFFF })
+    void rejectsInvalidPointCount(int pointCount) throws Exception {
+        byte[] data = new byte[12];
+        // EmfPlusGraphicsVersion: metafile signature 0xDBC01, graphics 
version 1
+        LittleEndian.putInt(data, 0, 0xDBC01001);
+        LittleEndian.putInt(data, 4, pointCount);
+        // remaining 4 bytes: pointFlags (2) + reserved (2)
+
+        EmfPlusPath path = new EmfPlusPath();
+        try (LittleEndianInputStream leis = new LittleEndianInputStream(new 
ByteArrayInputStream(data))) {
+            assertThrows(RecordFormatException.class,
+                    () -> path.init(leis, data.length, EmfPlusObjectType.PATH, 
0));
+        }
+    }
 }


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

Reply via email to