From 5efa428ca0cbf421fa394c53b600d9f242d69e0f Mon Sep 17 00:00:00 2001 From: Dominik Stadler Date: Mon, 7 Aug 2023 15:15:38 +0000 Subject: [PATCH] Bug 66425: Avoid a ClassCastException found via oss-fuzz We try to avoid throwing ClassCastException, but it was possible to trigger one here with a specially crafted input-file Should fix https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61242 Also enhance output of some test-failures and allow an empty exception message git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1911515 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/stress/TestAllFiles.java | 13 +++++++------ .../poi/hssf/usermodel/HSSFShapeGroup.java | 6 +++++- .../poi/hssf/dev/BaseTestIteratingXLS.java | 4 ++-- .../poi/hssf/dev/TestBiffDrawingToXml.java | 1 + .../poi/hssf/model/TestDrawingAggregate.java | 4 +++- ...nimized-POIHSSFFuzzer-5285517825277952.xls | Bin 0 -> 47616 bytes test-data/spreadsheet/stress.xls | Bin 59904 -> 60416 bytes 7 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 test-data/spreadsheet/clusterfuzz-testcase-minimized-POIHSSFFuzzer-5285517825277952.xls diff --git a/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java b/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java index a48d0cbc29..ed96cde4e8 100644 --- a/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java +++ b/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java @@ -42,6 +42,7 @@ import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.platform.commons.util.StringUtils; import org.opentest4j.AssertionFailedError; /** @@ -251,12 +252,12 @@ public class TestAllFiles { } else if (exClass != null) { Exception e = assertThrows((Class)exClass, exec, errPrefix + " expected " + exClass); String actMsg = pathReplace(e.getMessage()); - if (NullPointerException.class.isAssignableFrom(exClass)) { - if (actMsg != null) { - assertTrue(actMsg.contains(exMessage), errPrefix + "Message: "+actMsg+" - didn't contain: "+exMessage); - } - } else { - assertNotNull(actMsg, errPrefix); + + // verify that message is either null for both or set for both + assertTrue(actMsg != null || StringUtils.isBlank(exMessage), + errPrefix + " for " + exClass + " expected message '" + exMessage + "' but had '" + actMsg + "'"); + + if (actMsg != null) { assertTrue(actMsg.contains(exMessage), errPrefix + "Message: " + actMsg + " - didn't contain: " + exMessage); } diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index ab7df1d733..1a0fca32e8 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -54,7 +54,11 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { // read internal and external coordinates from spgrContainer EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0); - _spgrRecord = (EscherSpgrRecord) spContainer.getChild(0); + final EscherRecord child = spContainer.getChild(0); + if (!(child instanceof EscherSpgrRecord)) { + throw new IllegalArgumentException("Had unexpected type of child at index 0: " + child.getClass()); + } + _spgrRecord = (EscherSpgrRecord) child; for (EscherRecord ch : spContainer) { switch (EscherRecordTypes.forTypeID(ch.getRecordId())) { case CLIENT_ANCHOR: diff --git a/poi/src/test/java/org/apache/poi/hssf/dev/BaseTestIteratingXLS.java b/poi/src/test/java/org/apache/poi/hssf/dev/BaseTestIteratingXLS.java index 5ec8a30b23..45de3c2155 100644 --- a/poi/src/test/java/org/apache/poi/hssf/dev/BaseTestIteratingXLS.java +++ b/poi/src/test/java/org/apache/poi/hssf/dev/BaseTestIteratingXLS.java @@ -102,9 +102,9 @@ public abstract class BaseTestIteratingXLS { Executable ex = () -> runOneFile(file); if (t == null) { - assertDoesNotThrow(ex); + assertDoesNotThrow(ex, "Failing file: " + file); } else { - assertThrows(t, ex); + assertThrows(t, ex, "Failing file: " + file); } } diff --git a/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffDrawingToXml.java b/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffDrawingToXml.java index 0b78830996..ea39f5147d 100644 --- a/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffDrawingToXml.java +++ b/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffDrawingToXml.java @@ -54,6 +54,7 @@ class TestBiffDrawingToXml extends BaseTestIteratingXLS { excludes.put("43493.xls", RecordInputStream.LeftoverDataException.class); excludes.put("44958_1.xls", RecordInputStream.LeftoverDataException.class); excludes.put("protected_66115.xls", EncryptedDocumentException.class); + excludes.put("clusterfuzz-testcase-minimized-POIHSSFFuzzer-5285517825277952.xls", IllegalArgumentException.class); return excludes; } diff --git a/poi/src/test/java/org/apache/poi/hssf/model/TestDrawingAggregate.java b/poi/src/test/java/org/apache/poi/hssf/model/TestDrawingAggregate.java index b904af8808..9a3bd3d649 100644 --- a/poi/src/test/java/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/poi/src/test/java/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -136,7 +136,9 @@ class TestDrawingAggregate { File[] files = testData.listFiles((dir, name) -> name.endsWith(".xls")); assertNotNull(files, "Need to find files in test-data path, had path: " + testData); - return Stream.of(files).map(Arguments::of); + return Stream.of(files). + filter(file -> !file.getName().equals("clusterfuzz-testcase-minimized-POIHSSFFuzzer-5285517825277952.xls")). + map(Arguments::of); } /** diff --git a/test-data/spreadsheet/clusterfuzz-testcase-minimized-POIHSSFFuzzer-5285517825277952.xls b/test-data/spreadsheet/clusterfuzz-testcase-minimized-POIHSSFFuzzer-5285517825277952.xls new file mode 100644 index 0000000000000000000000000000000000000000..544c22f3995d32ebc654f680bcb16f2acf909d57 GIT binary patch literal 47616 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