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

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

commit 017ff5f8f8a78643e8d7c33df5533d179eeb2601
Author: Dominik Stadler <[email protected]>
AuthorDate: Fri Jan 9 16:05:12 2026 +0100

    Implement lazy allocation of data for complex escher properties
    
    This may reduce memory usage if the content is never used
    or not populated for some reason.
    
    This should fix https://issues.oss-fuzz.com/issues/42528528
---
 .../hwpf/converter/TestWordToConverterSuite.java   |   3 +-
 .../hwpf/converter/TestWordToTextConverter.java    |   3 +-
 .../org/apache/poi/ddf/EscherComplexProperty.java  |  51 +++++++++++++++++----
 src/resources/ooxml-lite-report.clazz              |   2 +
 src/resources/ooxml-lite-report.xsb                |   1 +
 ...se-minimized-POIHWPFFuzzer-5832867957309440.doc | Bin 0 -> 4748 bytes
 test-data/spreadsheet/stress.xls                   | Bin 74752 -> 75264 bytes
 7 files changed, 50 insertions(+), 10 deletions(-)

diff --git 
a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java
 
b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java
index 9cfb4b6d11..56665c679d 100644
--- 
a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java
+++ 
b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java
@@ -61,7 +61,8 @@ public class TestWordToConverterSuite {
         "clusterfuzz-testcase-minimized-POIHWPFFuzzer-4947285593948160.doc",
         "clusterfuzz-testcase-minimized-POIHWPFFuzzer-5440721166139392.doc",
         "clusterfuzz-testcase-minimized-POIHWPFFuzzer-5050208641482752.doc",
-        "clusterfuzz-testcase-minimized-POIHWPFFuzzer-6610789829836800.doc"
+        "clusterfuzz-testcase-minimized-POIHWPFFuzzer-6610789829836800.doc",
+        "clusterfuzz-testcase-minimized-POIHWPFFuzzer-5832867957309440.doc"
     );
 
     public static Stream<Arguments> files() {
diff --git 
a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToTextConverter.java
 
b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToTextConverter.java
index 9e66096b3c..c2bd0582ba 100644
--- 
a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToTextConverter.java
+++ 
b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToTextConverter.java
@@ -54,7 +54,8 @@ public class TestWordToTextConverter {
         "clusterfuzz-testcase-minimized-POIHWPFFuzzer-4947285593948160.doc",
         "clusterfuzz-testcase-minimized-POIHWPFFuzzer-5440721166139392.doc",
         "clusterfuzz-testcase-minimized-POIHWPFFuzzer-5050208641482752.doc",
-        "clusterfuzz-testcase-minimized-POIHWPFFuzzer-6610789829836800.doc"
+        "clusterfuzz-testcase-minimized-POIHWPFFuzzer-6610789829836800.doc",
+        "clusterfuzz-testcase-minimized-POIHWPFFuzzer-5832867957309440.doc"
     );
 
     /**
diff --git a/poi/src/main/java/org/apache/poi/ddf/EscherComplexProperty.java 
b/poi/src/main/java/org/apache/poi/ddf/EscherComplexProperty.java
index c001707c6c..675bc7d49c 100644
--- a/poi/src/main/java/org/apache/poi/ddf/EscherComplexProperty.java
+++ b/poi/src/main/java/org/apache/poi/ddf/EscherComplexProperty.java
@@ -35,6 +35,7 @@ public class EscherComplexProperty extends EscherProperty {
     private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000_000;
     private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
 
+    private int complexSize;
     private byte[] complexData;
 
     /**
@@ -61,7 +62,15 @@ public class EscherComplexProperty extends EscherProperty {
      */
     public EscherComplexProperty(short id, int complexSize) {
         super((short)(id | IS_COMPLEX));
-        complexData = IOUtils.safelyAllocate(complexSize, MAX_RECORD_LENGTH);
+
+        // lazy-allocate the data
+        this.complexSize = complexSize;
+    }
+
+    private void ensureComplexData() {
+        if (this.complexData == null) {
+            complexData = IOUtils.safelyAllocate(complexSize, 
MAX_RECORD_LENGTH);
+        }
     }
 
     /**
@@ -94,7 +103,7 @@ public class EscherComplexProperty extends EscherProperty {
     @Override
     public int serializeSimplePart(byte[] data, int pos) {
         LittleEndian.putShort(data, pos, getId());
-        LittleEndian.putInt(data, pos + 2, complexData.length);
+        LittleEndian.putInt(data, pos + 2, complexSize);
         return 6;
     }
 
@@ -107,8 +116,13 @@ public class EscherComplexProperty extends EscherProperty {
      */
     @Override
     public int serializeComplexPart(byte[] data, int pos) {
-        System.arraycopy(complexData, 0, data, pos, complexData.length);
-        return complexData.length;
+        if (complexData == null) {
+            // initialize empty array if complexData was never allocated
+            Arrays.fill(data, pos, pos + complexSize, (byte)0);
+        } else {
+            System.arraycopy(complexData, 0, data, pos, complexData.length);
+        }
+        return complexSize;
     }
 
     /**
@@ -117,6 +131,7 @@ public class EscherComplexProperty extends EscherProperty {
      * @return the complex bytes
      */
     public byte[] getComplexData() {
+        ensureComplexData();
         return complexData;
     }
 
@@ -128,25 +143,31 @@ public class EscherComplexProperty extends EscherProperty 
{
         if (complexData == null) {
             return 0;
         } else {
+            ensureComplexData();
             int copySize = Math.max(0, Math.min(this.complexData.length, 
complexData.length - offset));
             System.arraycopy(complexData, offset, this.complexData, 0, 
copySize);
             return copySize;
         }
     }
 
-
-
     protected void resizeComplexData(int newSize) {
         resizeComplexData(newSize, Integer.MAX_VALUE);
     }
 
     protected void resizeComplexData(int newSize, int copyLen) {
-        if (newSize == complexData.length) {
+        if (newSize == complexSize) {
+            return;
+        }
+
+        // no need to copy if data was not initialized yet
+        if (complexData == null) {
             return;
         }
+
         byte[] newArray = IOUtils.safelyAllocate(newSize, MAX_RECORD_LENGTH);
         System.arraycopy(complexData, 0, newArray, 0, 
Math.min(Math.min(complexData.length, copyLen),newSize));
         complexData = newArray;
+        complexSize = newSize;
     }
 
     /**
@@ -166,6 +187,18 @@ public class EscherComplexProperty extends EscherProperty {
 
         EscherComplexProperty escherComplexProperty = (EscherComplexProperty) 
o;
 
+        // not equal if size differs
+        if (complexSize != escherComplexProperty.complexSize) {
+            return false;
+        }
+
+        if (complexData == null) {
+            // if coomplexData is not initialized, it is equal only if
+            // complexData is also uninitialized or equals an empty array
+            return escherComplexProperty.complexData == null ||
+                    Arrays.equals(escherComplexProperty.complexData, new 
byte[escherComplexProperty.complexSize]);
+        }
+
         return Arrays.equals(complexData, escherComplexProperty.complexData);
     }
 
@@ -176,16 +209,18 @@ public class EscherComplexProperty extends EscherProperty 
{
      */
     @Override
     public int getPropertySize() {
-        return 6 + complexData.length;
+        return 6 + complexSize;
     }
 
     @Override
     public int hashCode() {
+        ensureComplexData();
         return Arrays.deepHashCode(new Object[]{complexData, getId()});
     }
 
     @Override
     public Map<String, Supplier<?>> getGenericProperties() {
+        ensureComplexData();
         return GenericRecordUtil.getGenericProperties(
             "base", super::getGenericProperties,
             "data", this::getComplexData
diff --git a/src/resources/ooxml-lite-report.clazz 
b/src/resources/ooxml-lite-report.clazz
index 144216dba8..444e098823 100644
--- a/src/resources/ooxml-lite-report.clazz
+++ b/src/resources/ooxml-lite-report.clazz
@@ -2551,3 +2551,5 @@ 
org/openxmlformats/schemas/drawingml/x2006/main/impl/CTAudioFileImpl
 org/openxmlformats/schemas/drawingml/x2006/main/CTAudioFile
 org/openxmlformats/schemas/drawingml/x2006/chart/impl/STHoleSizePercentImpl
 org/openxmlformats/schemas/drawingml/x2006/chart/impl/STHoleSizeUByteImpl
+org/openxmlformats/schemas/drawingml/x2006/main/CTSupplementalFont
+org/openxmlformats/schemas/drawingml/x2006/main/impl/CTSupplementalFontImpl
diff --git a/src/resources/ooxml-lite-report.xsb 
b/src/resources/ooxml-lite-report.xsb
index 7f3d358103..2120d975b8 100644
--- a/src/resources/ooxml-lite-report.xsb
+++ b/src/resources/ooxml-lite-report.xsb
@@ -1186,3 +1186,4 @@ ctindex5371type
 stholesizepercenta3d2type
 stholesizeubyte577atype
 chartspace67aadoctype
+ctsupplementalfonta06etype
diff --git 
a/test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5832867957309440.doc
 
b/test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5832867957309440.doc
new file mode 100644
index 0000000000..4f2d6de96c
Binary files /dev/null and 
b/test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5832867957309440.doc
 differ
diff --git a/test-data/spreadsheet/stress.xls b/test-data/spreadsheet/stress.xls
index 6fb06f73a6..94775397c8 100644
Binary files a/test-data/spreadsheet/stress.xls and 
b/test-data/spreadsheet/stress.xls differ


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

Reply via email to