]> source.dussan.org Git - poi.git/commitdiff
Fixed OOM in HSSFWorkbook#getAllPictures when reading .xls files containing metafiles...
authorYegor Kozlov <yegor@apache.org>
Sat, 20 Jun 2009 11:17:30 +0000 (11:17 +0000)
committerYegor Kozlov <yegor@apache.org>
Sat, 20 Jun 2009 11:17:30 +0000 (11:17 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@786793 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/ddf/EscherBSERecord.java
src/java/org/apache/poi/ddf/EscherDggRecord.java
src/java/org/apache/poi/ddf/EscherMetafileBlip.java
src/testcases/org/apache/poi/ddf/TestEscherBlipRecord.java
src/testcases/org/apache/poi/ddf/data/47143.dat [new file with mode: 0755]

index 9e8e2a6a3b3d03c9952aa13bb2d9ba1da4f77844..0d68b291781aab23c1faa7c3e0675464bd55cd1d 100644 (file)
@@ -33,6 +33,7 @@
 
     <changes>
         <release version="3.5-beta7" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">47143 - Fixed OOM in HSSFWorkbook#getAllPictures when reading .xls files containing metafiles</action>
            <action dev="POI-DEVELOPERS" type="add">Added implementation for ISNA()</action>
            <action dev="POI-DEVELOPERS" type="add">46793 - fixed SimpleShape#getLineWidth to handle default line width </action>
            <action dev="POI-DEVELOPERS" type="add">47356 - removed unused private fields in HWPF BorderCode</action>
index cfe4fe102807e5c87b4cd23ffc473f21ae36899d..a99c11fd5aeb8eaf8e7e83c042a7b0de133ee6c5 100644 (file)
@@ -310,13 +310,13 @@ public final class EscherBSERecord extends EscherRecord {
     }
 
     public String toString() {
-        String extraData = HexDump.toHex(_remainingData, 32);
+        String extraData = _remainingData == null ? null : HexDump.toHex(_remainingData, 32);
         return getClass().getName() + ":" + '\n' +
                 "  RecordId: 0x" + HexDump.toHex( RECORD_ID ) + '\n' +
                 "  Options: 0x" + HexDump.toHex( getOptions() ) + '\n' +
                 "  BlipTypeWin32: " + field_1_blipTypeWin32 + '\n' +
                 "  BlipTypeMacOS: " + field_2_blipTypeMacOS + '\n' +
-                "  SUID: " + HexDump.toHex(field_3_uid) + '\n' +
+                "  SUID: " + (field_3_uid == null ? "" : HexDump.toHex(field_3_uid)) + '\n' +
                 "  Tag: " + field_4_tag + '\n' +
                 "  Size: " + field_5_size + '\n' +
                 "  Ref: " + field_6_ref + '\n' +
index 2266d127ae1e7c3264bba6375155413e270a0d05..bdcf5ad0683edd34527dd7a6c8ce5ae445c016a6 100644 (file)
@@ -122,7 +122,7 @@ public final class EscherDggRecord extends EscherRecord {
     public String toString() {
 
         StringBuffer field_5_string = new StringBuffer();
-        for (int i = 0; i < field_5_fileIdClusters.length; i++) {
+        if(field_5_fileIdClusters != null) for (int i = 0; i < field_5_fileIdClusters.length; i++) {
             field_5_string.append("  DrawingGroupId").append(i+1).append(": ");
             field_5_string.append(field_5_fileIdClusters[i].field_1_drawingGroupId);
             field_5_string.append('\n');
@@ -156,7 +156,7 @@ public final class EscherDggRecord extends EscherRecord {
      * Number of id clusters + 1
      */
     public int getNumIdClusters() {
-        return field_5_fileIdClusters.length + 1;
+        return (field_5_fileIdClusters == null ? 0 : (field_5_fileIdClusters.length + 1));
     }
 
     public int getNumShapesSaved() {
index 662a7a7d13d6e5c804291179d1075a822e394035..9989951f8287036b4fcb7bc7acb0a9d30115c6ef 100644 (file)
@@ -65,11 +65,11 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
     private byte field_7_fFilter;
 
     private byte[] raw_pictureData;
+    private byte[] remainingData;
 
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesAfterHeader = readHeader( data, offset );
         int pos = offset + HEADER_SIZE;
-
         field_1_UID = new byte[16];
         System.arraycopy( data, pos, field_1_UID, 0, 16 ); pos += 16;
 
@@ -91,6 +91,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
 
         raw_pictureData = new byte[field_5_cbSave];
         System.arraycopy( data, pos, raw_pictureData, 0, field_5_cbSave );
+        pos += field_5_cbSave;
 
         // 0 means DEFLATE compression
         // 0xFE means no compression
@@ -100,6 +101,11 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
             field_pictureData = raw_pictureData;
         }
 
+        int remaining = bytesAfterHeader - pos + offset + HEADER_SIZE;
+        if(remaining > 0) {
+            remainingData = new byte[remaining];
+            System.arraycopy( data, pos, remainingData, 0, remaining );
+        }
         return bytesAfterHeader + HEADER_SIZE;
     }
 
@@ -126,7 +132,10 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
         data[pos] = field_6_fCompression; pos++;
         data[pos] = field_7_fFilter; pos++;
 
-        System.arraycopy( raw_pictureData, 0, data, pos, raw_pictureData.length );
+        System.arraycopy( raw_pictureData, 0, data, pos, raw_pictureData.length ); pos += raw_pictureData.length;
+        if(remainingData != null) {
+            System.arraycopy( remainingData, 0, data, pos, remainingData.length ); pos += remainingData.length;
+        }
 
         listener.afterRecordSerialize(offset + getRecordSize(), getRecordId(), getRecordSize(), this);
         return getRecordSize();
@@ -157,6 +166,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
 
     public int getRecordSize() {
         int size = 8 + 50 + raw_pictureData.length;
+        if(remainingData != null) size += remainingData.length;
         if((getOptions() ^ getSignature()) == 0x10){
             size += field_2_UID.length;
         }
@@ -227,10 +237,14 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
         field_6_fCompression = compressed ? 0 : (byte)0xFE;
     }
 
+    public byte[] getRemainingData() {
+        return remainingData;
+    }
+
     // filtering is always 254 according to available docs, so no point giving it a setter method.
 
     public String toString() {
-        String extraData = HexDump.toHex(field_pictureData, 32);
+        String extraData = "";//HexDump.toHex(field_pictureData, 32);
         return getClass().getName() + ":" + '\n' +
                 "  RecordId: 0x" + HexDump.toHex( getRecordId() ) + '\n' +
                 "  Options: 0x" + HexDump.toHex( getOptions() ) + '\n' +
@@ -242,7 +256,9 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
                 "  Compressed Size: " + HexDump.toHex( field_5_cbSave ) + '\n' +
                 "  Compression: " + HexDump.toHex( field_6_fCompression ) + '\n' +
                 "  Filter: " + HexDump.toHex( field_7_fFilter ) + '\n' +
-                "  Extra Data:" + '\n' + extraData;
+                "  Extra Data:" + '\n' + extraData +
+                (remainingData == null ? null : ("\n" +
+                 " Remaining Data: " + HexDump.toHex(remainingData, 32)));
     }
 
     /**
index 62c1f233b27135f278af0c448e9e64cce3a5b7db..9e2921fe88b55d4c0806c206a790b7e762feec37 100755 (executable)
@@ -152,4 +152,22 @@ public final class TestEscherBlipRecord extends TestCase {
         return data;
     }
 
+    /**
+     * The test data was created from pl031405.xls attached to Bugzilla #47143
+     */
+    public void test47143() {
+        byte[] data = read(new File(cwd, "47143.dat"));
+        EscherBSERecord bse = new EscherBSERecord();
+        bse.fillFields(data, 0, new DefaultEscherRecordFactory());
+        bse.toString(); //assert that toString() works
+        assertTrue(bse.getBlipRecord() instanceof EscherMetafileBlip);
+
+        EscherMetafileBlip blip = (EscherMetafileBlip)bse.getBlipRecord();
+        blip.toString(); //assert that toString() works
+        byte[] remaining = blip.getRemainingData();
+        assertNotNull(remaining);
+
+        byte[] ser = bse.serialize();  //serialize and assert against the source data
+        assertTrue(Arrays.equals(data, ser));
+    }
 }
diff --git a/src/testcases/org/apache/poi/ddf/data/47143.dat b/src/testcases/org/apache/poi/ddf/data/47143.dat
new file mode 100755 (executable)
index 0000000..0745ce1
Binary files /dev/null and b/src/testcases/org/apache/poi/ddf/data/47143.dat differ