From: Nick Burch Date: Thu, 24 Apr 2014 16:15:21 +0000 (+0000) Subject: More int/long sizing fixes for >2gb NPOIFS files, see bug #56447 X-Git-Tag: REL_3_11_BETA1~180 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=9d0167f5de0ffc9f6a266e66bcacf7fbe1b74145;p=poi.git More int/long sizing fixes for >2gb NPOIFS files, see bug #56447 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1589783 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java index bf7d1f7457..efa195e233 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java @@ -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); } diff --git a/src/java/org/apache/poi/poifs/storage/BATBlock.java b/src/java/org/apache/poi/poifs/storage/BATBlock.java index 661cd12dc6..8712e65f6f 100644 --- a/src/java/org/apache/poi/poifs/storage/BATBlock.java +++ b/src/java/org/apache/poi/poifs/storage/BATBlock.java @@ -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()); } diff --git a/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java b/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java index 758d559542..3fc77b839c 100644 --- a/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java +++ b/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java @@ -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 {