From 88bbfbb3f747e2f18768e928facf11712ab7b4c7 Mon Sep 17 00:00:00 2001 From: Dominik Stadler Date: Mon, 18 Sep 2023 06:38:37 +0000 Subject: 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 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1912383 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hwpf/converter/WordToTextConverter.java | 22 ++++++++++++---------- .../apache/poi/hslf/dev/BaseTestPPTIterating.java | 2 ++ 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'poi-scratchpad') diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java index ddd7ff68d5..8cb7579621 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java @@ -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 AbstractWordConverter 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 AbstractWordConverter } } - private AtomicInteger noteCounters = new AtomicInteger( 1 ); + private final AtomicInteger noteCounters = new AtomicInteger( 1 ); private Element notes; @@ -130,11 +129,8 @@ public class WordToTextConverter extends AbstractWordConverter * 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 AbstractWordConverter 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 ); diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java index 7848f688cd..ef146dda23 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java @@ -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 BaseTestPPTIterating { 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 files() { -- cgit v1.2.3