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]
