]> source.dussan.org Git - poi.git/commitdiff
61346 add more sanity checks before allocating byte arrays in emf/wmf
authorTim Allison <tallison@apache.org>
Wed, 26 Jul 2017 12:46:24 +0000 (12:46 +0000)
committerTim Allison <tallison@apache.org>
Wed, 26 Jul 2017 12:46:24 +0000 (12:46 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1803041 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/util/IOUtils.java
src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentEMFPlus.java
src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentPublic.java
src/scratchpad/src/org/apache/poi/hemf/record/HemfCommentRecord.java
src/scratchpad/src/org/apache/poi/hemf/record/HemfHeader.java
src/scratchpad/src/org/apache/poi/hemf/record/HemfText.java
src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java
src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java

index 25e5652d93fb4c7dbd483aa52c65931dc580f99a..b256591fa07b929cea6b6e20b4f990815b45c6c3 100644 (file)
@@ -431,4 +431,19 @@ public final class IOUtils {
         return toSkip - remain;
     }
 
+    public static byte[] safelyAllocate(long length, int maxLength) {
+        if (length < 0L) {
+            throw new RecordFormatException("Can't allocate an array of length < 0");
+        }
+        if (length > (long)Integer.MAX_VALUE) {
+            throw new RecordFormatException("Can't allocate an array > "+Integer.MAX_VALUE);
+        }
+        if (length > maxLength) {
+            throw new RecordFormatException("Not allowed to allocate an array > "+
+                    maxLength+" for this record type." +
+                    "If the file is not corrupt, please open an issue on bugzilla to request " +
+                    "increasing the maximum allowable size for this record type");
+        }
+        return new byte[(int)length];
+    }
 }
index b32bf5481dbcba1970af0272d9e078e9b4611b3f..1129839649d5e4f205b383d53d9957d18375c915 100644 (file)
@@ -23,6 +23,7 @@ import java.util.List;
 
 import org.apache.poi.hemf.hemfplus.record.HemfPlusRecord;
 import org.apache.poi.hemf.hemfplus.record.HemfPlusRecordType;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.RecordFormatException;
@@ -33,6 +34,9 @@ import org.apache.poi.util.RecordFormatException;
 @Internal
 public class HemfCommentEMFPlus extends AbstractHemfComment {
 
+    private static final int MAX_RECORD_LENGTH = 1000000;
+
+
     long dataSize;
     public HemfCommentEMFPlus(byte[] rawBytes) {
         //these rawBytes contain only the EMFPlusRecord(s?)
@@ -93,7 +97,7 @@ public class HemfCommentEMFPlus extends AbstractHemfComment {
             } catch (IllegalAccessException e) {
                 throw new RuntimeException(e);
             }
-            byte[] dataBytes = new byte[size];
+            byte[] dataBytes = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
             System.arraycopy(bytes, offset, dataBytes, 0, size);
             try {
                 record.init(dataBytes, recordId, flags);
index 87f282d653138ee6e233083a2064e1c8722d5bea..76744438399abf7437016874e86b3f68e4b94a65 100644 (file)
@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianConsts;
@@ -35,6 +36,9 @@ import org.apache.poi.util.RecordFormatException;
 @Internal
 public class HemfCommentPublic  {
 
+    private static final int MAX_RECORD_LENGTH = 1000000;
+
+
     /**
      * Stub, to be implemented
      */
@@ -80,7 +84,7 @@ public class HemfCommentPublic  {
             }
             List<HemfMultiFormatsData> list = new ArrayList<HemfMultiFormatsData>();
             for (EmrFormat emrFormat : emrFormatList) {
-                byte[] data = new byte[emrFormat.size];
+                byte[] data = IOUtils.safelyAllocate(emrFormat.size, MAX_RECORD_LENGTH);
                 System.arraycopy(rawBytes, emrFormat.offset-4, data, 0, emrFormat.size);
                 list.add(new HemfMultiFormatsData(emrFormat.signature, emrFormat.version, data));
             }
@@ -129,12 +133,8 @@ public class HemfCommentPublic  {
                 wmfBytes = new byte[0];
                 return;
             }
-            if (winMetafileSizeLong > Integer.MAX_VALUE) {
-                throw new RecordFormatException("Metafile record length can't be > Integer.MAX_VALUE");
-            }
-            int winMetafileSize = (int)winMetafileSizeLong;
-            wmfBytes = new byte[winMetafileSize];
-            System.arraycopy(rawBytes, offset, wmfBytes, 0, winMetafileSize);
+            wmfBytes = IOUtils.safelyAllocate(winMetafileSizeLong, MAX_RECORD_LENGTH);
+            System.arraycopy(rawBytes, offset, wmfBytes, 0, wmfBytes.length);
         }
 
         /**
index 2e8c17d7ade62a7fc7c5615c637d152fbab15901..90510f8d8fbca867b0e5ee95bfc98bf15bcb0021 100644 (file)
@@ -36,6 +36,7 @@ import org.apache.poi.util.RecordFormatException;
  */
 @Internal
 public class HemfCommentRecord implements HemfRecord {
+    private static final int MAX_RECORD_LENGTH = 1000000;
 
     public final static long COMMENT_EMFSPOOL = 0x00000000;
     public final static long COMMENT_EMFPLUS = 0x2B464D45;
@@ -87,7 +88,7 @@ public class HemfCommentRecord implements HemfRecord {
 
         int dataSize = (int)remainingDataSize;
         int recordSize = (int)remainingRecordSize;
-        byte[] arr = new byte[dataSize+initialBytes.length];
+        byte[] arr = IOUtils.safelyAllocate(dataSize+initialBytes.length, MAX_RECORD_LENGTH);
         System.arraycopy(initialBytes,0,arr, 0, initialBytes.length);
         long read = IOUtils.readFully(leis, arr, initialBytes.length, dataSize);
         if (read != dataSize) {
@@ -103,13 +104,12 @@ public class HemfCommentRecord implements HemfRecord {
     }
 
     private byte[] readToByteArray(LittleEndianInputStream leis, long dataSize, long recordSize) throws IOException {
-        assert dataSize < Integer.MAX_VALUE;
 
         if (recordSize == 0) {
             return new byte[0];
         }
 
-        byte[] arr = new byte[(int)dataSize];
+        byte[] arr = IOUtils.safelyAllocate(dataSize, MAX_RECORD_LENGTH);
 
         long read = IOUtils.readFully(leis, arr);
         if (read != dataSize) {
index a23f4fdae2ca49d9cea6fa2d29b9709523c23e16..2c3694c8444d706a9180c1c8834496379072baeb 100644 (file)
@@ -32,6 +32,9 @@ import org.apache.poi.util.LittleEndianInputStream;
 @Internal
 public class HemfHeader implements HemfRecord {
 
+    private static final int MAX_RECORD_LENGTH = 1000000;
+
+
     private Rectangle boundsRectangle;
     private Rectangle frameRectangle;
     private long bytes;
@@ -140,7 +143,7 @@ public class HemfHeader implements HemfRecord {
             throw new IOException("Not a valid EMF header. Record type:"+recordId);
         }
         //read the record--id and size (2 bytes) have already been read
-        byte[] data = new byte[(int)recordSize];
+        byte[] data = IOUtils.safelyAllocate(recordSize, MAX_RECORD_LENGTH);
         IOUtils.readFully(leis, data);
 
         int offset = 0;
index c40e493bdbc2e7d53a766483f29f668de4d74467..8c32812d7f06a7dc9d18907421d02110f60f3d7d 100644 (file)
@@ -39,7 +39,8 @@ import org.apache.poi.util.RecordFormatException;
 @Internal
 public class HemfText {
 
-    private final static Charset UTF16LE = Charset.forName("UTF-16LE");
+    private static final Charset UTF16LE = Charset.forName("UTF-16LE");
+    private static final int MAX_RECORD_LENGTH = 1000000;
 
     public static class ExtCreateFontIndirectW extends UnimplementedHemfRecord {
     }
@@ -80,7 +81,7 @@ public class HemfText {
             }
             //guarantee to read the rest of the EMRTextObjectRecord
             //emrtextbytes start after 7*4 bytes read above
-            byte[] emrTextBytes = new byte[recordSizeInt-(7*LittleEndian.INT_SIZE)];
+            byte[] emrTextBytes = IOUtils.safelyAllocate(recordSizeInt-(7*LittleEndian.INT_SIZE), MAX_RECORD_LENGTH);
             IOUtils.readFully(leis, emrTextBytes);
             textObject = new EmrTextObject(emrTextBytes, getEncodingHint(), 20);//should be 28, but recordSizeInt has already subtracted 8
             return recordSize;
@@ -218,9 +219,12 @@ public class HemfText {
             }
             if (numCharsLong > Integer.MAX_VALUE) {
                 throw new RecordFormatException("Number of characters can't be > Integer.MAX_VALUE");
+            } else if (numCharsLong < 0) {
+                throw new RecordFormatException("Number of characters can't be < 0");
             }
+
             numChars = (int)numCharsLong;
-            rawTextBytes = new byte[emrTextObjBytes.length-start];
+            rawTextBytes = IOUtils.safelyAllocate(emrTextObjBytes.length-start, MAX_RECORD_LENGTH);
             System.arraycopy(emrTextObjBytes, start, rawTextBytes, 0, emrTextObjBytes.length-start);
         }
 
index ce4d148796aa60e46a23c5e43f7f47533fc78af6..b9522730e6f5944b226cf45b3bdf14c78977f100 100644 (file)
@@ -17,6 +17,7 @@
 
 package org.apache.poi.hwmf.record;
 
+import javax.imageio.ImageIO;
 import java.awt.Color;
 import java.awt.Graphics2D;
 import java.awt.image.BufferedImage;
@@ -24,8 +25,6 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
-import javax.imageio.ImageIO;
-
 import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianConsts;
@@ -38,6 +37,9 @@ import org.apache.poi.util.RecordFormatException;
  * The DeviceIndependentBitmap Object defines an image in device-independent bitmap (DIB) format.
  */
 public class HwmfBitmapDib {
+
+    private static final int MAX_RECORD_LENGTH = 10000000;
+
     public static enum BitCount {
         /**
          * The image SHOULD be in either JPEG or PNG format. <6> Neither of these formats includes
@@ -385,7 +387,7 @@ public class HwmfBitmapDib {
         int imageSize = (int)Math.max(imageData.length, introSize+headerImageSize);
         
         // create the image data and leave the parsing to the ImageIO api
-        byte buf[] = new byte[BMP_HEADER_SIZE+imageSize];
+        byte buf[] = IOUtils.safelyAllocate(BMP_HEADER_SIZE+imageSize, MAX_RECORD_LENGTH);
 
         // https://en.wikipedia.org/wiki/BMP_file_format #  Bitmap file header
         buf[0] = (byte)'B';
index 9bcac30d06085beb84d75587d3ca1780c54484d8..928b31128d2744ba9eaffd7bd35dc0917a2d49ae 100644 (file)
@@ -26,6 +26,7 @@ import org.apache.poi.hwmf.draw.HwmfGraphics;
 import org.apache.poi.hwmf.record.HwmfMisc.WmfSetMapMode;
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.LittleEndianConsts;
 import org.apache.poi.util.LittleEndianInputStream;
 import org.apache.poi.util.POILogFactory;
@@ -33,7 +34,8 @@ import org.apache.poi.util.POILogger;
 
 public class HwmfText {
     private static final POILogger logger = POILogFactory.getLogger(HwmfText.class);
-    
+    private static final int MAX_RECORD_LENGTH = 1000000;
+
     /**
      * The META_SETTEXTCHAREXTRA record defines inter-character spacing for text justification in the 
      * playback device context. Spacing is added to the white space between each character, including
@@ -164,7 +166,7 @@ public class HwmfText {
         @Override
         public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
             stringLength = leis.readShort();
-            rawTextBytes = new byte[stringLength+(stringLength&1)];
+            rawTextBytes = IOUtils.safelyAllocate(stringLength+(stringLength&1), MAX_RECORD_LENGTH);
             leis.readFully(rawTextBytes);
             yStart = leis.readShort();
             xStart = leis.readShort();
@@ -188,7 +190,7 @@ public class HwmfText {
          * This does not include the extra optional padding on the byte array.
          */
         private byte[] getTextBytes() {
-            byte[] ret = new byte[stringLength];
+            byte[] ret = IOUtils.safelyAllocate(stringLength, MAX_RECORD_LENGTH);
             System.arraycopy(rawTextBytes, 0, ret, 0, stringLength);
             return ret;
         }
@@ -315,7 +317,7 @@ public class HwmfText {
                 size += 4*LittleEndianConsts.SHORT_SIZE;
             }
             
-            rawTextBytes = new byte[stringLength+(stringLength&1)];
+            rawTextBytes = IOUtils.safelyAllocate(stringLength+(stringLength&1), MAX_RECORD_LENGTH);
             leis.readFully(rawTextBytes);
             size += rawTextBytes.length;
             
@@ -355,7 +357,7 @@ public class HwmfText {
          * This does not include the extra optional padding on the byte array.
          */
         private byte[] getTextBytes() {
-            byte[] ret = new byte[stringLength];
+            byte[] ret = IOUtils.safelyAllocate(stringLength, MAX_RECORD_LENGTH);
             System.arraycopy(rawTextBytes, 0, ret, 0, stringLength);
             return ret;
         }