]> source.dussan.org Git - poi.git/commitdiff
More int/long sizing fixes for >2gb NPOIFS files, see bug #56447
authorNick Burch <nick@apache.org>
Thu, 24 Apr 2014 16:15:21 +0000 (16:15 +0000)
committerNick Burch <nick@apache.org>
Thu, 24 Apr 2014 16:15:21 +0000 (16:15 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1589783 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java
src/java/org/apache/poi/poifs/storage/BATBlock.java
src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java

index bf7d1f74571cac3c1376cb7fe7e00cdbadff728a..efa195e233f0180e856c35f1d61959a99ebb407a 100644 (file)
@@ -271,12 +271,17 @@ public class NPOIFSFileSystem extends BlockStore
            // We need to buffer the whole file into memory when
            //  working with an InputStream.
            // The max possible size is when each BAT block entry is used
-           int maxSize = BATBlock.calculateMaximumSize(_header); 
-           ByteBuffer data = ByteBuffer.allocate(maxSize);
+           long maxSize = BATBlock.calculateMaximumSize(_header); 
+           if (maxSize > Integer.MAX_VALUE) {
+               throw new IllegalArgumentException("Unable read a >2gb file via an InputStream");
+           }
+           ByteBuffer data = ByteBuffer.allocate((int)maxSize);
+           
            // Copy in the header
            headerBuffer.position(0);
            data.put(headerBuffer);
            data.position(headerBuffer.capacity());
+           
            // Now read the rest of the stream
            IOUtils.readFully(channel, data);
            success = true;
@@ -424,7 +429,8 @@ public class NPOIFSFileSystem extends BlockStore
     @Override
     protected ByteBuffer getBlockAt(final int offset) throws IOException {
        // The header block doesn't count, so add one
-       long startAt = (offset+1) * bigBlockSize.getBigBlockSize();
+       long blockWanted = offset + 1;
+       long startAt = blockWanted * bigBlockSize.getBigBlockSize();
        return _data.read(bigBlockSize.getBigBlockSize(), startAt);
     }
     
index 661cd12dc6e4ee94a6cd2c46fa43ad31b74ac2cd..8712e65f6fb3fad221dae2ce773ad29bbc08d295 100644 (file)
@@ -242,9 +242,9 @@ public final class BATBlock extends BigBlock {
      *  For 512 byte block sizes, this means we may over-estimate by up to 65kb.
      *  For 4096 byte block sizes, this means we may over-estimate by up to 4mb
      */
-    public static int calculateMaximumSize(final POIFSBigBlockSize bigBlockSize,
+    public static long calculateMaximumSize(final POIFSBigBlockSize bigBlockSize,
           final int numBATs) {
-       int size = 1; // Header isn't FAT addressed
+       long size = 1; // Header isn't FAT addressed
        
        // The header has up to 109 BATs, and extra ones are referenced
        //  from XBATs
@@ -254,7 +254,7 @@ public final class BATBlock extends BigBlock {
        // So far we've been in sector counts, turn into bytes
        return size * bigBlockSize.getBigBlockSize();
     }
-    public static int calculateMaximumSize(final HeaderBlock header)
+    public static long calculateMaximumSize(final HeaderBlock header)
     {
        return calculateMaximumSize(header.getBigBlockSize(), header.getBATCount());
     }
index 758d559542fc65a5633a5c7ea95a766da0e585d6..3fc77b839c9ebd4ab2ac005b9c243260a65a6455 100644 (file)
@@ -24,10 +24,10 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import org.apache.poi.poifs.common.POIFSConstants;
-
 import junit.framework.TestCase;
 
+import org.apache.poi.poifs.common.POIFSConstants;
+
 /**
  * Class to test BATBlock functionality
  *
@@ -271,6 +271,16 @@ public final class TestBATBlock extends TestCase {
              4096 + 112*4096*1024, 
              BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 112)
        );
+       
+       // Check for >2gb, which we only support via a File
+       assertEquals(
+               512 + 8030l*512*128, 
+               BATBlock.calculateMaximumSize(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 8030)
+       );
+       assertEquals(
+               4096 + 8030l*4096*1024, 
+               BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 8030)
+       );
     }
     
     public void testGetBATBlockAndIndex() throws Exception {