diff options
author | Dominik Stadler <centic@apache.org> | 2023-12-30 11:11:32 +0000 |
---|---|---|
committer | Dominik Stadler <centic@apache.org> | 2023-12-30 11:11:32 +0000 |
commit | 8e3b60f63d21458c59b9bf10dde10dcc2fa928b0 (patch) | |
tree | 56b4d1d9028fef4a63865de0b0458a2fedafec88 /poi | |
parent | c63cb1846c7d7e1168abf221c831ea89b8ef6cd1 (diff) | |
download | poi-8e3b60f63d21458c59b9bf10dde10dcc2fa928b0.tar.gz poi-8e3b60f63d21458c59b9bf10dde10dcc2fa928b0.zip |
Bug 66425: Avoid exceptions found via poi-fuzz
Prevent StackOverflow via endless nesting
Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65303
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1914989 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'poi')
-rw-r--r-- | poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java | 4 | ||||
-rw-r--r-- | poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java | 19 |
2 files changed, 20 insertions, 3 deletions
diff --git a/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java b/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java index da4d2a3289..ab30e2c404 100644 --- a/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java +++ b/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java @@ -91,7 +91,7 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl return fillFields(data, pOffset, recordFactory, 0); } - private int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory, int nesting) { + int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory, int nesting) { if (nesting > MAX_NESTED_CHILD_NODES) { throw new IllegalStateException("Had more than the limit of " + MAX_NESTED_CHILD_NODES + " nested child notes"); } @@ -104,6 +104,8 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl final int childBytesWritten; if (child instanceof EscherContainerRecord) { childBytesWritten = ((EscherContainerRecord)child).fillFields(data, offset, recordFactory, nesting + 1); + } else if (child instanceof UnknownEscherRecord) { + childBytesWritten = ((UnknownEscherRecord)child).fillFields(data, offset, recordFactory, nesting + 1); } else { childBytesWritten = child.fillFields(data, offset, recordFactory); } diff --git a/poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java b/poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java index c6e71ea099..475cfdecae 100644 --- a/poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java +++ b/poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java @@ -32,13 +32,14 @@ import org.apache.poi.util.LittleEndian; * we do not explicitly support. */ public final class UnknownEscherRecord extends EscherRecord { - //arbitrarily selected; may need to increase private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000_000; private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH; private static final byte[] NO_BYTES = new byte[0]; + private static final int MAX_NESTED_CHILD_NODES = 1000; + /** The data for this record not including the 8 byte header */ private byte[] thedata = NO_BYTES; private final List<EscherRecord> _childRecords = new ArrayList<>(); @@ -66,6 +67,14 @@ public final class UnknownEscherRecord extends EscherRecord { @Override public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { + return fillFields(data, offset, recordFactory, 0); + } + + int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory, int nesting) { + if (nesting > MAX_NESTED_CHILD_NODES) { + throw new IllegalStateException("Had more than the limit of " + MAX_NESTED_CHILD_NODES + " nested child notes"); + } + int bytesRemaining = readHeader( data, offset ); /* * Have a check between available bytes and bytesRemaining, @@ -83,7 +92,13 @@ public final class UnknownEscherRecord extends EscherRecord { bytesWritten += 8; while ( bytesRemaining > 0 ) { EscherRecord child = recordFactory.createRecord( data, offset ); - int childBytesWritten = child.fillFields( data, offset, recordFactory ); + final int childBytesWritten; + + if (child instanceof EscherContainerRecord) { + childBytesWritten = ((EscherContainerRecord)child).fillFields(data, offset, recordFactory, nesting + 1); + } else { + childBytesWritten = child.fillFields(data, offset, recordFactory); + } bytesWritten += childBytesWritten; offset += childBytesWritten; bytesRemaining -= childBytesWritten; |