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 44598bd03056e3415357c8e49a614fbd8c75c2e6 Author: Dominik Stadler <[email protected]> AuthorDate: Sat Feb 21 14:29:08 2026 +0100 Avoid OOM with incorrect property sizes Add allocation check to verify size >= 0 and < 1mio Also reformat code to match general coding style Fixes https://issues.oss-fuzz.com/issues/485091380 --- .../apache/poi/hslf/dev/TestSlideIdListing.java | 1 + .../poi/hslf/dev/TestSlideShowRecordDumper.java | 1 + .../hslf/dev/TestUserEditAndPersistListing.java | 1 + .../apache/poi/ddf/AbstractEscherOptRecord.java | 36 +++++++++------------ .../main/java/org/apache/poi/ddf/EscherRecord.java | 35 ++++++++------------ ...se-minimized-POIHSLFFuzzer-4983252485210112.ppt | Bin 0 -> 8960 bytes test-data/spreadsheet/stress.xls | Bin 80896 -> 81408 bytes 7 files changed, 32 insertions(+), 42 deletions(-) diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideIdListing.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideIdListing.java index 684f4e8e42..9727196a73 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideIdListing.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideIdListing.java @@ -33,6 +33,7 @@ public class TestSlideIdListing extends BaseTestPPTIterating { LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-5306877435838464.ppt"); LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6360479850954752.ppt"); LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6028723156746240.ppt"); + LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-4983252485210112.ppt"); } @Test diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideShowRecordDumper.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideShowRecordDumper.java index f5705fe981..b2e3bc373e 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideShowRecordDumper.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideShowRecordDumper.java @@ -33,6 +33,7 @@ public class TestSlideShowRecordDumper extends BaseTestPPTIterating { static { LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6360479850954752.ppt"); LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6028723156746240.ppt"); + LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-4983252485210112.ppt"); } @Test diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestUserEditAndPersistListing.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestUserEditAndPersistListing.java index e639e292b0..a9362c7b42 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestUserEditAndPersistListing.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestUserEditAndPersistListing.java @@ -32,6 +32,7 @@ public class TestUserEditAndPersistListing extends BaseTestPPTIterating { static { LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6360479850954752.ppt"); LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6028723156746240.ppt"); + LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-4983252485210112.ppt"); } @Test diff --git a/poi/src/main/java/org/apache/poi/ddf/AbstractEscherOptRecord.java b/poi/src/main/java/org/apache/poi/ddf/AbstractEscherOptRecord.java index 536e590a2d..f10f6f24f1 100644 --- a/poi/src/main/java/org/apache/poi/ddf/AbstractEscherOptRecord.java +++ b/poi/src/main/java/org/apache/poi/ddf/AbstractEscherOptRecord.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.function.Supplier; import org.apache.poi.util.GenericRecordUtil; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; /** @@ -30,6 +31,9 @@ import org.apache.poi.util.LittleEndian; * {@link EscherTertiaryOptRecord} */ public abstract class AbstractEscherOptRecord extends EscherRecord { + // arbitrary limit, can be adjusted if it turns out to be too low + private static final int MAX_PROPERTY_SIZE = 1_000_000; + private final List<EscherProperty> properties = new ArrayList<>(); protected AbstractEscherOptRecord() {} @@ -39,21 +43,17 @@ public abstract class AbstractEscherOptRecord extends EscherRecord { properties.addAll(other.properties); } - /** * Add a property to this record. * * @param prop the escher property to add */ - public void addEscherProperty( EscherProperty prop ) - { + public void addEscherProperty( EscherProperty prop ) { properties.add( prop ); } @Override - public int fillFields( byte[] data, int offset, - EscherRecordFactory recordFactory ) - { + public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) { int bytesRemaining = readHeader( data, offset ); if (bytesRemaining < 0) { throw new IllegalStateException("Invalid value for bytesRemaining: " + bytesRemaining); @@ -72,8 +72,7 @@ public abstract class AbstractEscherOptRecord extends EscherRecord { * * @return the list of properties */ - public List<EscherProperty> getEscherProperties() - { + public List<EscherProperty> getEscherProperties() { return properties; } @@ -83,26 +82,23 @@ public abstract class AbstractEscherOptRecord extends EscherRecord { * @param index the ordinal index of the property * @return the escher property */ - public EscherProperty getEscherProperty( int index ) - { + public EscherProperty getEscherProperty( int index ) { return properties.get( index ); } - - private int getPropertiesSize() - { + private int getPropertiesSize() { int totalSize = 0; - for ( EscherProperty property : properties ) - { - totalSize += property.getPropertySize(); + for ( EscherProperty property : properties ) { + int propertySize = property.getPropertySize(); + IOUtils.safelyAllocateCheck(propertySize, MAX_PROPERTY_SIZE); + totalSize += propertySize; } return totalSize; } @Override - public int getRecordSize() - { + public int getRecordSize() { return 8 + getPropertiesSize(); } @@ -116,9 +112,7 @@ public abstract class AbstractEscherOptRecord extends EscherRecord { } @Override - public int serialize( int offset, byte[] data, - EscherSerializationListener listener ) - { + public int serialize( int offset, byte[] data, EscherSerializationListener listener ) { listener.beforeRecordSerialize( offset, getRecordId(), this ); LittleEndian.putShort( data, offset, getOptions() ); diff --git a/poi/src/main/java/org/apache/poi/ddf/EscherRecord.java b/poi/src/main/java/org/apache/poi/ddf/EscherRecord.java index de5b95b22d..4ed0974d99 100644 --- a/poi/src/main/java/org/apache/poi/ddf/EscherRecord.java +++ b/poi/src/main/java/org/apache/poi/ddf/EscherRecord.java @@ -70,8 +70,7 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * * @see #fillFields(byte[], int, org.apache.poi.ddf.EscherRecordFactory) */ - protected int fillFields( byte[] data, EscherRecordFactory f ) - { + protected int fillFields( byte[] data, EscherRecordFactory f ) { return fillFields( data, 0, f ); } @@ -154,8 +153,7 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * @return The options field for this record. All records have one. */ @Internal - public short getOptions() - { + public short getOptions() { return _options; } @@ -183,8 +181,7 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * @return the serialized record. * @see #serialize(int, byte[]) */ - public byte[] serialize() - { + public byte[] serialize() { byte[] retval = new byte[getRecordSize()]; serialize( 0, retval ); @@ -201,8 +198,7 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * * @see #serialize(int, byte[], org.apache.poi.ddf.EscherSerializationListener) */ - public int serialize( int offset, byte[] data) - { + public int serialize( int offset, byte[] data) { return serialize( offset, data, new NullEscherSerializationListener() ); } @@ -252,7 +248,9 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * * @see EscherContainerRecord */ - public List<EscherRecord> getChildRecords() { return Collections.emptyList(); } + public List<EscherRecord> getChildRecords() { + return Collections.emptyList(); + } /** * Sets the child records for this record. By default this will throw @@ -281,8 +279,7 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * @param w The print writer to output to. * @param indent The current indent level. */ - public void display(PrintWriter w, int indent) - { + public void display(PrintWriter w, int indent) { for (int i = 0; i < indent * 4; i++) { w.print(' '); } @@ -301,8 +298,7 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * * @return The instance part of the record */ - public short getInstance() - { + public short getInstance() { return fInstance.getShortValue( _options ); } @@ -311,8 +307,7 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * * @param value instance part value */ - public void setInstance( short value ) - { + public void setInstance( short value ) { _options = fInstance.setShortValue( _options, value ); } @@ -321,8 +316,7 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * * @return The version part of the option record */ - public short getVersion() - { + public short getVersion() { return fVersion.getShortValue( _options ); } @@ -331,12 +325,11 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * * @param value version part value */ - public void setVersion( short value ) - { + public void setVersion( short value ) { _options = fVersion.setShortValue( _options, value ); } - public String toXml(){ + public String toXml() { return toXml(""); } @@ -344,7 +337,7 @@ public abstract class EscherRecord implements Duplicatable, GenericRecord { * @param tab - each children must be indented right relative to its parent * @return xml representation of this record */ - public final String toXml(String tab){ + public final String toXml(String tab) { return GenericRecordXmlWriter.marshal(this); } diff --git a/test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-4983252485210112.ppt b/test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-4983252485210112.ppt new file mode 100644 index 0000000000..0bec934f7e Binary files /dev/null and b/test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-4983252485210112.ppt differ diff --git a/test-data/spreadsheet/stress.xls b/test-data/spreadsheet/stress.xls index ed7f422722..ac5b024338 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]
