]> source.dussan.org Git - poi.git/commitdiff
Fix issues found when fuzzing Apache POI via Jazzer
authorDominik Stadler <centic@apache.org>
Sun, 5 Dec 2021 17:34:19 +0000 (17:34 +0000)
committerDominik Stadler <centic@apache.org>
Sun, 5 Dec 2021 17:34:19 +0000 (17:34 +0000)
Check for negative array allocation size or access and report a more meaningful exception

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

poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/CompressedStreamStore.java
poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java
poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/Ffn.java
poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/LFOData.java
poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/StyleSheet.java
poi/src/main/java/org/apache/poi/hssf/record/RecordFactory.java
poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java
poi/src/main/java/org/apache/poi/hssf/record/chart/ChartFRTInfoRecord.java
poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFRow.java
poi/src/main/java/org/apache/poi/poifs/filesystem/BlockStore.java
poi/src/main/java/org/apache/poi/ss/formula/constant/ConstantValueParser.java

index 91ea0400e0ce40327219e4252b33f8d0f1d763bb..fc1057f8394ca0c600cda55bd49680ae2380ad73 100644 (file)
@@ -58,7 +58,7 @@ public final class CompressedStreamStore extends StreamStore {
     public static int getMaxRecordLength() {
         return MAX_RECORD_LENGTH;
     }
-    
+
     /**
      * Creates a new compressed StreamStore, which will handle
      *  the decompression.
@@ -98,6 +98,10 @@ public final class CompressedStreamStore extends StreamStore {
         HDGFLZW lzw = new HDGFLZW();
         byte[] decompressed = lzw.decompress(bais);
 
+        if (decompressed.length < 4) {
+            throw new IllegalArgumentException("Could not read enough data to decompress: " + decompressed.length);
+        }
+
         // Split into header and contents
         byte[][] ret = new byte[2][];
         ret[0] = new byte[4];
index cd039cf36da8509b3aec07ef1ae510e3ee9a6aed..0879e394cf4abfa3c4b25914aad5cc6696f8134b 100644 (file)
@@ -45,6 +45,9 @@ public abstract class QCPLCBit extends QCBit {
 
         // First four bytes are the number
         numberOfPLCs = (int)LittleEndian.getUInt(data, 0);
+        if (numberOfPLCs < 0) {
+            throw new IllegalArgumentException("Invalid number of PLCs: " + numberOfPLCs);
+        }
 
         // Next four bytes are the type
         typeOfPLCS = (int)LittleEndian.getUInt(data, 4);
@@ -86,7 +89,7 @@ public abstract class QCPLCBit extends QCBit {
         this.plcValB = plcValB.clone();
     }
 
-    
+
 
     public static QCPLCBit createQCPLCBit(String thingType, String bitType, byte[] data) {
         // Grab the type
@@ -217,7 +220,7 @@ public abstract class QCPLCBit extends QCBit {
             super(thingType, bitType, data);
 
             int cntPlcs = getNumberOfPLCs();
-            
+
             // How many hyperlinks do we really have?
             // (zero hyperlinks gets numberOfPLCs=1)
             hyperlinks = new String[data.length == 0x34 ? 0 : cntPlcs];
index bea8b2e581082c9c95d90cf5e72a238b6ad3f13d..7c30f2346ad2f286296d4baa59a718e998cd02d0 100644 (file)
@@ -76,6 +76,11 @@ public final class Ffn {
 
         offsetTmp = offset - offsetTmp;
         _xszFfnLength = (this.getSize() - offsetTmp) / 2;
+
+        if (_xszFfnLength < 0) {
+            throw new IllegalArgumentException("Had invalid computed size: " + _xszFfnLength + " with size " + getSize() + " and offsetTmp: " + offsetTmp);
+        }
+
         _xszFfn = new char[_xszFfnLength];
 
         for (int i = 0; i < _xszFfnLength; i++) {
index 0e8cca03a418cc6c21eae0e23bc0ccd88c4b87d2..726e67d7def720f48830a702a055037a7cb4df25 100644 (file)
@@ -43,8 +43,11 @@ public class LFOData
         _rgLfoLvl = new ListFormatOverrideLevel[0];
     }
 
-    LFOData( byte[] buf, int startOffset, int cLfolvl )
-    {
+    LFOData( byte[] buf, int startOffset, int cLfolvl ) {
+        if (cLfolvl < 0) {
+            throw new IllegalArgumentException("Cannot create LFOData with negative count");
+        }
+
         int offset = startOffset;
 
         _cp = LittleEndian.getInt( buf, offset );
index 18d703c835ccb3e2b2d4cc11a8153ce4a66f0b3e..c9b8880f281794e6791cabad67375d05d3812d8a 100644 (file)
@@ -88,6 +88,10 @@ public final class StyleSheet {
 
         _stshif = new Stshif(tableStream, offset);
 
+        if (_stshif.getCstd() < 0) {
+            throw new IllegalArgumentException("Cannot create StyleSheet, invalid Cstd: " + _stshif.getCstd());
+        }
+
         // shall we discard cbLSD and mpstilsd?
 
         offset = startOffset + LittleEndianConsts.SHORT_SIZE + _cbStshi;
index 86014c4d2bf460c5a30667b8d8c61d246708d5c0..0828e465371879242c4bd3ed12835ce735274537 100644 (file)
@@ -22,6 +22,8 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.poi.util.RecordFormatException;
+
 /**
  * Title:  Record Factory<p>
  * Description:  Takes a stream and outputs an array of Record objects.
@@ -103,6 +105,10 @@ public final class RecordFactory {
      * @return the equivalent array of {@link NumberRecord NumberRecords}
      */
     public static NumberRecord[] convertRKRecords(MulRKRecord mrk) {
+        if (mrk.getNumColumns() < 0) {
+            throw new RecordFormatException("Cannot create RKRecords with negative number of columns: " + mrk.getNumColumns());
+        }
+
         NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()];
         for (int k = 0; k < mrk.getNumColumns(); k++) {
             NumberRecord nr = new NumberRecord();
@@ -156,7 +162,7 @@ public final class RecordFactory {
      *
      * @exception org.apache.poi.util.RecordFormatException on error processing the InputStream
      */
-    public static List<org.apache.poi.hssf.record.Record> createRecords(InputStream in) throws org.apache.poi.util.RecordFormatException {
+    public static List<org.apache.poi.hssf.record.Record> createRecords(InputStream in) throws RecordFormatException {
 
         List<org.apache.poi.hssf.record.Record> records = new ArrayList<>(NUM_RECORDS);
 
index 62535e50b8e083dc1696a68747c1fa20b43595fb..b83100845b2307ec57743588975b657f3ca381fe 100644 (file)
@@ -330,7 +330,10 @@ public final class RecordInputStream implements LittleEndianInput {
                 } else {
                     nextRecord();
                     nextChunk = Math.min(available(),len);
-                    assert(nextChunk > 0);
+                    if (nextChunk <= 0) {
+                        throw new RecordFormatException("Need to have a valid next chunk, but had: " + nextChunk +
+                                " with len: " + len + " and available: " + available());
+                    }
                 }
             }
             checkRecordPosition(nextChunk);
index ed6e6c91d568b64d0660fe1fc2479da53f2735e6..7d8dfd53559bd817395cfe10966556fad0548c11 100644 (file)
@@ -78,6 +78,9 @@ public final class ChartFRTInfoRecord extends StandardRecord {
         verOriginator = in.readByte();
         verWriter = in.readByte();
         int cCFRTID = in.readShort();
+        if (cCFRTID < 0) {
+            throw new IllegalArgumentException("Had negative CFRTID: " + cCFRTID);
+        }
 
         rgCFRTID = new CFRTID[cCFRTID];
         for (int i = 0; i < cCFRTID; i++) {
index 3487e31595bbbf87db472b535d5c74661a8ae9c9..4a28ca4668c52ba41d4a0d773edbf0edaf7da714 100644 (file)
@@ -96,6 +96,10 @@ public final class HSSFRow implements Row, Comparable<HSSFRow> {
         row = record;
         setRowNum(record.getRowNumber());
 
+        if (record.getLastCol() < 0 || INITIAL_CAPACITY < 0) {
+            throw new IllegalArgumentException("Had invalid column counts: " + record.getLastCol() + " and " + INITIAL_CAPACITY);
+        }
+
         // Size the initial cell list such that a read only case won't waste
         //  lots of memory, and a create/read followed by adding new cells can
         //  add a bit without needing a resize
index bdd016f86055e50ad091552581588cd849d5c039..178ff3aa8b435a3689c5837b16de3e1ea39524c7 100644 (file)
@@ -85,6 +85,10 @@ public abstract class BlockStore {
     protected class ChainLoopDetector {
        private final boolean[] used_blocks;
        protected ChainLoopDetector(long rawSize) {
+           if (rawSize < 0) {
+               throw new IllegalArgumentException("Cannot create a ChainLoopDetector with negative size, but had: " + rawSize);
+           }
+
           int blkSize = getBlockStoreBlockSize();
           int numBlocks = (int)(rawSize / blkSize);
           if ((rawSize % blkSize) != 0) {
index e0e923b02e3d7b29712116d06b56027c01bee4e6..9464ecbdb4b737d1796b550eadd204149b4a1850 100644 (file)
@@ -45,6 +45,10 @@ public final class ConstantValueParser {
     }
 
     public static Object[] parse(LittleEndianInput in, int nValues) {
+        if (nValues < 0) {
+            throw new IllegalArgumentException("Invalid number of values to parse: " + nValues);
+        }
+
         Object[] result = new Object[nValues];
         for (int i = 0; i < result.length; i++) {
             result[i] = readAConstantValue(in);