]> source.dussan.org Git - poi.git/commitdiff
Bug 66425: Avoid a StackOverflowException found via oss-fuzz
authorDominik Stadler <centic@apache.org>
Wed, 9 Aug 2023 16:16:49 +0000 (16:16 +0000)
committerDominik Stadler <centic@apache.org>
Wed, 9 Aug 2023 16:16:49 +0000 (16:16 +0000)
We try to avoid causing StackOverflow, but it was possible
to trigger one here with a specially crafted input-file.

This puts a limit on the number of nested children in place
and logs a warning when the Stream is not fully parsed.

Should fix https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61256

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1911577 13f79535-47bb-0310-9956-ffa450edef68

poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/PointerContainingStream.java
test-data/diagram/clusterfuzz-testcase-minimized-POIHDGFFuzzer-5947849161179136.vsd [new file with mode: 0644]
test-data/spreadsheet/stress.xls

index 3f3192f9fc6ddd21e2e54dd12c5ad57d63beabca..c4a91ad9693ada863bfdb825a077cf318100805d 100644 (file)
@@ -17,6 +17,8 @@
 
 package org.apache.poi.hdgf.streams;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.apache.poi.hdgf.chunks.ChunkFactory;
 import org.apache.poi.hdgf.pointers.Pointer;
 import org.apache.poi.hdgf.pointers.PointerFactory;
@@ -26,11 +28,15 @@ import org.apache.poi.hdgf.pointers.PointerFactory;
  *  other data too.
  */
 public class PointerContainingStream extends Stream { // TODO - instantiable superclass
-    private Pointer[] childPointers;
+    private static final Logger LOG = LogManager.getLogger(PointerContainingStream.class);
+
+    private static final int MAX_CHILDREN_NESTING = 1000;
+
+    private final Pointer[] childPointers;
     private Stream[] childStreams;
 
-    private ChunkFactory chunkFactory;
-    private PointerFactory pointerFactory;
+    private final ChunkFactory chunkFactory;
+    private final PointerFactory pointerFactory;
 
     protected PointerContainingStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory, PointerFactory pointerFactory) {
         super(pointer, store);
@@ -58,6 +64,17 @@ public class PointerContainingStream extends Stream { // TODO - instantiable sup
      *  those if appropriate.
      */
     public void findChildren(byte[] documentData) {
+        findChildren(documentData, 0);
+    }
+
+    private void findChildren(byte[] documentData, int nesting) {
+        if (nesting > MAX_CHILDREN_NESTING) {
+            LOG.warn("Encountered too deep nesting, cannot fully process stream " +
+                    " with more than " + MAX_CHILDREN_NESTING + " nested children." +
+                    " Some data could not be parsed.");
+            return;
+        }
+
         // For each pointer, generate the Stream it points to
         childStreams = new Stream[childPointers.length];
         for(int i=0; i<childPointers.length; i++) {
@@ -74,7 +91,7 @@ public class PointerContainingStream extends Stream { // TODO - instantiable sup
             if(childStreams[i] instanceof PointerContainingStream) {
                 PointerContainingStream child =
                     (PointerContainingStream)childStreams[i];
-                child.findChildren(documentData);
+                child.findChildren(documentData, nesting + 1);
             }
         }
     }
diff --git a/test-data/diagram/clusterfuzz-testcase-minimized-POIHDGFFuzzer-5947849161179136.vsd b/test-data/diagram/clusterfuzz-testcase-minimized-POIHDGFFuzzer-5947849161179136.vsd
new file mode 100644 (file)
index 0000000..801fd68
Binary files /dev/null and b/test-data/diagram/clusterfuzz-testcase-minimized-POIHDGFFuzzer-5947849161179136.vsd differ
index e084a6c0b23cf7dee3c32553d4d9b553c520a715..b8bae8e3d9f5ea94773b646a26ca5e4e0c61a95d 100644 (file)
Binary files a/test-data/spreadsheet/stress.xls and b/test-data/spreadsheet/stress.xls differ