mirror of https://github.com/apache/poi.git
Bug 66425: Avoid a ClassCastException found via oss-fuzz
We try to avoid throwing NullPointerException, 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=61266 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1911523 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f3997b49ef
commit
163ff25594
|
@ -18,6 +18,7 @@
|
|||
package org.apache.poi.integration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
@ -26,6 +27,7 @@ import java.nio.charset.StandardCharsets;
|
|||
|
||||
import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
|
||||
import org.apache.poi.examples.xssf.eventusermodel.XLSX2CSV;
|
||||
import org.apache.poi.ooxml.POIXMLException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackageAccess;
|
||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
|
@ -94,6 +96,25 @@ public class TestXLSX2CSV {
|
|||
assertTrue(output.contains(",\"hello, xssf\",,\"hello, xssf\""), "Had: " + output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidSampleFile() throws Exception {
|
||||
final UnsynchronizedByteArrayOutputStream outputBytes = UnsynchronizedByteArrayOutputStream.builder().get();
|
||||
PrintStream out = new PrintStream(outputBytes, true, StandardCharsets.UTF_8.name());
|
||||
|
||||
// The package open is instantaneous, as it should be.
|
||||
try (OPCPackage p = OPCPackage.open(XSSFTestDataSamples.getSampleFile("clusterfuzz-testcase-minimized-XLSX2CSVFuzzer-5025401116950528.xlsx").getAbsolutePath(), PackageAccess.READ)) {
|
||||
XLSX2CSV xlsx2csv = new XLSX2CSV(p, out, -1);
|
||||
assertThrows(POIXMLException.class,
|
||||
xlsx2csv::process);
|
||||
}
|
||||
|
||||
String errorOutput = errorBytes.toString(StandardCharsets.UTF_8);
|
||||
assertEquals("", errorOutput);
|
||||
|
||||
String output = outputBytes.toString(StandardCharsets.UTF_8);
|
||||
assertEquals("", output, "Had: " + output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinColumns() throws Exception {
|
||||
final UnsynchronizedByteArrayOutputStream outputBytes = UnsynchronizedByteArrayOutputStream.builder().get();
|
||||
|
|
|
@ -235,7 +235,7 @@ public class TestAllFiles {
|
|||
@SuppressWarnings("unchecked")
|
||||
private static void verify(String file, Executable exec, Class<? extends Throwable> exClass, String exMessage, String password,
|
||||
FileHandler fileHandler) {
|
||||
final String errPrefix = file + " - failed for handler " + fileHandler.getClass().getSimpleName() + ": ";
|
||||
final String errPrefix = file.replace("\\", "/") + " - failed for handler " + fileHandler.getClass().getSimpleName() + ": ";
|
||||
// this also removes the password for non encrypted files
|
||||
Biff8EncryptionKey.setCurrentUserPassword(password);
|
||||
if (exClass != null && AssertionFailedError.class.isAssignableFrom(exClass)) {
|
||||
|
|
|
@ -251,7 +251,9 @@ public class ReadOnlySharedStringsTable extends DefaultHandler implements Shared
|
|||
this.strings = new ArrayList<>(this.uniqueCount);
|
||||
characters = new StringBuilder(64);
|
||||
} else if ("si".equals(localName)) {
|
||||
characters.setLength(0);
|
||||
if (characters != null) {
|
||||
characters.setLength(0);
|
||||
}
|
||||
} else if ("t".equals(localName)) {
|
||||
tIsOpen = true;
|
||||
} else if ("rPh".equals(localName)) {
|
||||
|
@ -269,7 +271,9 @@ public class ReadOnlySharedStringsTable extends DefaultHandler implements Shared
|
|||
}
|
||||
|
||||
if ("si".equals(localName)) {
|
||||
strings.add(characters.toString());
|
||||
if (strings != null && characters != null) {
|
||||
strings.add(characters.toString());
|
||||
}
|
||||
} else if ("t".equals(localName)) {
|
||||
tIsOpen = false;
|
||||
} else if ("rPh".equals(localName)) {
|
||||
|
@ -285,7 +289,9 @@ public class ReadOnlySharedStringsTable extends DefaultHandler implements Shared
|
|||
if (inRPh && includePhoneticRuns) {
|
||||
characters.append(ch, start, length);
|
||||
} else if (! inRPh){
|
||||
characters.append(ch, start, length);
|
||||
if (characters != null) {
|
||||
characters.append(ch, start, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.apache.poi.xssf.eventusermodel;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -39,7 +40,7 @@ import org.xml.sax.SAXException;
|
|||
* Tests for {@link org.apache.poi.xssf.eventusermodel.XSSFReader}
|
||||
*/
|
||||
public final class TestReadOnlySharedStringsTable {
|
||||
private static POIDataSamples _ssTests = POIDataSamples.getSpreadSheetInstance();
|
||||
private static final POIDataSamples _ssTests = POIDataSamples.getSpreadSheetInstance();
|
||||
|
||||
@Test
|
||||
void testParse() throws Exception {
|
||||
|
@ -47,24 +48,25 @@ public final class TestReadOnlySharedStringsTable {
|
|||
List<PackagePart> parts = pkg.getPartsByName(Pattern.compile("/xl/sharedStrings.xml"));
|
||||
assertEquals(1, parts.size());
|
||||
|
||||
SharedStringsTable stbl = new SharedStringsTable(parts.get(0));
|
||||
ReadOnlySharedStringsTable rtbl = new ReadOnlySharedStringsTable(parts.get(0));
|
||||
ReadOnlySharedStringsTable rtbl2;
|
||||
try (InputStream stream = parts.get(0).getInputStream()){
|
||||
rtbl2 = new ReadOnlySharedStringsTable(stream);
|
||||
}
|
||||
try (SharedStringsTable stbl = new SharedStringsTable(parts.get(0))) {
|
||||
ReadOnlySharedStringsTable rtbl = new ReadOnlySharedStringsTable(parts.get(0));
|
||||
ReadOnlySharedStringsTable rtbl2;
|
||||
try (InputStream stream = parts.get(0).getInputStream()) {
|
||||
rtbl2 = new ReadOnlySharedStringsTable(stream);
|
||||
}
|
||||
|
||||
assertEquals(stbl.getCount(), rtbl.getCount());
|
||||
assertEquals(stbl.getUniqueCount(), rtbl.getUniqueCount());
|
||||
assertEquals(stbl.getUniqueCount(), rtbl2.getUniqueCount());
|
||||
assertEquals(stbl.getCount(), rtbl.getCount());
|
||||
assertEquals(stbl.getUniqueCount(), rtbl.getUniqueCount());
|
||||
assertEquals(stbl.getUniqueCount(), rtbl2.getUniqueCount());
|
||||
|
||||
assertEquals(stbl.getCount(), stbl.getUniqueCount());
|
||||
assertEquals(rtbl.getCount(), rtbl.getUniqueCount());
|
||||
assertEquals(rtbl.getCount(), rtbl2.getUniqueCount());
|
||||
for (int i = 0; i < stbl.getUniqueCount(); i++) {
|
||||
RichTextString i1 = stbl.getItemAt(i);
|
||||
assertEquals(i1.getString(), rtbl.getItemAt(i).getString());
|
||||
assertEquals(i1.getString(), rtbl2.getItemAt(i).getString());
|
||||
assertEquals(stbl.getCount(), stbl.getUniqueCount());
|
||||
assertEquals(rtbl.getCount(), rtbl.getUniqueCount());
|
||||
assertEquals(rtbl.getCount(), rtbl2.getUniqueCount());
|
||||
for (int i = 0; i < stbl.getUniqueCount(); i++) {
|
||||
RichTextString i1 = stbl.getItemAt(i);
|
||||
assertEquals(i1.getString(), rtbl.getItemAt(i).getString());
|
||||
assertEquals(i1.getString(), rtbl2.getItemAt(i).getString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,20 +77,21 @@ public final class TestReadOnlySharedStringsTable {
|
|||
List<PackagePart> parts = pkg.getPartsByName(Pattern.compile("/xl/sharedStrings.xml"));
|
||||
assertEquals(1, parts.size());
|
||||
|
||||
SharedStringsTable stbl = new SharedStringsTable(parts.get(0));
|
||||
ReadOnlySharedStringsTable rtbl = new ReadOnlySharedStringsTable(parts.get(0));
|
||||
ReadOnlySharedStringsTable rtbl2;
|
||||
try (InputStream stream = parts.get(0).getInputStream()) {
|
||||
rtbl2 = new ReadOnlySharedStringsTable(stream);
|
||||
}
|
||||
try (SharedStringsTable stbl = new SharedStringsTable(parts.get(0))) {
|
||||
ReadOnlySharedStringsTable rtbl = new ReadOnlySharedStringsTable(parts.get(0));
|
||||
ReadOnlySharedStringsTable rtbl2;
|
||||
try (InputStream stream = parts.get(0).getInputStream()) {
|
||||
rtbl2 = new ReadOnlySharedStringsTable(stream);
|
||||
}
|
||||
|
||||
assertEquals(stbl.getCount(), rtbl.getCount());
|
||||
assertEquals(stbl.getUniqueCount(), rtbl.getUniqueCount());
|
||||
assertEquals(stbl.getUniqueCount(), rtbl2.getUniqueCount());
|
||||
for (int i = 0; i < stbl.getUniqueCount(); i++) {
|
||||
RichTextString i1 = stbl.getItemAt(i);
|
||||
assertEquals(i1.getString(), rtbl.getItemAt(i).getString());
|
||||
assertEquals(i1.getString(), rtbl2.getItemAt(i).getString());
|
||||
assertEquals(stbl.getCount(), rtbl.getCount());
|
||||
assertEquals(stbl.getUniqueCount(), rtbl.getUniqueCount());
|
||||
assertEquals(stbl.getUniqueCount(), rtbl2.getUniqueCount());
|
||||
for (int i = 0; i < stbl.getUniqueCount(); i++) {
|
||||
RichTextString i1 = stbl.getItemAt(i);
|
||||
assertEquals(i1.getString(), rtbl.getItemAt(i).getString());
|
||||
assertEquals(i1.getString(), rtbl2.getItemAt(i).getString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,6 +133,22 @@ public final class TestReadOnlySharedStringsTable {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullPointerException() throws Exception {
|
||||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("clusterfuzz-testcase-minimized-XLSX2CSVFuzzer-5025401116950528.xlsx"))) {
|
||||
assertEmptySST(pkg);
|
||||
}
|
||||
|
||||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("clusterfuzz-testcase-minimized-XLSX2CSVFuzzer-5025401116950528.xlsx"))) {
|
||||
List<PackagePart> parts = pkg.getPartsByName(Pattern.compile("/xl/sharedStrings.xml"));
|
||||
assertEquals(1, parts.size());
|
||||
|
||||
//noinspection resource
|
||||
assertThrows(IOException.class,
|
||||
() -> new SharedStringsTable(parts.get(0)));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertEmptySST(OPCPackage pkg) throws IOException, SAXException {
|
||||
ReadOnlySharedStringsTable sst = new ReadOnlySharedStringsTable(pkg);
|
||||
assertEquals(0, sst.getCount());
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue