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
This commit is contained in:
Nick Burch 2014-04-24 16:15:21 +00:00
parent e7dff43065
commit fbd86d5084
3 changed files with 24 additions and 8 deletions

View 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);
}

View 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());
}

View 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 {