Author: centic Date: Mon Sep 18 06:38:37 2023 New Revision: 1912383 URL: http://svn.apache.org/viewvc?rev=1912383&view=rev Log: Bug 66425: Avoid exceptions found via poi-fuzz
We try to avoid throwing NullPointerException, ClassCastExceptions and StackOverflowException, but it was possible to trigger them Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61562 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=62068 Added: poi/trunk/test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5074346559012864.doc (with props) poi/trunk/test-data/document/clusterfuzz-testcase-minimized-POIXWPFFuzzer-6733884933668864.docx (with props) poi/trunk/test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-5962760801091584.ppt (with props) poi/trunk/test-data/spreadsheet/clusterfuzz-testcase-minimized-XLSX2CSVFuzzer-6594557414080512.xlsx (with props) Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/POIXMLRelation.java poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/extractor/POIXMLExtractorFactory.java poi/trunk/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java poi/trunk/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java poi/trunk/test-data/spreadsheet/stress.xls Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/POIXMLRelation.java URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/POIXMLRelation.java?rev=1912383&r1=1912382&r2=1912383&view=diff ============================================================================== --- poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/POIXMLRelation.java (original) +++ poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/POIXMLRelation.java Mon Sep 18 06:38:37 2023 @@ -198,6 +198,9 @@ public abstract class POIXMLRelation { * @since 3.16-beta3 */ public InputStream getContents(PackagePart corePart) throws IOException, InvalidFormatException { + if (corePart == null) { + throw new IllegalArgumentException("Core-Part cannot be empty"); + } PackageRelationshipCollection prc = corePart.getRelationshipsByType(getRelation()); Iterator<PackageRelationship> it = prc.iterator(); Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/extractor/POIXMLExtractorFactory.java URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/extractor/POIXMLExtractorFactory.java?rev=1912383&r1=1912382&r2=1912383&view=diff ============================================================================== --- poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/extractor/POIXMLExtractorFactory.java (original) +++ poi/trunk/poi-ooxml/src/main/java/org/apache/poi/ooxml/extractor/POIXMLExtractorFactory.java Mon Sep 18 06:38:37 2023 @@ -229,7 +229,7 @@ public final class POIXMLExtractorFactor // Grab the core document part, and try to identify from that final PackagePart corePart = pkg.getPart(core.getRelationship(0)); - final String contentType = corePart.getContentType(); + final String contentType = corePart == null ? null : corePart.getContentType(); // Is it XSSF? for (XSSFRelation rel : XSSFExcelExtractor.SUPPORTED_TYPES) { Modified: poi/trunk/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java URL: http://svn.apache.org/viewvc/poi/trunk/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java?rev=1912383&r1=1912382&r2=1912383&view=diff ============================================================================== --- poi/trunk/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java (original) +++ poi/trunk/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java Mon Sep 18 06:38:37 2023 @@ -22,8 +22,6 @@ import java.lang.reflect.Method; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.dom.DOMSource; @@ -53,10 +51,11 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; @Beta -public class WordToTextConverter extends AbstractWordConverter -{ +public class WordToTextConverter extends AbstractWordConverter { private static final Logger LOG = LogManager.getLogger(WordToTextConverter.class); + private static final int MAX_NESTED_CHILD_NODES = 500; + public static String getText( DirectoryNode root ) throws Exception { final HWPFDocumentCore wordDocument = AbstractWordUtils.loadDoc( root ); @@ -109,7 +108,7 @@ public class WordToTextConverter extends serializer.transform( domSource, streamResult ); } - private static Document process( File docFile ) throws IOException, ParserConfigurationException { + private static Document process( File docFile ) throws IOException { try (final HWPFDocumentCore wordDocument = AbstractWordUtils.loadDoc( docFile )) { WordToTextConverter wordToTextConverter = new WordToTextConverter( XMLHelper.newDocumentBuilder().newDocument()); @@ -118,7 +117,7 @@ public class WordToTextConverter extends } } - private AtomicInteger noteCounters = new AtomicInteger( 1 ); + private final AtomicInteger noteCounters = new AtomicInteger( 1 ); private Element notes; @@ -130,11 +129,8 @@ public class WordToTextConverter extends * Creates new instance of {@link WordToTextConverter}. Can be used for * output several {@link HWPFDocument}s into single text document. * - * @throws ParserConfigurationException - * if an internal {@link DocumentBuilder} cannot be created */ - public WordToTextConverter() throws ParserConfigurationException - { + public WordToTextConverter() { this.textDocumentFacade = new TextDocumentFacade( XMLHelper.newDocumentBuilder().newDocument() ); } @@ -312,6 +308,12 @@ public class WordToTextConverter extends Element note = textDocumentFacade.createBlock(); notes.appendChild( note ); + // avoid StackOverflowException with very deeply nested files (mostly synthetic test files via fuzzing) + // if this limit is reached in real-word documents, we can make this configurable + if (note.getParentNode() != null && note.getParentNode().getChildNodes().getLength() > MAX_NESTED_CHILD_NODES) { + throw new IllegalStateException("Had more than the limit of " + MAX_NESTED_CHILD_NODES + " nested child notes"); + } + note.appendChild( textDocumentFacade.createText( "^" + noteIndex + "\t " ) ); processCharacters( wordDocument, Integer.MIN_VALUE, noteTextRange, note ); Modified: poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java URL: http://svn.apache.org/viewvc/poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java?rev=1912383&r1=1912382&r2=1912383&view=diff ============================================================================== --- poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java (original) +++ poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java Mon Sep 18 06:38:37 2023 @@ -35,6 +35,7 @@ import java.util.stream.Stream; import org.apache.poi.POIDataSamples; import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException; +import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.hslf.exceptions.OldPowerPointFormatException; import org.apache.poi.util.IOUtils; import org.apache.commons.io.output.NullPrintStream; @@ -65,6 +66,7 @@ public abstract class BaseTestPPTIterati EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6710128412590080.ppt", RuntimeException.class); EXCLUDED.put("clusterfuzz-testcase-minimized-POIFuzzer-5429732352851968.ppt", FileNotFoundException.class); EXCLUDED.put("clusterfuzz-testcase-minimized-POIFuzzer-5681320547975168.ppt", FileNotFoundException.class); + EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-5962760801091584.ppt", RuntimeException.class); } public static Stream<Arguments> files() { Modified: poi/trunk/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java?rev=1912383&r1=1912382&r2=1912383&view=diff ============================================================================== --- poi/trunk/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java (original) +++ poi/trunk/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java Mon Sep 18 06:38:37 2023 @@ -50,6 +50,8 @@ public final class EscherContainerRecord private static final Logger LOGGER = LogManager.getLogger(EscherContainerRecord.class); + private static final int MAX_NESTED_CHILD_NODES = 1000; + /** * in case if document contains any charts we have such document structure: * BOF @@ -86,12 +88,26 @@ public final class EscherContainerRecord @Override public int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory) { + return fillFields(data, pOffset, recordFactory, 0); + } + + private 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"); + } int bytesRemaining = readHeader(data, pOffset); int bytesWritten = 8; int offset = pOffset + 8; while (bytesRemaining > 0 && offset < data.length) { 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; Added: poi/trunk/test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5074346559012864.doc URL: http://svn.apache.org/viewvc/poi/trunk/test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5074346559012864.doc?rev=1912383&view=auto ============================================================================== Binary file - no diff available. Propchange: poi/trunk/test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5074346559012864.doc ------------------------------------------------------------------------------ svn:mime-type = application/msword Added: poi/trunk/test-data/document/clusterfuzz-testcase-minimized-POIXWPFFuzzer-6733884933668864.docx URL: http://svn.apache.org/viewvc/poi/trunk/test-data/document/clusterfuzz-testcase-minimized-POIXWPFFuzzer-6733884933668864.docx?rev=1912383&view=auto ============================================================================== Binary file - no diff available. Propchange: poi/trunk/test-data/document/clusterfuzz-testcase-minimized-POIXWPFFuzzer-6733884933668864.docx ------------------------------------------------------------------------------ --- svn:mime-type (added) +++ svn:mime-type Mon Sep 18 06:38:37 2023 @@ -0,0 +1 @@ +application/vnd.openxmlformats-officedocument.wordprocessingml.document Added: poi/trunk/test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-5962760801091584.ppt URL: http://svn.apache.org/viewvc/poi/trunk/test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-5962760801091584.ppt?rev=1912383&view=auto ============================================================================== Binary file - no diff available. Propchange: poi/trunk/test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-5962760801091584.ppt ------------------------------------------------------------------------------ svn:mime-type = application/vnd.ms-powerpoint Added: poi/trunk/test-data/spreadsheet/clusterfuzz-testcase-minimized-XLSX2CSVFuzzer-6594557414080512.xlsx URL: http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/clusterfuzz-testcase-minimized-XLSX2CSVFuzzer-6594557414080512.xlsx?rev=1912383&view=auto ============================================================================== Binary file - no diff available. Propchange: poi/trunk/test-data/spreadsheet/clusterfuzz-testcase-minimized-XLSX2CSVFuzzer-6594557414080512.xlsx ------------------------------------------------------------------------------ --- svn:mime-type (added) +++ svn:mime-type Mon Sep 18 06:38:37 2023 @@ -0,0 +1 @@ +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Modified: poi/trunk/test-data/spreadsheet/stress.xls URL: http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/stress.xls?rev=1912383&r1=1912382&r2=1912383&view=diff ============================================================================== Binary files - no diff available. --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
