Skip to content

Commit

Permalink
Bug 66425: Avoid exceptions found via poi-fuzz
Browse files Browse the repository at this point in the history
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
  • Loading branch information
centic9 committed Dec 30, 2023
1 parent c63cb18 commit 8e3b60f
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public abstract class BaseTestPPTIterating {
EXCLUDED.put("clusterfuzz-testcase-minimized-POIFuzzer-6411649193738240.ppt", FileNotFoundException.class);
EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-4838893004128256.ppt", FileNotFoundException.class);
EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-4624961081573376.ppt", FileNotFoundException.class);
EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-5018229722382336.ppt", RuntimeException.class);
}

public static Stream<Arguments> files() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactor
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");
}
Expand All @@ -104,6 +104,8 @@ private int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFacto
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);
}
Expand Down
19 changes: 17 additions & 2 deletions poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ Licensed to the Apache Software Foundation (ASF) under one or more
* 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<>();
Expand Down Expand Up @@ -66,6 +67,14 @@ public UnknownEscherRecord(UnknownEscherRecord other) {

@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,
Expand All @@ -83,7 +92,13 @@ public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory
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;
Expand Down
Binary file not shown.
Binary file modified test-data/spreadsheet/stress.xls
Binary file not shown.

0 comments on commit 8e3b60f

Please sign in to comment.