Bug 61349 -- add more sanity checks when allocating byte[]

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1809169 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tim Allison 2017-09-21 14:52:59 +00:00
parent 828fb9a86c
commit 9cade10fa4
135 changed files with 772 additions and 193 deletions

View File

@ -19,6 +19,7 @@ package org.apache.poi.poifs.poibrowser;
import java.io.*; import java.io.*;
import org.apache.poi.poifs.filesystem.*; import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.util.IOUtils;
/** /**
* <p>Describes the most important (whatever that is) features of a * <p>Describes the most important (whatever that is) features of a
@ -26,6 +27,10 @@ import org.apache.poi.poifs.filesystem.*;
*/ */
public class DocumentDescriptor public class DocumentDescriptor
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
String name; String name;
POIFSDocumentPath path; POIFSDocumentPath path;
DocumentInputStream stream; DocumentInputStream stream;
@ -60,7 +65,7 @@ public class DocumentDescriptor
if (stream.markSupported()) if (stream.markSupported())
{ {
stream.mark(nrOfBytes); stream.mark(nrOfBytes);
final byte[] b = new byte[nrOfBytes]; final byte[] b = IOUtils.safelyAllocate(nrOfBytes, MAX_RECORD_LENGTH);
final int read = stream.read(b, 0, Math.min(size, b.length)); final int read = stream.read(b, 0, Math.min(size, b.length));
bytes = new byte[read]; bytes = new byte[read];
System.arraycopy(b, 0, bytes, 0, read); System.arraycopy(b, 0, bytes, 0, read);

View File

@ -21,6 +21,7 @@ import java.util.Iterator;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -28,6 +29,10 @@ import org.apache.poi.util.LittleEndian;
* with all sorts of special cases. I'm hopeful I've got them all. * with all sorts of special cases. I'm hopeful I've got them all.
*/ */
public final class EscherArrayProperty extends EscherComplexProperty implements Iterable<byte[]> { public final class EscherArrayProperty extends EscherComplexProperty implements Iterable<byte[]> {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* The size of the header that goes at the * The size of the header that goes at the
* start of the array, before the data * start of the array, before the data
@ -69,7 +74,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements
public void setNumberOfElementsInArray(int numberOfElements) { public void setNumberOfElementsInArray(int numberOfElements) {
int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE; int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE;
if (expectedArraySize != getComplexData().length) { if (expectedArraySize != getComplexData().length) {
byte[] newArray = new byte[expectedArraySize]; byte[] newArray = IOUtils.safelyAllocate(expectedArraySize, MAX_RECORD_LENGTH);
System.arraycopy(getComplexData(), 0, newArray, 0, getComplexData().length); System.arraycopy(getComplexData(), 0, newArray, 0, getComplexData().length);
setComplexData(newArray); setComplexData(newArray);
} }
@ -83,7 +88,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements
public void setNumberOfElementsInMemory(int numberOfElements) { public void setNumberOfElementsInMemory(int numberOfElements) {
int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE; int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE;
if (expectedArraySize != getComplexData().length) { if (expectedArraySize != getComplexData().length) {
byte[] newArray = new byte[expectedArraySize]; byte[] newArray = IOUtils.safelyAllocate(expectedArraySize, MAX_RECORD_LENGTH);
System.arraycopy(getComplexData(), 0, newArray, 0, expectedArraySize); System.arraycopy(getComplexData(), 0, newArray, 0, expectedArraySize);
setComplexData(newArray); setComplexData(newArray);
} }
@ -100,7 +105,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements
int expectedArraySize = getNumberOfElementsInArray() * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE; int expectedArraySize = getNumberOfElementsInArray() * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE;
if (expectedArraySize != getComplexData().length) { if (expectedArraySize != getComplexData().length) {
// Keep just the first 6 bytes. The rest is no good to us anyway. // Keep just the first 6 bytes. The rest is no good to us anyway.
byte[] newArray = new byte[expectedArraySize]; byte[] newArray = IOUtils.safelyAllocate(expectedArraySize, MAX_RECORD_LENGTH);
System.arraycopy( getComplexData(), 0, newArray, 0, 6 ); System.arraycopy( getComplexData(), 0, newArray, 0, 6 );
setComplexData(newArray); setComplexData(newArray);
} }
@ -108,7 +113,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements
public byte[] getElement(int index) { public byte[] getElement(int index) {
int actualSize = getActualSizeOfElements(getSizeOfElements()); int actualSize = getActualSizeOfElements(getSizeOfElements());
byte[] result = new byte[actualSize]; byte[] result = IOUtils.safelyAllocate(actualSize, MAX_RECORD_LENGTH);
System.arraycopy(getComplexData(), FIXED_SIZE + index * actualSize, result, 0, result.length ); System.arraycopy(getComplexData(), FIXED_SIZE + index * actualSize, result, 0, result.length );
return result; return result;
} }

View File

@ -17,6 +17,7 @@
package org.apache.poi.ddf; package org.apache.poi.ddf;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -27,6 +28,10 @@ import org.apache.poi.util.LittleEndian;
* @see EscherBlipRecord * @see EscherBlipRecord
*/ */
public final class EscherBSERecord extends EscherRecord { public final class EscherBSERecord extends EscherRecord {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static final short RECORD_ID = (short) 0xF007; public static final short RECORD_ID = (short) 0xF007;
public static final String RECORD_DESCRIPTION = "MsofbtBSE"; public static final String RECORD_DESCRIPTION = "MsofbtBSE";
@ -84,7 +89,7 @@ public final class EscherBSERecord extends EscherRecord {
pos += 36 + bytesRead; pos += 36 + bytesRead;
bytesRemaining -= bytesRead; bytesRemaining -= bytesRead;
_remainingData = new byte[bytesRemaining]; _remainingData = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH);
System.arraycopy( data, pos, _remainingData, 0, bytesRemaining ); System.arraycopy( data, pos, _remainingData, 0, bytesRemaining );
return bytesRemaining + 8 + 36 + (field_12_blipRecord == null ? 0 : field_12_blipRecord.getRecordSize()) ; return bytesRemaining + 8 + 36 + (field_12_blipRecord == null ? 0 : field_12_blipRecord.getRecordSize()) ;

View File

@ -17,9 +17,14 @@
package org.apache.poi.ddf; package org.apache.poi.ddf;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
public class EscherBlipRecord extends EscherRecord { public class EscherBlipRecord extends EscherRecord {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000_000;
public static final short RECORD_ID_START = (short) 0xF018; public static final short RECORD_ID_START = (short) 0xF018;
public static final short RECORD_ID_END = (short) 0xF117; public static final short RECORD_ID_END = (short) 0xF117;
public static final String RECORD_DESCRIPTION = "msofbtBlip"; public static final String RECORD_DESCRIPTION = "msofbtBlip";
@ -36,7 +41,7 @@ public class EscherBlipRecord extends EscherRecord {
int bytesAfterHeader = readHeader( data, offset ); int bytesAfterHeader = readHeader( data, offset );
int pos = offset + HEADER_SIZE; int pos = offset + HEADER_SIZE;
field_pictureData = new byte[bytesAfterHeader]; field_pictureData = IOUtils.safelyAllocate(bytesAfterHeader, MAX_RECORD_LENGTH);
System.arraycopy(data, pos, field_pictureData, 0, bytesAfterHeader); System.arraycopy(data, pos, field_pictureData, 0, bytesAfterHeader);
return bytesAfterHeader + 8; return bytesAfterHeader + 8;
@ -94,7 +99,7 @@ public class EscherBlipRecord extends EscherRecord {
if (pictureData == null || offset < 0 || length < 0 || pictureData.length < offset+length) { if (pictureData == null || offset < 0 || length < 0 || pictureData.length < offset+length) {
throw new IllegalArgumentException("picture data can't be null"); throw new IllegalArgumentException("picture data can't be null");
} }
field_pictureData = new byte[length]; field_pictureData = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH);
System.arraycopy(pictureData, offset, field_pictureData, 0, length); System.arraycopy(pictureData, offset, field_pictureData, 0, length);
} }

View File

@ -17,6 +17,7 @@
package org.apache.poi.ddf; package org.apache.poi.ddf;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -30,6 +31,9 @@ import org.apache.poi.util.LittleEndian;
public class EscherClientAnchorRecord public class EscherClientAnchorRecord
extends EscherRecord extends EscherRecord
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static final short RECORD_ID = (short) 0xF010; public static final short RECORD_ID = (short) 0xF010;
public static final String RECORD_DESCRIPTION = "MsofbtClientAnchor"; public static final String RECORD_DESCRIPTION = "MsofbtClientAnchor";
@ -83,7 +87,7 @@ public class EscherClientAnchorRecord
} }
} }
bytesRemaining -= size; bytesRemaining -= size;
remainingData = new byte[bytesRemaining]; remainingData = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH);
System.arraycopy( data, pos + size, remainingData, 0, bytesRemaining ); System.arraycopy( data, pos + size, remainingData, 0, bytesRemaining );
return 8 + size + bytesRemaining; return 8 + size + bytesRemaining;
} }

View File

@ -18,6 +18,7 @@
package org.apache.poi.ddf; package org.apache.poi.ddf;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -27,6 +28,9 @@ import org.apache.poi.util.LittleEndian;
public class EscherClientDataRecord public class EscherClientDataRecord
extends EscherRecord extends EscherRecord
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static final short RECORD_ID = (short) 0xF011; public static final short RECORD_ID = (short) 0xF011;
public static final String RECORD_DESCRIPTION = "MsofbtClientData"; public static final String RECORD_DESCRIPTION = "MsofbtClientData";
@ -36,7 +40,7 @@ public class EscherClientDataRecord
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
int bytesRemaining = readHeader( data, offset ); int bytesRemaining = readHeader( data, offset );
int pos = offset + 8; int pos = offset + 8;
remainingData = new byte[bytesRemaining]; remainingData = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH);
System.arraycopy( data, pos, remainingData, 0, bytesRemaining ); System.arraycopy( data, pos, remainingData, 0, bytesRemaining );
return 8 + bytesRemaining; return 8 + bytesRemaining;
} }

View File

@ -26,12 +26,15 @@ import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream; import java.util.zip.InflaterInputStream;
import org.apache.poi.hssf.usermodel.HSSFPictureData; import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
public final class EscherMetafileBlip extends EscherBlipRecord { public final class EscherMetafileBlip extends EscherBlipRecord {
private static final POILogger log = POILogFactory.getLogger(EscherMetafileBlip.class); private static final POILogger log = POILogFactory.getLogger(EscherMetafileBlip.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000_000;
public static final short RECORD_ID_EMF = (short) 0xF018 + 2; public static final short RECORD_ID_EMF = (short) 0xF018 + 2;
public static final short RECORD_ID_WMF = (short) 0xF018 + 3; public static final short RECORD_ID_WMF = (short) 0xF018 + 3;
@ -79,7 +82,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
field_6_fCompression = data[pos]; pos++; field_6_fCompression = data[pos]; pos++;
field_7_fFilter = data[pos]; pos++; field_7_fFilter = data[pos]; pos++;
raw_pictureData = new byte[field_5_cbSave]; raw_pictureData = IOUtils.safelyAllocate(field_5_cbSave, MAX_RECORD_LENGTH);
System.arraycopy( data, pos, raw_pictureData, 0, field_5_cbSave ); System.arraycopy( data, pos, raw_pictureData, 0, field_5_cbSave );
pos += field_5_cbSave; pos += field_5_cbSave;
@ -93,7 +96,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
int remaining = bytesAfterHeader - pos + offset + HEADER_SIZE; int remaining = bytesAfterHeader - pos + offset + HEADER_SIZE;
if(remaining > 0) { if(remaining > 0) {
remainingData = new byte[remaining]; remainingData = IOUtils.safelyAllocate(remaining, MAX_RECORD_LENGTH);
System.arraycopy( data, pos, remainingData, 0, remaining ); System.arraycopy( data, pos, remainingData, 0, remaining );
} }
return bytesAfterHeader + HEADER_SIZE; return bytesAfterHeader + HEADER_SIZE;

View File

@ -24,12 +24,15 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.zip.InflaterInputStream; import java.util.zip.InflaterInputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
public final class EscherPictBlip extends EscherBlipRecord { public final class EscherPictBlip extends EscherBlipRecord {
private static final POILogger log = POILogFactory.getLogger(EscherPictBlip.class); private static final POILogger log = POILogFactory.getLogger(EscherPictBlip.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static final short RECORD_ID_EMF = (short) 0xF018 + 2; public static final short RECORD_ID_EMF = (short) 0xF018 + 2;
public static final short RECORD_ID_WMF = (short) 0xF018 + 3; public static final short RECORD_ID_WMF = (short) 0xF018 + 3;
@ -68,7 +71,7 @@ public final class EscherPictBlip extends EscherBlipRecord {
field_6_fCompression = data[pos]; pos++; field_6_fCompression = data[pos]; pos++;
field_7_fFilter = data[pos]; pos++; field_7_fFilter = data[pos]; pos++;
raw_pictureData = new byte[field_5_cbSave]; raw_pictureData = IOUtils.safelyAllocate(field_5_cbSave, MAX_RECORD_LENGTH);
System.arraycopy( data, pos, raw_pictureData, 0, field_5_cbSave ); System.arraycopy( data, pos, raw_pictureData, 0, field_5_cbSave );
// 0 means DEFLATE compression // 0 means DEFLATE compression

View File

@ -20,12 +20,17 @@ package org.apache.poi.ddf;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
* Generates a property given a reference into the byte array storing that property. * Generates a property given a reference into the byte array storing that property.
*/ */
public final class EscherPropertyFactory { public final class EscherPropertyFactory {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000_000;
/** /**
* Create new properties from a byte array. * Create new properties from a byte array.
* *
@ -64,9 +69,9 @@ public final class EscherPropertyFactory {
if ( !isComplex ) { if ( !isComplex ) {
ep = new EscherSimpleProperty( propId, propData ); ep = new EscherSimpleProperty( propId, propData );
} else if ( propertyType == EscherPropertyMetaData.TYPE_ARRAY) { } else if ( propertyType == EscherPropertyMetaData.TYPE_ARRAY) {
ep = new EscherArrayProperty( propId, new byte[propData]); ep = new EscherArrayProperty( propId, IOUtils.safelyAllocate(propData, MAX_RECORD_LENGTH));
} else { } else {
ep = new EscherComplexProperty( propId, new byte[propData]); ep = new EscherComplexProperty( propId, IOUtils.safelyAllocate(propData, MAX_RECORD_LENGTH));
} }
break; break;
} }

View File

@ -20,6 +20,7 @@ package org.apache.poi.ddf;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
@ -30,6 +31,10 @@ import org.apache.poi.util.RecordFormatException;
* they will be in the parent's format, not Escher format. * they will be in the parent's format, not Escher format.
*/ */
public final class EscherTextboxRecord extends EscherRecord implements Cloneable { public final class EscherTextboxRecord extends EscherRecord implements Cloneable {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static final short RECORD_ID = (short)0xF00D; public static final short RECORD_ID = (short)0xF00D;
public static final String RECORD_DESCRIPTION = "msofbtClientTextbox"; public static final String RECORD_DESCRIPTION = "msofbtClientTextbox";
@ -48,7 +53,7 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable
// Save the data, ready for the calling code to do something // Save the data, ready for the calling code to do something
// useful with it // useful with it
thedata = new byte[bytesRemaining]; thedata = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH);
System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining ); System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining );
return bytesRemaining + 8; return bytesRemaining + 8;
} }
@ -97,7 +102,7 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable
*/ */
public void setData(byte[] b, int start, int length) public void setData(byte[] b, int start, int length)
{ {
thedata = new byte[length]; thedata = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH);
System.arraycopy(b,start,thedata,0,length); System.arraycopy(b,start,thedata,0,length);
} }

View File

@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -28,6 +29,10 @@ import org.apache.poi.util.LittleEndian;
* we do not explicitly support. * we do not explicitly support.
*/ */
public final class UnknownEscherRecord extends EscherRecord implements Cloneable { public final class UnknownEscherRecord extends EscherRecord implements Cloneable {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000_000;
private static final byte[] NO_BYTES = new byte[0]; private static final byte[] NO_BYTES = new byte[0];
/** The data for this record not including the the 8 byte header */ /** The data for this record not including the the 8 byte header */
@ -70,7 +75,7 @@ public final class UnknownEscherRecord extends EscherRecord implements Cloneable
bytesRemaining = 0; bytesRemaining = 0;
} }
thedata = new byte[bytesRemaining]; thedata = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH);
System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining ); System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining );
return bytesRemaining + 8; return bytesRemaining + 8;
} }

View File

@ -16,18 +16,23 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.hpsf; package org.apache.poi.hpsf;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
@Internal @Internal
class Blob { class Blob {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private byte[] _value; private byte[] _value;
Blob() {} Blob() {}
void read( LittleEndianInput lei ) { void read( LittleEndianInput lei ) {
int size = lei.readInt(); int size = lei.readInt();
_value = new byte[size]; _value = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
if ( size > 0 ) { if ( size > 0 ) {
lei.readFully(_value); lei.readFully(_value);
} }

View File

@ -26,6 +26,9 @@ import org.apache.poi.util.POILogger;
@Internal @Internal
class ClipboardData { class ClipboardData {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000_000;
private static final POILogger LOG = POILogFactory.getLogger( ClipboardData.class ); private static final POILogger LOG = POILogFactory.getLogger( ClipboardData.class );
private int _format; private int _format;
@ -48,7 +51,7 @@ class ClipboardData {
} }
_format = lei.readInt(); _format = lei.readInt();
_value = new byte[size - LittleEndianConsts.INT_SIZE]; _value = IOUtils.safelyAllocate(size - LittleEndianConsts.INT_SIZE, MAX_RECORD_LENGTH);
lei.readFully(_value); lei.readFully(_value);
} }

View File

@ -21,6 +21,7 @@ import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import org.apache.poi.util.CodePageUtil; import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianByteArrayInputStream;
@ -30,6 +31,9 @@ import org.apache.poi.util.POILogger;
@Internal @Internal
class CodePageString { class CodePageString {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private final static POILogger LOG = POILogFactory.getLogger( CodePageString.class ); private final static POILogger LOG = POILogFactory.getLogger( CodePageString.class );
private byte[] _value; private byte[] _value;
@ -40,7 +44,7 @@ class CodePageString {
void read( LittleEndianByteArrayInputStream lei ) { void read( LittleEndianByteArrayInputStream lei ) {
int offset = lei.getReadIndex(); int offset = lei.getReadIndex();
int size = lei.readInt(); int size = lei.readInt();
_value = new byte[size]; _value = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
if (size == 0) { if (size == 0) {
return; return;
} }

View File

@ -33,6 +33,7 @@ import org.apache.commons.collections4.bidimap.TreeBidiMap;
import org.apache.poi.hpsf.wellknown.PropertyIDMap; import org.apache.poi.hpsf.wellknown.PropertyIDMap;
import org.apache.poi.hpsf.wellknown.SectionIDMap; import org.apache.poi.hpsf.wellknown.SectionIDMap;
import org.apache.poi.util.CodePageUtil; import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
@ -43,6 +44,9 @@ import org.apache.poi.util.POILogger;
* Represents a section in a {@link PropertySet}. * Represents a section in a {@link PropertySet}.
*/ */
public class Section { public class Section {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private static final POILogger LOG = POILogFactory.getLogger(Section.class); private static final POILogger LOG = POILogFactory.getLogger(Section.class);
/** /**
@ -835,7 +839,7 @@ public class Section {
} }
try { try {
byte buf[] = new byte[nrBytes]; byte buf[] = IOUtils.safelyAllocate(nrBytes, MAX_RECORD_LENGTH);
leis.readFully(buf, 0, nrBytes); leis.readFully(buf, 0, nrBytes);
final String str = CodePageUtil.getStringFromCodePage(buf, 0, nrBytes, cp); final String str = CodePageUtil.getStringFromCodePage(buf, 0, nrBytes, cp);

View File

@ -21,6 +21,7 @@ import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import org.apache.poi.util.CodePageUtil; import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianByteArrayInputStream;
@ -32,6 +33,8 @@ import org.apache.poi.util.StringUtil;
@Internal @Internal
class UnicodeString { class UnicodeString {
private static final POILogger LOG = POILogFactory.getLogger( UnicodeString.class ); private static final POILogger LOG = POILogFactory.getLogger( UnicodeString.class );
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private byte[] _value; private byte[] _value;
@ -40,7 +43,7 @@ class UnicodeString {
void read(LittleEndianByteArrayInputStream lei) { void read(LittleEndianByteArrayInputStream lei) {
final int length = lei.readInt(); final int length = lei.readInt();
final int unicodeBytes = length*2; final int unicodeBytes = length*2;
_value = new byte[unicodeBytes]; _value = IOUtils.safelyAllocate(unicodeBytes, MAX_RECORD_LENGTH);
// If Length is zero, this field MUST be zero bytes in length. If Length is // If Length is zero, this field MUST be zero bytes in length. If Length is
// nonzero, this field MUST be a null-terminated array of 16-bit Unicode characters, followed by // nonzero, this field MUST be a null-terminated array of 16-bit Unicode characters, followed by

View File

@ -25,6 +25,7 @@ import java.util.Date;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
@ -58,6 +59,9 @@ public class VariantSupport extends Variant {
private static final POILogger logger = POILogFactory.getLogger(VariantSupport.class); private static final POILogger logger = POILogFactory.getLogger(VariantSupport.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private static boolean logUnsupportedTypes; private static boolean logUnsupportedTypes;
/** /**
@ -172,7 +176,7 @@ public class VariantSupport extends Variant {
typedPropertyValue.readValue(lei); typedPropertyValue.readValue(lei);
} catch ( UnsupportedOperationException exc ) { } catch ( UnsupportedOperationException exc ) {
int propLength = Math.min( length, lei.available() ); int propLength = Math.min( length, lei.available() );
final byte[] v = new byte[propLength]; final byte[] v = IOUtils.safelyAllocate(propLength, MAX_RECORD_LENGTH);
lei.readFully(v, 0, propLength); lei.readFully(v, 0, propLength);
throw new ReadingNotSupportedException( type, v ); throw new ReadingNotSupportedException( type, v );
} }
@ -248,7 +252,7 @@ public class VariantSupport extends Variant {
default: default:
final int unpadded = lei.getReadIndex()-offset; final int unpadded = lei.getReadIndex()-offset;
lei.setReadIndex(offset); lei.setReadIndex(offset);
final byte[] v = new byte[unpadded]; final byte[] v = IOUtils.safelyAllocate(unpadded, MAX_RECORD_LENGTH);
lei.readFully( v, 0, unpadded ); lei.readFully( v, 0, unpadded );
throw new ReadingNotSupportedException( type, v ); throw new ReadingNotSupportedException( type, v );
} }

View File

@ -57,6 +57,9 @@ import org.apache.poi.util.IOUtils;
public class OldExcelExtractor implements Closeable { public class OldExcelExtractor implements Closeable {
private final static int FILE_PASS_RECORD_SID = 0x2f; private final static int FILE_PASS_RECORD_SID = 0x2f;
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private RecordInputStream ris; private RecordInputStream ris;
@ -278,7 +281,7 @@ public class OldExcelExtractor implements Closeable {
break; break;
default: default:
ris.readFully(new byte[ris.remaining()]); ris.readFully(IOUtils.safelyAllocate(ris.remaining(), MAX_RECORD_LENGTH));
} }
} }

View File

@ -36,6 +36,7 @@ import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -50,6 +51,10 @@ import org.apache.poi.util.POILogger;
* this is only used for the other types * this is only used for the other types
*/ */
public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cloneable { public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cloneable {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static final short sid = 0x087A; public static final short sid = 0x087A;
private FtrHeader futureHeader; private FtrHeader futureHeader;
@ -92,7 +97,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
priority = 0; priority = 0;
template_type = getConditionType(); template_type = getConditionType();
template_param_length = 16; template_param_length = 16;
template_params = new byte[template_param_length]; template_params = IOUtils.safelyAllocate(template_param_length, MAX_RECORD_LENGTH);
} }
/** /**
@ -236,7 +241,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
} else { } else {
int len = readFormatOptions(in); int len = readFormatOptions(in);
if (len < ext_formatting_length) { if (len < ext_formatting_length) {
ext_formatting_data = new byte[ext_formatting_length-len]; ext_formatting_data = IOUtils.safelyAllocate(ext_formatting_length-len, MAX_RECORD_LENGTH);
in.readFully(ext_formatting_data); in.readFully(ext_formatting_data);
} }
} }
@ -252,7 +257,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
template_type = in.readUShort(); template_type = in.readUShort();
template_param_length = in.readByte(); template_param_length = in.readByte();
if (template_param_length == 0 || template_param_length == 16) { if (template_param_length == 0 || template_param_length == 16) {
template_params = new byte[template_param_length]; template_params = IOUtils.safelyAllocate(template_param_length, MAX_RECORD_LENGTH);
in.readFully(template_params); in.readFully(template_params);
} else { } else {
logger.log(POILogger.WARN, "CF Rule v12 template params length should be 0 or 16, found " + template_param_length); logger.log(POILogger.WARN, "CF Rule v12 template params length should be 0 or 16, found " + template_param_length);
@ -465,7 +470,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
// use min() to gracefully handle cases where the length-property and the array-length do not match // use min() to gracefully handle cases where the length-property and the array-length do not match
// we saw some such files in circulation // we saw some such files in circulation
rec.ext_formatting_length = Math.min(ext_formatting_length, ext_formatting_data.length); rec.ext_formatting_length = Math.min(ext_formatting_length, ext_formatting_data.length);
rec.ext_formatting_data = new byte[ext_formatting_length]; rec.ext_formatting_data = IOUtils.safelyAllocate(ext_formatting_length, MAX_RECORD_LENGTH);
System.arraycopy(ext_formatting_data, 0, rec.ext_formatting_data, 0, rec.ext_formatting_length); System.arraycopy(ext_formatting_data, 0, rec.ext_formatting_data, 0, rec.ext_formatting_length);
rec.formula_scale = formula_scale.copy(); rec.formula_scale = formula_scale.copy();
@ -474,7 +479,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
rec.priority = priority; rec.priority = priority;
rec.template_type = template_type; rec.template_type = template_type;
rec.template_param_length = template_param_length; rec.template_param_length = template_param_length;
rec.template_params = new byte[template_param_length]; rec.template_params = IOUtils.safelyAllocate(template_param_length, MAX_RECORD_LENGTH);
System.arraycopy(template_params, 0, rec.template_params, 0, template_param_length); System.arraycopy(template_params, 0, rec.template_params, 0, template_param_length);
if (color_gradient != null) { if (color_gradient != null) {
@ -487,7 +492,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
rec.data_bar = (DataBarFormatting)data_bar.clone(); rec.data_bar = (DataBarFormatting)data_bar.clone();
} }
if (filter_data != null) { if (filter_data != null) {
rec.filter_data = new byte[filter_data.length]; rec.filter_data = IOUtils.safelyAllocate(filter_data.length, MAX_RECORD_LENGTH);
System.arraycopy(filter_data, 0, rec.filter_data, 0, filter_data.length); System.arraycopy(filter_data, 0, rec.filter_data, 0, filter_data.length);
} }

View File

@ -20,6 +20,7 @@ package org.apache.poi.hssf.record;
import java.util.Arrays; import java.util.Arrays;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
@ -69,6 +70,9 @@ import org.apache.poi.util.StringUtil;
public class DConRefRecord extends StandardRecord public class DConRefRecord extends StandardRecord
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* The id of the record type, * The id of the record type,
* <code>sid = {@value}</code> * <code>sid = {@value}</code>
@ -142,7 +146,7 @@ public class DConRefRecord extends StandardRecord
*/ */
int byteLength = charCount * ((charType & 1) + 1); int byteLength = charCount * ((charType & 1) + 1);
path = LittleEndian.getByteArray(data, offset, byteLength); path = LittleEndian.getByteArray(data, offset, byteLength, MAX_RECORD_LENGTH);
offset += byteLength; offset += byteLength;
/* /*
@ -150,7 +154,7 @@ public class DConRefRecord extends StandardRecord
* unused field. Not sure If i need to bother with this... * unused field. Not sure If i need to bother with this...
*/ */
if (path[0] == 0x02) if (path[0] == 0x02)
_unused = LittleEndian.getByteArray(data, offset, (charType + 1)); _unused = LittleEndian.getByteArray(data, offset, (charType + 1), MAX_RECORD_LENGTH);
} }
@ -175,7 +179,7 @@ public class DConRefRecord extends StandardRecord
// byteLength depends on whether we are using single- or double-byte chars. // byteLength depends on whether we are using single- or double-byte chars.
int byteLength = charCount * (charType + 1); int byteLength = charCount * (charType + 1);
path = new byte[byteLength]; path = IOUtils.safelyAllocate(byteLength, MAX_RECORD_LENGTH);
inStream.readFully(path); inStream.readFully(path);
if (path[0] == 0x02) if (path[0] == 0x02)

View File

@ -25,6 +25,7 @@ import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.Ref3DPtg; import org.apache.poi.ss.formula.ptg.Ref3DPtg;
import org.apache.poi.ss.formula.ptg.RefPtg; import org.apache.poi.ss.formula.ptg.RefPtg;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianInputStream; import org.apache.poi.util.LittleEndianInputStream;
@ -41,6 +42,9 @@ import org.apache.poi.util.StringUtil;
*/ */
public final class EmbeddedObjectRefSubRecord extends SubRecord implements Cloneable { public final class EmbeddedObjectRefSubRecord extends SubRecord implements Cloneable {
private static POILogger logger = POILogFactory.getLogger(EmbeddedObjectRefSubRecord.class); private static POILogger logger = POILogFactory.getLogger(EmbeddedObjectRefSubRecord.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static final short sid = 0x0009; public static final short sid = 0x0009;
private static final byte[] EMPTY_BYTE_ARRAY = { }; private static final byte[] EMPTY_BYTE_ARRAY = { };
@ -173,7 +177,7 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone
if (size == 0) { if (size == 0) {
return EMPTY_BYTE_ARRAY; return EMPTY_BYTE_ARRAY;
} }
byte[] result = new byte[size]; byte[] result = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
in.readFully(result); in.readFully(result);
return result; return result;
} }

View File

@ -36,6 +36,7 @@ import org.apache.poi.ddf.EscherSerializationListener;
import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherSpgrRecord; import org.apache.poi.ddf.EscherSpgrRecord;
import org.apache.poi.ddf.EscherTextboxRecord; import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
@ -85,6 +86,9 @@ import org.apache.poi.util.RecordFormatException;
public final class EscherAggregate extends AbstractEscherHolderRecord { public final class EscherAggregate extends AbstractEscherHolderRecord {
public static final short sid = 9876; // not a real sid - dummy value public static final short sid = 9876; // not a real sid - dummy value
private static POILogger log = POILogFactory.getLogger(EscherAggregate.class); private static POILogger log = POILogFactory.getLogger(EscherAggregate.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000_000;
public static final short ST_MIN = (short) 0; public static final short ST_MIN = (short) 0;
public static final short ST_NOT_PRIMATIVE = ST_MIN; public static final short ST_NOT_PRIMATIVE = ST_MIN;
@ -592,7 +596,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord {
// Determine buffer size // Determine buffer size
List<EscherRecord> records = getEscherRecords(); List<EscherRecord> records = getEscherRecords();
int rawEscherSize = getEscherRecordSize(records); int rawEscherSize = getEscherRecordSize(records);
byte[] buffer = new byte[rawEscherSize]; byte[] buffer = IOUtils.safelyAllocate(rawEscherSize, MAX_RECORD_LENGTH);
final List<Integer> spEndingOffsets = new ArrayList<>(); final List<Integer> spEndingOffsets = new ArrayList<>();
int pos = 0; int pos = 0;
for (EscherRecord e : records) { for (EscherRecord e : records) {

View File

@ -18,6 +18,7 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
@ -48,7 +49,7 @@ public final class FtCblsSubRecord extends SubRecord implements Cloneable {
throw new RecordFormatException("Unexpected size (" + size + ")"); throw new RecordFormatException("Unexpected size (" + size + ")");
} }
//just grab the raw data //just grab the raw data
byte[] buf = new byte[size]; byte[] buf = IOUtils.safelyAllocate(size, ENCODED_SIZE);
in.readFully(buf); in.readFully(buf);
reserved = buf; reserved = buf;
} }

View File

@ -18,6 +18,7 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
@ -27,6 +28,9 @@ import org.apache.poi.util.LittleEndianOutput;
*/ */
public final class GroupMarkerSubRecord extends SubRecord implements Cloneable { public final class GroupMarkerSubRecord extends SubRecord implements Cloneable {
public final static short sid = 0x0006; public final static short sid = 0x0006;
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private static final byte[] EMPTY_BYTE_ARRAY = { }; private static final byte[] EMPTY_BYTE_ARRAY = { };
@ -38,7 +42,7 @@ public final class GroupMarkerSubRecord extends SubRecord implements Cloneable {
} }
public GroupMarkerSubRecord(LittleEndianInput in, int size) { public GroupMarkerSubRecord(LittleEndianInput in, int size) {
byte[] buf = new byte[size]; byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
in.readFully(buf); in.readFully(buf);
reserved = buf; reserved = buf;
} }

View File

@ -20,6 +20,7 @@ package org.apache.poi.hssf.record;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.HexRead; import org.apache.poi.util.HexRead;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
@ -36,6 +37,9 @@ import org.apache.poi.util.StringUtil;
public final class HyperlinkRecord extends StandardRecord implements Cloneable { public final class HyperlinkRecord extends StandardRecord implements Cloneable {
public final static short sid = 0x01B8; public final static short sid = 0x01B8;
private static POILogger logger = POILogFactory.getLogger(HyperlinkRecord.class); private static POILogger logger = POILogFactory.getLogger(HyperlinkRecord.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
static final class GUID { static final class GUID {
/* /*
@ -525,7 +529,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable {
int len = in.readInt(); int len = in.readInt();
byte[] path_bytes = new byte[len]; byte[] path_bytes = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH);
in.readFully(path_bytes); in.readFully(path_bytes);
_address = new String(path_bytes, StringUtil.UTF8); _address = new String(path_bytes, StringUtil.UTF8);

View File

@ -18,6 +18,7 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
@ -55,7 +56,7 @@ public final class NoteStructureSubRecord extends SubRecord implements Cloneable
throw new RecordFormatException("Unexpected size (" + size + ")"); throw new RecordFormatException("Unexpected size (" + size + ")");
} }
//just grab the raw data //just grab the raw data
byte[] buf = new byte[size]; byte[] buf = IOUtils.safelyAllocate(size, ENCODED_SIZE);
in.readFully(buf); in.readFully(buf);
reserved = buf; reserved = buf;
} }

View File

@ -18,6 +18,7 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
@ -29,6 +30,8 @@ import org.apache.poi.util.RecordFormatException;
*/ */
public final class OldLabelRecord extends OldCellRecord { public final class OldLabelRecord extends OldCellRecord {
private final static POILogger logger = POILogFactory.getLogger(OldLabelRecord.class); private final static POILogger logger = POILogFactory.getLogger(OldLabelRecord.class);
//arbitrarily set, may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public final static short biff2_sid = 0x0004; public final static short biff2_sid = 0x0004;
public final static short biff345_sid = 0x0204; public final static short biff345_sid = 0x0204;
@ -51,7 +54,7 @@ public final class OldLabelRecord extends OldCellRecord {
} }
// Can only decode properly later when you know the codepage // Can only decode properly later when you know the codepage
field_5_bytes = new byte[field_4_string_len]; field_5_bytes = IOUtils.safelyAllocate(field_4_string_len, MAX_RECORD_LENGTH);
in.read(field_5_bytes, 0, field_4_string_len); in.read(field_5_bytes, 0, field_4_string_len);
if (in.remaining() > 0) { if (in.remaining() > 0) {

View File

@ -18,6 +18,7 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
/** /**
* Title: Bound Sheet Record (aka BundleSheet) (0x0085) for BIFF 5<P> * Title: Bound Sheet Record (aka BundleSheet) (0x0085) for BIFF 5<P>
@ -26,6 +27,10 @@ import org.apache.poi.util.HexDump;
* file. * file.
*/ */
public final class OldSheetRecord { public final class OldSheetRecord {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public final static short sid = 0x0085; public final static short sid = 0x0085;
private int field_1_position_of_BOF; private int field_1_position_of_BOF;
@ -39,7 +44,7 @@ public final class OldSheetRecord {
field_2_visibility = in.readUByte(); field_2_visibility = in.readUByte();
field_3_type = in.readUByte(); field_3_type = in.readUByte();
int field_4_sheetname_length = in.readUByte(); int field_4_sheetname_length = in.readUByte();
field_5_sheetname = new byte[field_4_sheetname_length]; field_5_sheetname = IOUtils.safelyAllocate(field_4_sheetname_length, MAX_RECORD_LENGTH);
in.read(field_5_sheetname, 0, field_4_sheetname_length); in.read(field_5_sheetname, 0, field_4_sheetname_length);
} }

View File

@ -21,6 +21,7 @@ import java.io.UnsupportedEncodingException;
import org.apache.poi.hpsf.Property; import org.apache.poi.hpsf.Property;
import org.apache.poi.util.CodePageUtil; import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.IOUtils;
/** /**
@ -28,6 +29,10 @@ import org.apache.poi.util.CodePageUtil;
* formula string results. * formula string results.
*/ */
public final class OldStringRecord { public final class OldStringRecord {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public final static short biff2_sid = 0x0007; public final static short biff2_sid = 0x0007;
public final static short biff345_sid = 0x0207; public final static short biff345_sid = 0x0207;
@ -49,7 +54,7 @@ public final class OldStringRecord {
} }
// Can only decode properly later when you know the codepage // Can only decode properly later when you know the codepage
field_2_bytes = new byte[field_1_string_len]; field_2_bytes = IOUtils.safelyAllocate(field_1_string_len, MAX_RECORD_LENGTH);
in.read(field_2_bytes, 0, field_1_string_len); in.read(field_2_bytes, 0, field_1_string_len);
} }

View File

@ -25,6 +25,7 @@ import java.util.Locale;
import org.apache.poi.hssf.dev.BiffViewer; import org.apache.poi.hssf.dev.BiffViewer;
import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream; import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream;
import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
@ -36,9 +37,13 @@ import org.apache.poi.util.RecordFormatException;
* Description: Wraps a stream and provides helper methods for the construction of records.<P> * Description: Wraps a stream and provides helper methods for the construction of records.<P>
*/ */
public final class RecordInputStream implements LittleEndianInput { public final class RecordInputStream implements LittleEndianInput {
/** Maximum size of a single record (minus the 4 byte header) without a continue*/ /** Maximum size of a single record (minus the 4 byte header) without a continue*/
public final static short MAX_RECORD_DATA_SIZE = 8224; public final static short MAX_RECORD_DATA_SIZE = 8224;
private static final int INVALID_SID_VALUE = -1; private static final int INVALID_SID_VALUE = -1;
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* When {@link #_currentDataLength} has this value, it means that the previous BIFF record is * When {@link #_currentDataLength} has this value, it means that the previous BIFF record is
* finished, the next sid has been properly read, but the data size field has not been read yet. * finished, the next sid has been properly read, but the data size field has not been read yet.
@ -441,7 +446,7 @@ public final class RecordInputStream implements LittleEndianInput {
if (size ==0) { if (size ==0) {
return EMPTY_BYTE_ARRAY; return EMPTY_BYTE_ARRAY;
} }
byte[] result = new byte[size]; byte[] result = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
readFully(result); readFully(result);
return result; return result;
} }

View File

@ -18,6 +18,7 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.LittleEndianOutputStream; import org.apache.poi.util.LittleEndianOutputStream;
@ -28,6 +29,10 @@ import java.io.ByteArrayOutputStream;
* Subrecords are part of the OBJ class. * Subrecords are part of the OBJ class.
*/ */
public abstract class SubRecord { public abstract class SubRecord {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
protected SubRecord() { protected SubRecord() {
// no fields to initialise // no fields to initialise
} }
@ -107,7 +112,7 @@ public abstract class SubRecord {
public UnknownSubRecord(LittleEndianInput in, int sid, int size) { public UnknownSubRecord(LittleEndianInput in, int sid, int size) {
_sid = sid; _sid = sid;
byte[] buf = new byte[size]; byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
in.readFully(buf); in.readFully(buf);
_data = buf; _data = buf;
} }

View File

@ -28,6 +28,7 @@ import org.apache.poi.hssf.record.cont.ContinuableRecordInput;
import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; import org.apache.poi.hssf.record.cont.ContinuableRecordOutput;
import org.apache.poi.util.BitField; import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
@ -46,6 +47,10 @@ public class UnicodeString implements Comparable<UnicodeString> {
// TODO - make this final when the compatibility version is removed // TODO - make this final when the compatibility version is removed
private static POILogger _logger = POILogFactory.getLogger(UnicodeString.class); private static POILogger _logger = POILogFactory.getLogger(UnicodeString.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private short field_1_charCount; private short field_1_charCount;
private byte field_2_optionflags; private byte field_2_optionflags;
private String field_3_string; private String field_3_string;
@ -196,7 +201,7 @@ public class UnicodeString implements Comparable<UnicodeString> {
_logger.log( POILogger.WARN, "Warning - ExtRst overran by " + (0-extraDataLength) + " bytes"); _logger.log( POILogger.WARN, "Warning - ExtRst overran by " + (0-extraDataLength) + " bytes");
extraDataLength = 0; extraDataLength = 0;
} }
extraData = new byte[extraDataLength]; extraData = IOUtils.safelyAllocate(extraDataLength, MAX_RECORD_LENGTH);
for(int i=0; i<extraData.length; i++) { for(int i=0; i<extraData.length; i++) {
extraData[i] = in.readByte(); extraData[i] = in.readByte();
} }

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.record.InterfaceHdrRecord;
import org.apache.poi.poifs.crypt.ChunkedCipherInputStream; import org.apache.poi.poifs.crypt.ChunkedCipherInputStream;
import org.apache.poi.poifs.crypt.Decryptor; import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
@ -35,6 +36,8 @@ import org.apache.poi.util.RecordFormatException;
public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndianInput { public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndianInput {
public static final int RC4_REKEYING_INTERVAL = 1024; public static final int RC4_REKEYING_INTERVAL = 1024;
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private final EncryptionInfo info; private final EncryptionInfo info;
private ChunkedCipherInputStream ccis; private ChunkedCipherInputStream ccis;
@ -43,7 +46,7 @@ public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndia
public Biff8DecryptingStream(InputStream in, int initialOffset, EncryptionInfo info) throws RecordFormatException { public Biff8DecryptingStream(InputStream in, int initialOffset, EncryptionInfo info) throws RecordFormatException {
try { try {
byte initialBuf[] = new byte[initialOffset]; byte initialBuf[] = IOUtils.safelyAllocate(initialOffset, MAX_RECORD_LENGTH);
InputStream stream; InputStream stream;
if (initialOffset == 0) { if (initialOffset == 0) {
stream = in; stream = in;

View File

@ -112,6 +112,7 @@ import org.apache.poi.ss.usermodel.SheetVisibility;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.Configurator; import org.apache.poi.util.Configurator;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianByteArrayInputStream;
@ -128,6 +129,10 @@ import org.apache.poi.util.POILogger;
* @see org.apache.poi.hssf.usermodel.HSSFSheet * @see org.apache.poi.hssf.usermodel.HSSFSheet
*/ */
public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook { public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private static final Pattern COMMA_PATTERN = Pattern.compile(","); private static final Pattern COMMA_PATTERN = Pattern.compile(",");
/** /**
@ -1552,7 +1557,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
if (sid == BoundSheetRecord.sid) { if (sid == BoundSheetRecord.sid) {
// special case for the field_1_position_of_BOF (=lbPlyPos) field of // special case for the field_1_position_of_BOF (=lbPlyPos) field of
// the BoundSheet8 record which must be unencrypted // the BoundSheet8 record which must be unencrypted
byte bsrBuf[] = new byte[len]; byte bsrBuf[] = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH);
plain.readFully(bsrBuf); plain.readFully(bsrBuf);
os.writePlain(bsrBuf, 0, 4); os.writePlain(bsrBuf, 0, 4);
os.write(bsrBuf, 4, len-4); os.write(bsrBuf, 4, len-4);

View File

@ -27,11 +27,16 @@ import javax.crypto.IllegalBlockSizeException;
import javax.crypto.ShortBufferException; import javax.crypto.ShortBufferException;
import org.apache.poi.EncryptedDocumentException; import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianInputStream; import org.apache.poi.util.LittleEndianInputStream;
@Internal @Internal
public abstract class ChunkedCipherInputStream extends LittleEndianInputStream { public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private final int chunkSize; private final int chunkSize;
private final int chunkBits; private final int chunkBits;
@ -55,8 +60,8 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
this.pos = initialPos; this.pos = initialPos;
this.chunkSize = chunkSize; this.chunkSize = chunkSize;
int cs = chunkSize == -1 ? 4096 : chunkSize; int cs = chunkSize == -1 ? 4096 : chunkSize;
this.chunk = new byte[cs]; this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
this.plain = new byte[cs]; this.plain = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
this.chunkBits = Integer.bitCount(chunk.length-1); this.chunkBits = Integer.bitCount(chunk.length-1);
this.lastIndex = (int)(pos >> chunkBits); this.lastIndex = (int)(pos >> chunkBits);
this.cipher = initCipherForBlock(null, lastIndex); this.cipher = initCipherForBlock(null, lastIndex);

View File

@ -47,6 +47,9 @@ import org.apache.poi.util.TempFile;
@Internal @Internal
public abstract class ChunkedCipherOutputStream extends FilterOutputStream { public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
private static final POILogger LOG = POILogFactory.getLogger(ChunkedCipherOutputStream.class); private static final POILogger LOG = POILogFactory.getLogger(ChunkedCipherOutputStream.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private static final int STREAMING = -1; private static final int STREAMING = -1;
private final int chunkSize; private final int chunkSize;
@ -70,7 +73,7 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
super(null); super(null);
this.chunkSize = chunkSize; this.chunkSize = chunkSize;
int cs = chunkSize == STREAMING ? 4096 : chunkSize; int cs = chunkSize == STREAMING ? 4096 : chunkSize;
this.chunk = new byte[cs]; this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
this.plainByteFlags = new BitSet(cs); this.plainByteFlags = new BitSet(cs);
this.chunkBits = Integer.bitCount(cs-1); this.chunkBits = Integer.bitCount(cs-1);
this.fileOut = TempFile.createTempFile("encrypted_package", "crypt"); this.fileOut = TempFile.createTempFile("encrypted_package", "crypt");
@ -84,7 +87,7 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
super(stream); super(stream);
this.chunkSize = chunkSize; this.chunkSize = chunkSize;
int cs = chunkSize == STREAMING ? 4096 : chunkSize; int cs = chunkSize == STREAMING ? 4096 : chunkSize;
this.chunk = new byte[cs]; this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
this.plainByteFlags = new BitSet(cs); this.plainByteFlags = new BitSet(cs);
this.chunkBits = Integer.bitCount(cs-1); this.chunkBits = Integer.bitCount(cs-1);
this.fileOut = null; this.fileOut = null;

View File

@ -34,6 +34,7 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.RC2ParameterSpec; import javax.crypto.spec.RC2ParameterSpec;
import org.apache.poi.EncryptedDocumentException; import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
@ -44,6 +45,10 @@ import org.apache.poi.util.StringUtil;
*/ */
@Internal @Internal
public class CryptoFunctions { public class CryptoFunctions {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* <p><cite>2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)<br> * <p><cite>2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)<br>
* 2.3.4.11 Encryption Key Generation (Agile Encryption)</cite></p> * 2.3.4.11 Encryption Key Generation (Agile Encryption)</cite></p>
@ -280,7 +285,7 @@ public class CryptoFunctions {
private static byte[] getBlockX(byte[] hash, int size, byte fill) { private static byte[] getBlockX(byte[] hash, int size, byte fill) {
if (hash.length == size) return hash; if (hash.length == size) return hash;
byte[] result = new byte[size]; byte[] result = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
Arrays.fill(result, fill); Arrays.fill(result, fill);
System.arraycopy(hash, 0, result, 0, Math.min(result.length, hash.length)); System.arraycopy(hash, 0, result, 0, Math.min(result.length, hash.length));
return result; return result;

View File

@ -26,6 +26,7 @@ import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSWriterEvent; import org.apache.poi.poifs.filesystem.POIFSWriterEvent;
import org.apache.poi.poifs.filesystem.POIFSWriterListener; import org.apache.poi.poifs.filesystem.POIFSWriterListener;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.LittleEndianByteArrayOutputStream;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
@ -33,6 +34,10 @@ import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
public class DataSpaceMapUtils { public class DataSpaceMapUtils {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static void addDefaultDataSpace(DirectoryEntry dir) throws IOException { public static void addDefaultDataSpace(DirectoryEntry dir) throws IOException {
DataSpaceMapEntry dsme = new DataSpaceMapEntry( DataSpaceMapEntry dsme = new DataSpaceMapEntry(
new int[]{ 0 } new int[]{ 0 }
@ -332,7 +337,7 @@ public class DataSpaceMapUtils {
return length == 0 ? null : ""; return length == 0 ? null : "";
} }
byte data[] = new byte[length]; byte data[] = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH);
is.readFully(data); is.readFully(data);
// Padding (variable): A set of bytes that MUST be of correct size such that the size of the UTF-8-LP-P4 // Padding (variable): A set of bytes that MUST be of correct size such that the size of the UTF-8-LP-P4

View File

@ -39,6 +39,10 @@ import org.apache.poi.util.IOUtils;
* Dump internal structure of a OLE2 file into file system * Dump internal structure of a OLE2 file into file system
*/ */
public class POIFSDump { public class POIFSDump {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
if (args.length == 0) { if (args.length == 0) {
System.err.println("Must specify at least one file to dump"); System.err.println("Must specify at least one file to dump");
@ -132,7 +136,7 @@ public class POIFSDump {
try { try {
NPOIFSStream stream = new NPOIFSStream(fs, startBlock); NPOIFSStream stream = new NPOIFSStream(fs, startBlock);
byte[] b = new byte[fs.getBigBlockSize()]; byte[] b = IOUtils.safelyAllocate(fs.getBigBlockSize(), MAX_RECORD_LENGTH);
for (ByteBuffer bb : stream) { for (ByteBuffer bb : stream) {
int len = bb.remaining(); int len = bb.remaining();
bb.get(b); bb.get(b);

View File

@ -20,6 +20,7 @@ package org.apache.poi.poifs.filesystem;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.SuppressForbidden; import org.apache.poi.util.SuppressForbidden;

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import java.util.Iterator; import java.util.Iterator;
import org.apache.poi.poifs.property.DocumentProperty; import org.apache.poi.poifs.property.DocumentProperty;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -224,7 +225,7 @@ public final class NDocumentInputStream extends DocumentInputStream {
long rval = new_offset - _current_offset; long rval = new_offset - _current_offset;
// TODO Do this better // TODO Do this better
byte[] skip = new byte[(int)rval]; byte[] skip = IOUtils.safelyAllocate(rval, Integer.MAX_VALUE);
readFully(skip); readFully(skip);
return rval; return rval;
} }

View File

@ -31,13 +31,18 @@ import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.dev.POIFSViewable; import org.apache.poi.poifs.dev.POIFSViewable;
import org.apache.poi.poifs.property.DocumentProperty; import org.apache.poi.poifs.property.DocumentProperty;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
/** /**
* This class manages a document in the NIO POIFS filesystem. * This class manages a document in the NIO POIFS filesystem.
* This is the {@link NPOIFSFileSystem} version. * This is the {@link NPOIFSFileSystem} version.
*/ */
public final class NPOIFSDocument implements POIFSViewable { public final class NPOIFSDocument implements POIFSViewable {
private DocumentProperty _property;
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private DocumentProperty _property;
private NPOIFSFileSystem _filesystem; private NPOIFSFileSystem _filesystem;
private NPOIFSStream _stream; private NPOIFSStream _stream;
@ -147,7 +152,7 @@ public final class NPOIFSDocument implements POIFSViewable {
int usedInBlock = length % _block_size; int usedInBlock = length % _block_size;
if (usedInBlock != 0 && usedInBlock != _block_size) { if (usedInBlock != 0 && usedInBlock != _block_size) {
int toBlockEnd = _block_size - usedInBlock; int toBlockEnd = _block_size - usedInBlock;
byte[] padding = new byte[toBlockEnd]; byte[] padding = IOUtils.safelyAllocate(toBlockEnd, MAX_RECORD_LENGTH);
Arrays.fill(padding, (byte)0xFF); Arrays.fill(padding, (byte)0xFF);
os.write(padding); os.write(padding);
} }
@ -214,7 +219,7 @@ public final class NPOIFSDocument implements POIFSViewable {
if(getSize() > 0) { if(getSize() > 0) {
// Get all the data into a single array // Get all the data into a single array
byte[] data = new byte[getSize()]; byte[] data = IOUtils.safelyAllocate(getSize(), MAX_RECORD_LENGTH);
int offset = 0; int offset = 0;
for(ByteBuffer buffer : _stream) { for(ByteBuffer buffer : _stream) {
int length = Math.min(_block_size, data.length-offset); int length = Math.min(_block_size, data.length-offset);

View File

@ -66,7 +66,10 @@ import org.apache.poi.util.POILogger;
public class NPOIFSFileSystem extends BlockStore public class NPOIFSFileSystem extends BlockStore
implements POIFSViewable, Closeable implements POIFSViewable, Closeable
{ {
private static final POILogger LOG = POILogFactory.getLogger(NPOIFSFileSystem.class); //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private static final POILogger LOG = POILogFactory.getLogger(NPOIFSFileSystem.class);
/** /**
* Convenience method for clients that want to avoid the auto-close behaviour of the constructor. * Convenience method for clients that want to avoid the auto-close behaviour of the constructor.
@ -103,7 +106,8 @@ public class NPOIFSFileSystem extends BlockStore
if(newFS) { if(newFS) {
// Data needs to initially hold just the header block, // Data needs to initially hold just the header block,
// a single bat block, and an empty properties section // a single bat block, and an empty properties section
_data = new ByteArrayBackedDataSource(new byte[bigBlockSize.getBigBlockSize()*3]); _data = new ByteArrayBackedDataSource(IOUtils.safelyAllocate(
bigBlockSize.getBigBlockSize()*3, MAX_RECORD_LENGTH));
} }
} }

View File

@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianOutputStream; import org.apache.poi.util.LittleEndianOutputStream;
@ -34,9 +35,12 @@ import org.apache.poi.util.StringUtil;
*/ */
public class Ole10Native { public class Ole10Native {
public static final String OLE10_NATIVE = "\u0001Ole10Native"; public static final String OLE10_NATIVE = "\u0001Ole10Native";
protected static final String ISO1 = "ISO-8859-1"; protected static final String ISO1 = "ISO-8859-1";
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000_000;
// (the fields as they appear in the raw record:) // (the fields as they appear in the raw record:)
private int totalSize; // 4 bytes, total size of record not including this field private int totalSize; // 4 bytes, total size of record not including this field
private short flags1 = 2; // 2 bytes, unknown, mostly [02 00] private short flags1 = 2; // 2 bytes, unknown, mostly [02 00]
@ -97,7 +101,7 @@ public class Ole10Native {
public static Ole10Native createFromEmbeddedOleObject(DirectoryNode directory) throws IOException, Ole10NativeException { public static Ole10Native createFromEmbeddedOleObject(DirectoryNode directory) throws IOException, Ole10NativeException {
DocumentEntry nativeEntry = DocumentEntry nativeEntry =
(DocumentEntry)directory.getEntry(OLE10_NATIVE); (DocumentEntry)directory.getEntry(OLE10_NATIVE);
byte[] data = new byte[nativeEntry.getSize()]; byte[] data = IOUtils.safelyAllocate(nativeEntry.getSize(), MAX_RECORD_LENGTH);
int readBytes = directory.createDocumentInputStream(nativeEntry).read(data); int readBytes = directory.createDocumentInputStream(nativeEntry).read(data);
assert(readBytes == data.length); assert(readBytes == data.length);
@ -196,7 +200,7 @@ public class Ole10Native {
if ((long)dataSize + (long)ofs > (long)data.length) { //cast to avoid overflow if ((long)dataSize + (long)ofs > (long)data.length) { //cast to avoid overflow
throw new Ole10NativeException("Invalid Ole10Native: declared data length > available data"); throw new Ole10NativeException("Invalid Ole10Native: declared data length > available data");
} }
dataBuffer = new byte[dataSize]; dataBuffer = IOUtils.safelyAllocate(dataSize, MAX_RECORD_LENGTH);
System.arraycopy(data, ofs, dataBuffer, 0, dataSize); System.arraycopy(data, ofs, dataBuffer, 0, dataSize);
ofs += dataSize; ofs += dataSize;
} }

View File

@ -17,6 +17,8 @@
package org.apache.poi.poifs.nio; package org.apache.poi.poifs.nio;
import org.apache.poi.util.IOUtils;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -25,6 +27,9 @@ import java.nio.ByteBuffer;
* A POIFS {@link DataSource} backed by a byte array. * A POIFS {@link DataSource} backed by a byte array.
*/ */
public class ByteArrayBackedDataSource extends DataSource { public class ByteArrayBackedDataSource extends DataSource {
//Can we make this shorter?
private static final int MAX_RECORD_LENGTH = Integer.MAX_VALUE;
private byte[] buffer; private byte[] buffer;
private long size; private long size;
@ -76,7 +81,8 @@ public class ByteArrayBackedDataSource extends DataSource {
difference = 4096; difference = 4096;
} }
byte[] nb = new byte[(int)(difference+buffer.length)]; long totalLen = difference+buffer.length;
byte[] nb = IOUtils.safelyAllocate(totalLen, MAX_RECORD_LENGTH);
System.arraycopy(buffer, 0, nb, 0, (int)size); System.arraycopy(buffer, 0, nb, 0, (int)size);
buffer = nb; buffer = nb;
} }

View File

@ -29,6 +29,7 @@ import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.NPOIFSStream; import org.apache.poi.poifs.filesystem.NPOIFSStream;
import org.apache.poi.poifs.storage.HeaderBlock; import org.apache.poi.poifs.storage.HeaderBlock;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -40,6 +41,9 @@ import org.apache.poi.util.POILogger;
public final class NPropertyTable extends PropertyTableBase { public final class NPropertyTable extends PropertyTableBase {
private static final POILogger _logger = private static final POILogger _logger =
POILogFactory.getLogger(NPropertyTable.class); POILogFactory.getLogger(NPropertyTable.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private POIFSBigBlockSize _bigBigBlockSize; private POIFSBigBlockSize _bigBigBlockSize;
public NPropertyTable(HeaderBlock headerBlock) public NPropertyTable(HeaderBlock headerBlock)
@ -86,7 +90,7 @@ public final class NPropertyTable extends PropertyTableBase {
bb.array().length == bigBlockSize.getBigBlockSize()) { bb.array().length == bigBlockSize.getBigBlockSize()) {
data = bb.array(); data = bb.array();
} else { } else {
data = new byte[bigBlockSize.getBigBlockSize()]; data = IOUtils.safelyAllocate(bigBlockSize.getBigBlockSize(), MAX_RECORD_LENGTH);
int toRead = data.length; int toRead = data.length;
if (bb.remaining() < bigBlockSize.getBigBlockSize()) { if (bb.remaining() < bigBlockSize.getBigBlockSize()) {

View File

@ -32,6 +32,10 @@ import org.apache.poi.util.IOUtils;
* @author Marc Johnson (mjohnson at apache dot org) * @author Marc Johnson (mjohnson at apache dot org)
*/ */
public final class DocumentBlock extends BigBlock { public final class DocumentBlock extends BigBlock {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private static final byte _default_value = ( byte ) 0xFF; private static final byte _default_value = ( byte ) 0xFF;
private byte[] _data; private byte[] _data;
private int _bytes_read; private int _bytes_read;
@ -81,7 +85,7 @@ public final class DocumentBlock extends BigBlock {
private DocumentBlock(POIFSBigBlockSize bigBlockSize) private DocumentBlock(POIFSBigBlockSize bigBlockSize)
{ {
super(bigBlockSize); super(bigBlockSize);
_data = new byte[ bigBlockSize.getBigBlockSize() ]; _data = IOUtils.safelyAllocate(bigBlockSize.getBigBlockSize(), MAX_RECORD_LENGTH);
Arrays.fill(_data, _default_value); Arrays.fill(_data, _default_value);
} }

View File

@ -41,7 +41,11 @@ import org.apache.poi.util.ShortField;
* The block containing the archive header * The block containing the archive header
*/ */
public final class HeaderBlock implements HeaderBlockConstants { public final class HeaderBlock implements HeaderBlockConstants {
private static final byte _default_value = ( byte ) 0xFF;
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private static final byte _default_value = ( byte ) 0xFF;
/** /**
* What big block size the file uses. Most files * What big block size the file uses. Most files
@ -104,7 +108,7 @@ public final class HeaderBlock implements HeaderBlockConstants {
// Fetch the rest of the block if needed // Fetch the rest of the block if needed
if(bigBlockSize.getBigBlockSize() != 512) { if(bigBlockSize.getBigBlockSize() != 512) {
int rest = bigBlockSize.getBigBlockSize() - 512; int rest = bigBlockSize.getBigBlockSize() - 512;
byte[] tmp = new byte[rest]; byte[] tmp = IOUtils.safelyAllocate(rest, MAX_RECORD_LENGTH);
IOUtils.readFully(stream, tmp); IOUtils.readFully(stream, tmp);
} }
} }

View File

@ -35,6 +35,9 @@ import java.io.*;
public class RawDataBlock public class RawDataBlock
implements ListManagedBlock implements ListManagedBlock
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private byte[] _data; private byte[] _data;
private boolean _eof; private boolean _eof;
private boolean _hasData; private boolean _hasData;
@ -66,7 +69,7 @@ public class RawDataBlock
*/ */
public RawDataBlock(final InputStream stream, int blockSize) public RawDataBlock(final InputStream stream, int blockSize)
throws IOException { throws IOException {
_data = new byte[ blockSize ]; _data = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH);
int count = IOUtils.readFully(stream, _data); int count = IOUtils.readFully(stream, _data);
_hasData = (count > 0); _hasData = (count > 0);

View File

@ -23,6 +23,7 @@ import org.apache.poi.ss.formula.ptg.ExpPtg;
import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.TblPtg; import org.apache.poi.ss.formula.ptg.TblPtg;
import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
@ -35,6 +36,9 @@ import org.apache.poi.util.LittleEndianOutput;
*/ */
public class Formula { public class Formula {
//Arbitrarily set. May need to increase.
private static final int MAX_ENCODED_LEN = 100000;
private static final Formula EMPTY = new Formula(new byte[0], 0); private static final Formula EMPTY = new Formula(new byte[0], 0);
/** immutable */ /** immutable */
@ -72,7 +76,7 @@ public class Formula {
* @return A new formula object as read from the stream. Possibly empty, never <code>null</code>. * @return A new formula object as read from the stream. Possibly empty, never <code>null</code>.
*/ */
public static Formula read(int encodedTokenLen, LittleEndianInput in, int totalEncodedLen) { public static Formula read(int encodedTokenLen, LittleEndianInput in, int totalEncodedLen) {
byte[] byteEncoding = new byte[totalEncodedLen]; byte[] byteEncoding = IOUtils.safelyAllocate(totalEncodedLen, MAX_ENCODED_LEN);
in.readFully(byteEncoding); in.readFully(byteEncoding);
return new Formula(byteEncoding, encodedTokenLen); return new Formula(byteEncoding, encodedTokenLen);
} }

View File

@ -28,6 +28,7 @@ import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.util.IOUtils;
/** /**
* Converts the text meta-data file into a <tt>FunctionMetadataRegistry</tt> * Converts the text meta-data file into a <tt>FunctionMetadataRegistry</tt>
@ -36,6 +37,9 @@ import org.apache.poi.ss.formula.ptg.Ptg;
*/ */
final class FunctionMetadataReader { final class FunctionMetadataReader {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private static final String METADATA_FILE_NAME = "functionMetadata.txt"; private static final String METADATA_FILE_NAME = "functionMetadata.txt";
/** plain ASCII text metadata file uses three dots for ellipsis */ /** plain ASCII text metadata file uses three dots for ellipsis */
@ -141,7 +145,7 @@ final class FunctionMetadataReader {
// (all unspecified params are assumed to be the same as the last) // (all unspecified params are assumed to be the same as the last)
nItems --; nItems --;
} }
byte[] result = new byte[nItems]; byte[] result = IOUtils.safelyAllocate(nItems, MAX_RECORD_LENGTH);
for (int i = 0; i < nItems; i++) { for (int i = 0; i < nItems; i++) {
result[i] = parseOperandTypeCode(array[i]); result[i] = parseOperandTypeCode(array[i]);
} }

View File

@ -34,12 +34,26 @@ public final class IOUtils {
* The default buffer size to use for the skip() methods. * The default buffer size to use for the skip() methods.
*/ */
private static final int SKIP_BUFFER_SIZE = 2048; private static final int SKIP_BUFFER_SIZE = 2048;
private static int BYTE_ARRAY_MAX_OVERRIDE = -1;
private static byte[] SKIP_BYTE_BUFFER; private static byte[] SKIP_BYTE_BUFFER;
private IOUtils() { private IOUtils() {
// no instances of this class // no instances of this class
} }
/**
* If this value is set to > 0, {@link #safelyAllocate(long, int)} will ignore the
* maximum record length parameter. This is designed to allow users to bypass
* the hard-coded maximum record lengths if they are willing to accept the risk
* of an OutOfMemoryException.
*
* @param maxOverride
* @since 4.0.0
*/
public static void setByteArrayMaxOverride(int maxOverride) {
BYTE_ARRAY_MAX_OVERRIDE = maxOverride;
}
/** /**
* Peeks at the first 8 bytes of the stream. Returns those bytes, but * Peeks at the first 8 bytes of the stream. Returns those bytes, but
* with the stream unaffected. Requires a stream that supports mark/reset, * with the stream unaffected. Requires a stream that supports mark/reset,
@ -480,12 +494,23 @@ public final class IOUtils {
if (length > (long)Integer.MAX_VALUE) { if (length > (long)Integer.MAX_VALUE) {
throw new RecordFormatException("Can't allocate an array > "+Integer.MAX_VALUE); throw new RecordFormatException("Can't allocate an array > "+Integer.MAX_VALUE);
} }
if (length > maxLength) { if (BYTE_ARRAY_MAX_OVERRIDE > 0) {
throw new RecordFormatException("Not allowed to allocate an array > "+ if (length > BYTE_ARRAY_MAX_OVERRIDE) {
maxLength+" for this record type." + throwRFE(length, BYTE_ARRAY_MAX_OVERRIDE);
"If the file is not corrupt, please open an issue on bugzilla to request " + }
"increasing the maximum allowable size for this record type"); } else if (length > maxLength) {
throwRFE(length, maxLength);
} }
return new byte[(int)length]; return new byte[(int)length];
} }
private static void throwRFE(long length, int maxLength) {
throw new RecordFormatException("Tried to allocate an array of length "+length +
", but "+ maxLength+" is the maximum for this record type.\n" +
"If the file is not corrupt, please open an issue on bugzilla to request \n" +
"increasing the maximum allowable size for this record type.\n"+
"As a temporary workaround, consider setting a higher override value with " +
"IOUtils.setByteArrayMaxOverride()");
}
} }

View File

@ -32,6 +32,10 @@ import java.io.OutputStream;
* http://marknelson.us/1989/10/01/lzw-data-compression/ * http://marknelson.us/1989/10/01/lzw-data-compression/
*/ */
public abstract class LZWDecompresser { public abstract class LZWDecompresser {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/** /**
* Does the mask bit mean it's compressed or uncompressed? * Does the mask bit mean it's compressed or uncompressed?
*/ */
@ -119,7 +123,7 @@ public abstract class LZWDecompresser {
// These are bytes as looked up in the dictionary // These are bytes as looked up in the dictionary
// It needs to be signed, as it'll get passed on to // It needs to be signed, as it'll get passed on to
// the output stream // the output stream
byte[] dataB = new byte[16+codeLengthIncrease]; byte[] dataB = IOUtils.safelyAllocate(16+codeLengthIncrease, MAX_RECORD_LENGTH);
// This is an unsigned byte read from the stream // This is an unsigned byte read from the stream
// It needs to be unsigned, so that bit stuff works // It needs to be unsigned, so that bit stuff works
int dataI; int dataI;

View File

@ -63,6 +63,9 @@ public class LittleEndian implements LittleEndianConsts
* @param size * @param size
* Number of bytes to copy. * Number of bytes to copy.
* @return The byteArray value * @return The byteArray value
*
* @see #getByteArray(byte[], int, int, long) if size is not a constant
*
* @throws IndexOutOfBoundsException * @throws IndexOutOfBoundsException
* - if copying would cause access of data outside array bounds. * - if copying would cause access of data outside array bounds.
*/ */
@ -74,6 +77,31 @@ public class LittleEndian implements LittleEndianConsts
return copy; return copy;
} }
/**
* Copy a portion of a byte array
*
* @param data
* the original byte array
* @param offset
* Where to start copying from.
* @param size
* Number of bytes to copy.
* @param maxSize
* Size must be <= maxSize or an exception is thrown.
* Use this to avoid potential OOMs on corrupt data.
* @return The byteArray value
* @throws IndexOutOfBoundsException
* - if copying would cause access of data outside array bounds.
*/
public static byte[] getByteArray( byte[] data, int offset, int size, int maxSize)
{
byte[] copy = IOUtils.safelyAllocate(size, maxSize);
System.arraycopy( data, offset, copy, 0, size );
return copy;
}
/** /**
* get a double value from a byte array, reads it in little endian format * get a double value from a byte array, reads it in little endian format
* then converts the resulting revolting IEEE 754 (curse them) floating * then converts the resulting revolting IEEE 754 (curse them) floating

View File

@ -28,6 +28,9 @@ import java.util.Map;
@Internal @Internal
public class StringUtil { public class StringUtil {
protected static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); protected static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 10000000;
public static final Charset UTF16LE = Charset.forName("UTF-16LE"); public static final Charset UTF16LE = Charset.forName("UTF-16LE");
public static final Charset UTF8 = Charset.forName("UTF-8"); public static final Charset UTF8 = Charset.forName("UTF-8");
public static final Charset WIN_1252 = Charset.forName("cp1252"); public static final Charset WIN_1252 = Charset.forName("cp1252");
@ -118,7 +121,7 @@ public class StringUtil {
} }
public static String readCompressedUnicode(LittleEndianInput in, int nChars) { public static String readCompressedUnicode(LittleEndianInput in, int nChars) {
byte[] buf = new byte[nChars]; byte[] buf = IOUtils.safelyAllocate(nChars, MAX_RECORD_LENGTH);
in.readFully(buf); in.readFully(buf);
return new String(buf, ISO_8859_1); return new String(buf, ISO_8859_1);
} }
@ -252,7 +255,7 @@ public class StringUtil {
} }
public static String readUnicodeLE(LittleEndianInput in, int nChars) { public static String readUnicodeLE(LittleEndianInput in, int nChars) {
byte[] bytes = new byte[nChars*2]; byte[] bytes = IOUtils.safelyAllocate(nChars*2, MAX_RECORD_LENGTH);
in.readFully(bytes); in.readFully(bytes);
return new String(bytes, UTF16LE); return new String(bytes, UTF16LE);
} }

View File

@ -58,6 +58,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier.AgileCertificateEntry; import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier.AgileCertificateEntry;
import org.apache.poi.poifs.crypt.standard.EncryptionRecord; import org.apache.poi.poifs.crypt.standard.EncryptionRecord;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.LittleEndianByteArrayOutputStream;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
@ -76,6 +77,10 @@ import com.microsoft.schemas.office.x2006.keyEncryptor.certificate.CTCertificate
import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor; import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor;
public class AgileEncryptor extends Encryptor implements Cloneable { public class AgileEncryptor extends Encryptor implements Cloneable {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private byte integritySalt[]; private byte integritySalt[];
private byte pwHash[]; private byte pwHash[];
@ -91,11 +96,11 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
int keySize = header.getKeySize()/8; int keySize = header.getKeySize()/8;
int hashSize = header.getHashAlgorithm().hashSize; int hashSize = header.getHashAlgorithm().hashSize;
byte[] newVerifierSalt = new byte[blockSize] byte[] newVerifierSalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
, newVerifier = new byte[blockSize] , newVerifier = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
, newKeySalt = new byte[blockSize] , newKeySalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
, newKeySpec = new byte[keySize] , newKeySpec = IOUtils.safelyAllocate(keySize, MAX_RECORD_LENGTH)
, newIntegritySalt = new byte[hashSize]; , newIntegritySalt = IOUtils.safelyAllocate(hashSize, MAX_RECORD_LENGTH);
r.nextBytes(newVerifierSalt); // blocksize r.nextBytes(newVerifierSalt); // blocksize
r.nextBytes(newVerifier); // blocksize r.nextBytes(newVerifier); // blocksize
r.nextBytes(newKeySalt); // blocksize r.nextBytes(newKeySalt); // blocksize

View File

@ -57,7 +57,9 @@ import org.apache.poi.xssf.usermodel.XSSFObjectData;
@Beta @Beta
public class EmbeddedExtractor implements Iterable<EmbeddedExtractor> { public class EmbeddedExtractor implements Iterable<EmbeddedExtractor> {
private static final POILogger LOG = POILogFactory.getLogger(EmbeddedExtractor.class); private static final POILogger LOG = POILogFactory.getLogger(EmbeddedExtractor.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
// contentType // contentType
private static final String CONTENT_TYPE_BYTES = "binary/octet-stream"; private static final String CONTENT_TYPE_BYTES = "binary/octet-stream";
private static final String CONTENT_TYPE_PDF = "application/pdf"; private static final String CONTENT_TYPE_PDF = "application/pdf";
@ -252,7 +254,7 @@ public class EmbeddedExtractor implements Iterable<EmbeddedExtractor> {
} }
int pictureBytesLen = idxEnd-idxStart+6; int pictureBytesLen = idxEnd-idxStart+6;
byte[] pdfBytes = new byte[pictureBytesLen]; byte[] pdfBytes = IOUtils.safelyAllocate(pictureBytesLen, MAX_RECORD_LENGTH);
System.arraycopy(pictureBytes, idxStart, pdfBytes, 0, pictureBytesLen); System.arraycopy(pictureBytes, idxStart, pdfBytes, 0, pictureBytesLen);
String filename = source.getShapeName().trim(); String filename = source.getShapeName().trim();
if (!endsWithIgnoreCase(filename, ".pdf")) { if (!endsWithIgnoreCase(filename, ".pdf")) {

View File

@ -73,6 +73,8 @@ import org.openxmlformats.schemas.presentationml.x2006.main.PresentationDocument
public class XMLSlideShow extends POIXMLDocument public class XMLSlideShow extends POIXMLDocument
implements SlideShow<XSLFShape,XSLFTextParagraph> { implements SlideShow<XSLFShape,XSLFTextParagraph> {
private static final POILogger LOG = POILogFactory.getLogger(XMLSlideShow.class); private static final POILogger LOG = POILogFactory.getLogger(XMLSlideShow.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private CTPresentation _presentation; private CTPresentation _presentation;
private List<XSLFSlide> _slides; private List<XSLFSlide> _slides;
@ -533,7 +535,7 @@ implements SlideShow<XSLFShape,XSLFTextParagraph> {
public XSLFPictureData addPicture(File pict, PictureType format) throws IOException public XSLFPictureData addPicture(File pict, PictureType format) throws IOException
{ {
int length = (int) pict.length(); int length = (int) pict.length();
byte[] data = new byte[length]; byte[] data = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH);
FileInputStream is = new FileInputStream(pict); FileInputStream is = new FileInputStream(pict);
try { try {
IOUtils.readFully(is, data); IOUtils.readFully(is, data);

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.BitSet; import java.util.BitSet;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianInputStream; import org.apache.poi.util.LittleEndianInputStream;
@ -34,6 +35,9 @@ import org.apache.poi.util.LittleEndianInputStream;
@Internal @Internal
public abstract class XSSFBParser { public abstract class XSSFBParser {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private final LittleEndianInputStream is; private final LittleEndianInputStream is;
private final BitSet records; private final BitSet records;
@ -88,8 +92,7 @@ public abstract class XSSFBParser {
} }
if (records == null || records.get(recordId)) { if (records == null || records.get(recordId)) {
//add sanity check for length? byte[] buff = IOUtils.safelyAllocate(recordLength, MAX_RECORD_LENGTH);
byte[] buff = new byte[(int) recordLength];
is.readFully(buff); is.readFully(buff);
handleRecord(recordId, buff); handleRecord(recordId, buff);
} else { } else {

View File

@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -38,6 +39,11 @@ import org.apache.poi.util.POILogger;
* to process the chunk value area * to process the chunk value area
*/ */
public final class ChunkFactory { public final class ChunkFactory {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/** The version of the currently open document */ /** The version of the currently open document */
private int version; private int version;
/** /**
@ -179,7 +185,7 @@ public final class ChunkFactory {
} }
// Now, create the chunk // Now, create the chunk
byte[] contents = new byte[header.getLength()]; byte[] contents = IOUtils.safelyAllocate(header.getLength(), MAX_RECORD_LENGTH);
System.arraycopy(data, offset+header.getSizeInBytes(), contents, 0, contents.length); System.arraycopy(data, offset+header.getSizeInBytes(), contents, 0, contents.length);
Chunk chunk = new Chunk(header, trailer, separator, contents); Chunk chunk = new Chunk(header, trailer, separator, contents);

View File

@ -21,12 +21,17 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import org.apache.poi.hdgf.HDGFLZW; import org.apache.poi.hdgf.HDGFLZW;
import org.apache.poi.util.IOUtils;
/** /**
* A StreamStore where the data on-disk is compressed, * A StreamStore where the data on-disk is compressed,
* using the crazy Visio LZW * using the crazy Visio LZW
*/ */
public final class CompressedStreamStore extends StreamStore { public final class CompressedStreamStore extends StreamStore {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/** The raw, compressed contents */ /** The raw, compressed contents */
private byte[] compressedContents; private byte[] compressedContents;
/** /**
@ -46,7 +51,7 @@ public final class CompressedStreamStore extends StreamStore {
protected CompressedStreamStore(byte[] data, int offset, int length) throws IOException { protected CompressedStreamStore(byte[] data, int offset, int length) throws IOException {
this(decompress(data,offset,length)); this(decompress(data,offset,length));
compressedContents = new byte[length]; compressedContents = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH);
System.arraycopy(data, offset, compressedContents, 0, length); System.arraycopy(data, offset, compressedContents, 0, length);
} }
/** /**

View File

@ -17,24 +17,29 @@
package org.apache.poi.hdgf.streams; package org.apache.poi.hdgf.streams;
import org.apache.poi.util.IOUtils;
/** /**
* Holds the representation of the stream on-disk, and * Holds the representation of the stream on-disk, and
* handles de-compressing it as required. * handles de-compressing it as required.
* In future, may also handle writing it back out again * In future, may also handle writing it back out again
*/ */
public class StreamStore { // TODO - instantiable superclass public class StreamStore { // TODO - instantiable superclass
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 10_000_000;
private byte[] contents; private byte[] contents;
/** /**
* Creates a new, non compressed Stream Store * Creates a new, non compressed Stream Store
*/ */
protected StreamStore(byte[] data, int offset, int length) { protected StreamStore(byte[] data, int offset, int length) {
contents = new byte[length]; contents = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH);
System.arraycopy(data, offset, contents, 0, length); System.arraycopy(data, offset, contents, 0, length);
} }
protected void prependContentsWith(byte[] b) { protected void prependContentsWith(byte[] b) {
byte[] newContents = new byte[contents.length + b.length]; byte[] newContents = IOUtils.safelyAllocate(contents.length + b.length, MAX_RECORD_LENGTH);
System.arraycopy(b, 0, newContents, 0, b.length); System.arraycopy(b, 0, newContents, 0, b.length);
System.arraycopy(contents, 0, newContents, b.length, contents.length); System.arraycopy(contents, 0, newContents, b.length, contents.length);
contents = newContents; contents = newContents;

View File

@ -34,7 +34,7 @@ import org.apache.poi.util.RecordFormatException;
@Internal @Internal
public class HemfCommentEMFPlus extends AbstractHemfComment { public class HemfCommentEMFPlus extends AbstractHemfComment {
private static final int MAX_RECORD_LENGTH = 1000000; private static final int MAX_RECORD_LENGTH = 1_000_000;
long dataSize; long dataSize;

View File

@ -36,7 +36,7 @@ import org.apache.poi.util.RecordFormatException;
@Internal @Internal
public class HemfCommentPublic { public class HemfCommentPublic {
private static final int MAX_RECORD_LENGTH = 1000000; private static final int MAX_RECORD_LENGTH = 1_000_000;
/** /**

View File

@ -36,7 +36,7 @@ import org.apache.poi.util.RecordFormatException;
*/ */
@Internal @Internal
public class HemfCommentRecord implements HemfRecord { public class HemfCommentRecord implements HemfRecord {
private static final int MAX_RECORD_LENGTH = 1000000; private static final int MAX_RECORD_LENGTH = 1_000_000;
public final static long COMMENT_EMFSPOOL = 0x00000000; public final static long COMMENT_EMFSPOOL = 0x00000000;
public final static long COMMENT_EMFPLUS = 0x2B464D45; public final static long COMMENT_EMFPLUS = 0x2B464D45;

View File

@ -32,7 +32,7 @@ import org.apache.poi.util.LittleEndianInputStream;
@Internal @Internal
public class HemfHeader implements HemfRecord { public class HemfHeader implements HemfRecord {
private static final int MAX_RECORD_LENGTH = 1000000; private static final int MAX_RECORD_LENGTH = 1_000_000;
private Rectangle boundsRectangle; private Rectangle boundsRectangle;

View File

@ -40,7 +40,7 @@ import org.apache.poi.util.RecordFormatException;
public class HemfText { public class HemfText {
private static final Charset UTF16LE = Charset.forName("UTF-16LE"); private static final Charset UTF16LE = Charset.forName("UTF-16LE");
private static final int MAX_RECORD_LENGTH = 1000000; private static final int MAX_RECORD_LENGTH = 1_000_000;
public static class ExtCreateFontIndirectW extends UnimplementedHemfRecord { public static class ExtCreateFontIndirectW extends UnimplementedHemfRecord {
} }

View File

@ -38,6 +38,10 @@ import org.apache.poi.util.StringUtil;
* or one of its {@link Attachment}s. * or one of its {@link Attachment}s.
*/ */
public class MAPIAttribute { public class MAPIAttribute {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private final MAPIProperty property; private final MAPIProperty property;
private final int type; private final int type;
private final byte[] data; private final byte[] data;
@ -144,7 +148,7 @@ public class MAPIAttribute {
} else { } else {
// Custom name was stored // Custom name was stored
int mplen = LittleEndian.readInt(inp); int mplen = LittleEndian.readInt(inp);
byte[] mpdata = new byte[mplen]; byte[] mpdata = IOUtils.safelyAllocate(mplen, MAX_RECORD_LENGTH);
IOUtils.readFully(inp, mpdata); IOUtils.readFully(inp, mpdata);
name = StringUtil.getFromUnicodeLE(mpdata, 0, (mplen/2)-1); name = StringUtil.getFromUnicodeLE(mpdata, 0, (mplen/2)-1);
skipToBoundary(mplen, inp); skipToBoundary(mplen, inp);
@ -164,7 +168,7 @@ public class MAPIAttribute {
} }
for(int j=0; j<values; j++) { for(int j=0; j<values; j++) {
int len = getLength(type, inp); int len = getLength(type, inp);
byte[] data = new byte[len]; byte[] data = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH);
IOUtils.readFully(inp, data); IOUtils.readFully(inp, data);
skipToBoundary(len, inp); skipToBoundary(len, inp);
@ -203,9 +207,11 @@ public class MAPIAttribute {
private static void skipToBoundary(int length, InputStream inp) throws IOException { private static void skipToBoundary(int length, InputStream inp) throws IOException {
// Data is always padded out to a 4 byte boundary // Data is always padded out to a 4 byte boundary
if(length % 4 != 0) { if(length % 4 != 0) {
int skip = 4 - (length % 4); int toSkip = 4 - (length % 4);
byte[] padding = new byte[skip]; long skipped = IOUtils.skipFully(inp, toSkip);
IOUtils.readFully(inp, padding); if (skipped != toSkip) {
throw new IOException("tried to skip "+toSkip +" but only skipped:"+skipped);
}
} }
} }
} }

View File

@ -24,6 +24,7 @@ import org.apache.poi.hmef.Attachment;
import org.apache.poi.hmef.CompressedRTF; import org.apache.poi.hmef.CompressedRTF;
import org.apache.poi.hmef.HMEFMessage; import org.apache.poi.hmef.HMEFMessage;
import org.apache.poi.hsmf.datatypes.MAPIProperty; import org.apache.poi.hsmf.datatypes.MAPIProperty;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
@ -31,6 +32,10 @@ import org.apache.poi.util.StringUtil;
* to a {@link HMEFMessage} or one of its {@link Attachment}s. * to a {@link HMEFMessage} or one of its {@link Attachment}s.
*/ */
public final class MAPIRtfAttribute extends MAPIAttribute { public final class MAPIRtfAttribute extends MAPIAttribute {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private final byte[] decompressed; private final byte[] decompressed;
private final String data; private final String data;
@ -41,7 +46,7 @@ public final class MAPIRtfAttribute extends MAPIAttribute {
CompressedRTF rtf = new CompressedRTF(); CompressedRTF rtf = new CompressedRTF();
byte[] tmp = rtf.decompress(new ByteArrayInputStream(data)); byte[] tmp = rtf.decompress(new ByteArrayInputStream(data));
if(tmp.length > rtf.getDeCompressedSize()) { if(tmp.length > rtf.getDeCompressedSize()) {
this.decompressed = new byte[rtf.getDeCompressedSize()]; this.decompressed = IOUtils.safelyAllocate(rtf.getDeCompressedSize(), MAX_RECORD_LENGTH);
System.arraycopy(tmp, 0, decompressed, 0, decompressed.length); System.arraycopy(tmp, 0, decompressed, 0, decompressed.length);
} else { } else {
this.decompressed = tmp; this.decompressed = tmp;

View File

@ -33,6 +33,10 @@ import org.apache.poi.util.LittleEndian;
* ones, so we can't just re-use the HSMF ones. * ones, so we can't just re-use the HSMF ones.
*/ */
public class TNEFAttribute { public class TNEFAttribute {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private final TNEFProperty property; private final TNEFProperty property;
private final int type; private final int type;
private final byte[] data; private final byte[] data;
@ -47,7 +51,7 @@ public class TNEFAttribute {
int length = LittleEndian.readInt(inp); int length = LittleEndian.readInt(inp);
property = TNEFProperty.getBest(id, type); property = TNEFProperty.getBest(id, type);
data = new byte[length]; data = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH);
IOUtils.readFully(inp, data); IOUtils.readFully(inp, data);
checksum = LittleEndian.readUShort(inp); checksum = LittleEndian.readUShort(inp);

View File

@ -29,12 +29,17 @@ import org.apache.poi.hmef.attribute.TNEFDateAttribute;
import org.apache.poi.hmef.attribute.TNEFProperty; import org.apache.poi.hmef.attribute.TNEFProperty;
import org.apache.poi.hmef.attribute.TNEFStringAttribute; import org.apache.poi.hmef.attribute.TNEFStringAttribute;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
* Developer focused raw dumper * Developer focused raw dumper
*/ */
public final class HMEFDumper { public final class HMEFDumper {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
if(args.length < 1) { if(args.length < 1) {
throw new IllegalArgumentException("Filename must be given"); throw new IllegalArgumentException("Filename must be given");
@ -138,7 +143,7 @@ public final class HMEFDumper {
thisLen = len - offset; thisLen = len - offset;
} }
byte data[] = new byte[thisLen]; byte data[] = IOUtils.safelyAllocate(thisLen, MAX_RECORD_LENGTH);
System.arraycopy(attr.getData(), offset, data, 0, thisLen); System.arraycopy(attr.getData(), offset, data, 0, thisLen);
System.out.print( System.out.print(

View File

@ -23,11 +23,16 @@ import java.util.ArrayList;
import org.apache.poi.ddf.DefaultEscherRecordFactory; import org.apache.poi.ddf.DefaultEscherRecordFactory;
import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.util.IOUtils;
/** /**
* Parent class of all Escher parts * Parent class of all Escher parts
*/ */
public abstract class EscherPart extends HPBFPart { public abstract class EscherPart extends HPBFPart {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private EscherRecord[] records; private EscherRecord[] records;
/** /**
@ -69,7 +74,7 @@ public abstract class EscherPart extends HPBFPart {
size += records[i].getRecordSize(); size += records[i].getRecordSize();
} }
byte data[] = new byte[size]; byte data[] = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
size = 0; size = 0;
for(int i=0; i<records.length; i++) { for(int i=0; i<records.length; i++) {
int thisSize = int thisSize =

View File

@ -24,6 +24,7 @@ import org.apache.poi.hpbf.model.qcbits.QCPLCBit;
import org.apache.poi.hpbf.model.qcbits.QCTextBit; import org.apache.poi.hpbf.model.qcbits.QCTextBit;
import org.apache.poi.hpbf.model.qcbits.UnknownQCBit; import org.apache.poi.hpbf.model.qcbits.UnknownQCBit;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
@ -34,6 +35,8 @@ import org.apache.poi.util.POILogger;
*/ */
public final class QuillContents extends HPBFPart { public final class QuillContents extends HPBFPart {
private static POILogger logger = POILogFactory.getLogger(QuillContents.class); private static POILogger logger = POILogFactory.getLogger(QuillContents.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private static final String[] PATH = { "Quill", "QuillSub", "CONTENTS", }; private static final String[] PATH = { "Quill", "QuillSub", "CONTENTS", };
private QCBit[] bits; private QCBit[] bits;
@ -66,7 +69,7 @@ public final class QuillContents extends HPBFPart {
int from = (int)LittleEndian.getUInt(data, offset+16); int from = (int)LittleEndian.getUInt(data, offset+16);
int len = (int)LittleEndian.getUInt(data, offset+20); int len = (int)LittleEndian.getUInt(data, offset+20);
byte[] bitData = new byte[len]; byte[] bitData = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH);
System.arraycopy(data, from, bitData, 0, len); System.arraycopy(data, from, bitData, 0, len);
// Create // Create

View File

@ -17,12 +17,17 @@
package org.apache.poi.hpbf.model.qcbits; package org.apache.poi.hpbf.model.qcbits;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
* A Text based bit of Quill Contents * A Text based bit of Quill Contents
*/ */
public final class QCTextBit extends QCBit { public final class QCTextBit extends QCBit {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
public QCTextBit(String thingType, String bitType, byte[] data) { public QCTextBit(String thingType, String bitType, byte[] data) {
super(thingType, bitType, data); super(thingType, bitType, data);
} }
@ -36,7 +41,7 @@ public final class QCTextBit extends QCBit {
} }
public void setText(String text) { public void setText(String text) {
byte data[] = new byte[text.length()*2]; byte data[] = IOUtils.safelyAllocate(text.length()*2, MAX_RECORD_LENGTH);
StringUtil.putUnicodeLE(text, data, 0); StringUtil.putUnicodeLE(text, data, 0);
setData(data); setData(data);
} }

View File

@ -26,6 +26,7 @@ import java.io.IOException;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import org.apache.poi.hslf.usermodel.HSLFPictureData; import org.apache.poi.hslf.usermodel.HSLFPictureData;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
/** /**
@ -38,7 +39,7 @@ public abstract class Bitmap extends HSLFPictureData {
public byte[] getData(){ public byte[] getData(){
byte[] rawdata = getRawData(); byte[] rawdata = getRawData();
int prefixLen = 16*getUIDInstanceCount()+1; int prefixLen = 16*getUIDInstanceCount()+1;
byte[] imgdata = new byte[rawdata.length-prefixLen]; byte[] imgdata = IOUtils.safelyAllocate(rawdata.length-prefixLen, rawdata.length);
System.arraycopy(rawdata, prefixLen, imgdata, 0, imgdata.length); System.arraycopy(rawdata, prefixLen, imgdata, 0, imgdata.length);
return imgdata; return imgdata;
} }

View File

@ -19,12 +19,17 @@ package org.apache.poi.hslf.blip;
import java.io.IOException; import java.io.IOException;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
* Represents a DIB picture data in a PPT file * Represents a DIB picture data in a PPT file
*/ */
public final class DIB extends Bitmap { public final class DIB extends Bitmap {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/** /**
* Size of the BITMAPFILEHEADER structure preceding the actual DIB bytes * Size of the BITMAPFILEHEADER structure preceding the actual DIB bytes
*/ */
@ -87,7 +92,7 @@ public final class DIB extends Bitmap {
LittleEndian.putInt(header, 10, offset); LittleEndian.putInt(header, 10, offset);
//DIB data is the header + dib bytes //DIB data is the header + dib bytes
byte[] dib = new byte[header.length + data.length]; byte[] dib = IOUtils.safelyAllocate(header.length + data.length, MAX_RECORD_LENGTH);
System.arraycopy(header, 0, dib, 0, header.length); System.arraycopy(header, 0, dib, 0, header.length);
System.arraycopy(data, 0, dib, header.length, data.length); System.arraycopy(data, 0, dib, header.length, data.length);
@ -97,7 +102,7 @@ public final class DIB extends Bitmap {
@Override @Override
public void setData(byte[] data) throws IOException { public void setData(byte[] data) throws IOException {
//cut off the bitmap file-header //cut off the bitmap file-header
byte[] dib = new byte[data.length-HEADER_SIZE]; byte[] dib = IOUtils.safelyAllocate(data.length-HEADER_SIZE, data.length);
System.arraycopy(data, HEADER_SIZE, dib, 0, dib.length); System.arraycopy(data, HEADER_SIZE, dib, 0, dib.length);
super.setData(dib); super.setData(dib);
} }

View File

@ -39,6 +39,10 @@ import org.apache.poi.util.LittleEndian;
*/ */
public final class PPTXMLDump { public final class PPTXMLDump {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private static final int HEADER_SIZE = 8; //size of the record header private static final int HEADER_SIZE = 8; //size of the record header
private static final int PICT_HEADER_SIZE = 25; //size of the picture header private static final int PICT_HEADER_SIZE = 25; //size of the picture header
private static final String PICTURES_ENTRY = "Pictures"; private static final String PICTURES_ENTRY = "Pictures";
@ -164,7 +168,7 @@ public final class PPTXMLDump {
System.arraycopy(data, pos, header, 0, header.length); System.arraycopy(data, pos, header, 0, header.length);
int size = LittleEndian.getInt(header, 4) - 17; int size = LittleEndian.getInt(header, 4) - 17;
byte[] pictdata = new byte[size]; byte[] pictdata = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
System.arraycopy(data, pos + PICT_HEADER_SIZE, pictdata, 0, pictdata.length); System.arraycopy(data, pos + PICT_HEADER_SIZE, pictdata, 0, pictdata.length);
pos += PICT_HEADER_SIZE + size; pos += PICT_HEADER_SIZE + size;

View File

@ -48,7 +48,11 @@ import org.apache.poi.util.LittleEndian;
* from hslf.record.RecordTypes also) * from hslf.record.RecordTypes also)
*/ */
public final class SlideShowDumper { public final class SlideShowDumper {
private byte[] docstream;
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private byte[] docstream;
/** Do we try to use DDF to understand the escher objects? */ /** Do we try to use DDF to understand the escher objects? */
private boolean ddfEscher; private boolean ddfEscher;
@ -209,7 +213,7 @@ public void walkTree(int depth, int startPos, int maxLen) throws IOException {
final String ind = (indent == 0) ? "%1$s" : "%1$"+indent+"s"; final String ind = (indent == 0) ? "%1$s" : "%1$"+indent+"s";
byte[] contents = new byte[len]; byte[] contents = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH);
System.arraycopy(docstream,pos,contents,0,len); System.arraycopy(docstream,pos,contents,0,len);
DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory(); DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory();
EscherRecord record = erf.createRecord(contents,0); EscherRecord record = erf.createRecord(contents,0);

View File

@ -20,6 +20,7 @@ package org.apache.poi.hslf.record;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -29,6 +30,9 @@ import org.apache.poi.util.LittleEndian;
*/ */
public final class AnimationInfoAtom extends RecordAtom { public final class AnimationInfoAtom extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* whether the animation plays in the reverse direction * whether the animation plays in the reverse direction
*/ */
@ -98,7 +102,7 @@ public final class AnimationInfoAtom extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Grab the record data // Grab the record data
_recdata = new byte[len-8]; _recdata = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_recdata,0,len-8); System.arraycopy(source,start+8,_recdata,0,len-8);
} }

View File

@ -20,6 +20,7 @@ package org.apache.poi.hslf.record;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
@ -32,6 +33,10 @@ import org.apache.poi.util.StringUtil;
*/ */
public final class CString extends RecordAtom { public final class CString extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private byte[] _header; private byte[] _header;
private static long _type = 4026l; private static long _type = 4026l;
@ -83,7 +88,7 @@ public final class CString extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Grab the text // Grab the text
_text = new byte[len-8]; _text = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_text,0,len-8); System.arraycopy(source,start+8,_text,0,len-8);
} }
/** /**

View File

@ -22,6 +22,7 @@ import java.io.OutputStream;
import java.util.Date; import java.util.Date;
import org.apache.poi.hslf.util.SystemTimeUtils; import org.apache.poi.hslf.util.SystemTimeUtils;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -32,6 +33,10 @@ import org.apache.poi.util.LittleEndian;
public final class Comment2000Atom extends RecordAtom public final class Comment2000Atom extends RecordAtom
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* Record header. * Record header.
*/ */
@ -68,7 +73,7 @@ public final class Comment2000Atom extends RecordAtom
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Get the record data. // Get the record data.
_data = new byte[len-8]; _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_data,0,len-8); System.arraycopy(source,start+8,_data,0,len-8);
} }

View File

@ -31,6 +31,7 @@ import org.apache.poi.hslf.exceptions.OldPowerPointFormatException;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -44,6 +45,8 @@ import org.apache.poi.util.StringUtil;
public class CurrentUserAtom public class CurrentUserAtom
{ {
private final static POILogger logger = POILogFactory.getLogger(CurrentUserAtom.class); private final static POILogger logger = POILogFactory.getLogger(CurrentUserAtom.class);
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/** Standard Atom header */ /** Standard Atom header */
public static final byte[] atomHeader = new byte[] { 0, 0, -10, 15 }; public static final byte[] atomHeader = new byte[] { 0, 0, -10, 15 };
@ -127,7 +130,7 @@ public class CurrentUserAtom
// Grab the contents // Grab the contents
int len = docProps.getSize(); int len = docProps.getSize();
_contents = new byte[len]; _contents = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH);
InputStream in = dir.createDocumentInputStream("Current User"); InputStream in = dir.createDocumentInputStream("Current User");
int readLen = in.read(_contents); int readLen = in.read(_contents);
in.close(); in.close();
@ -197,12 +200,12 @@ public class CurrentUserAtom
int len = 2*(int)usernameLen; int len = 2*(int)usernameLen;
if(_contents.length >= start+len) { if(_contents.length >= start+len) {
byte[] textBytes = new byte[len]; byte[] textBytes = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH);
System.arraycopy(_contents,start,textBytes,0,len); System.arraycopy(_contents,start,textBytes,0,len);
lastEditUser = StringUtil.getFromUnicodeLE(textBytes); lastEditUser = StringUtil.getFromUnicodeLE(textBytes);
} else { } else {
// Fake from the 8 bit version // Fake from the 8 bit version
byte[] textBytes = new byte[(int)usernameLen]; byte[] textBytes = IOUtils.safelyAllocate(usernameLen, MAX_RECORD_LENGTH);
System.arraycopy(_contents,28,textBytes,0,(int)usernameLen); System.arraycopy(_contents,28,textBytes,0,(int)usernameLen);
lastEditUser = StringUtil.getFromCompressedUnicode(textBytes,0,(int)usernameLen); lastEditUser = StringUtil.getFromCompressedUnicode(textBytes,0,(int)usernameLen);
} }
@ -219,7 +222,7 @@ public class CurrentUserAtom
// 4 = revision // 4 = revision
// 3 * len = ascii + unicode // 3 * len = ascii + unicode
int size = 8 + 20 + 4 + (3 * lastEditUser.length()); int size = 8 + 20 + 4 + (3 * lastEditUser.length());
_contents = new byte[size]; _contents = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
// First we have a 8 byte atom header // First we have a 8 byte atom header
System.arraycopy(atomHeader,0,_contents,0,4); System.arraycopy(atomHeader,0,_contents,0,4);
@ -238,7 +241,7 @@ public class CurrentUserAtom
// The username gets stored twice, once as US // The username gets stored twice, once as US
// ascii, and again as unicode laster on // ascii, and again as unicode laster on
byte[] asciiUN = new byte[lastEditUser.length()]; byte[] asciiUN = IOUtils.safelyAllocate(lastEditUser.length(), MAX_RECORD_LENGTH);
StringUtil.putCompressedUnicode(lastEditUser,asciiUN,0); StringUtil.putCompressedUnicode(lastEditUser,asciiUN,0);
// Now we're able to do the length of the last edited user // Now we're able to do the length of the last edited user
@ -260,7 +263,7 @@ public class CurrentUserAtom
LittleEndian.putInt(_contents,28+asciiUN.length,(int)releaseVersion); LittleEndian.putInt(_contents,28+asciiUN.length,(int)releaseVersion);
// username in unicode // username in unicode
byte [] ucUN = new byte[lastEditUser.length()*2]; byte [] ucUN = IOUtils.safelyAllocate(lastEditUser.length()*2, MAX_RECORD_LENGTH);
StringUtil.putUnicodeLE(lastEditUser,ucUN,0); StringUtil.putUnicodeLE(lastEditUser,ucUN,0);
System.arraycopy(ucUN,0,_contents,28+asciiUN.length+4,ucUN.length); System.arraycopy(ucUN,0,_contents,28+asciiUN.length+4,ucUN.length);

View File

@ -17,6 +17,7 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@ -30,6 +31,9 @@ import java.io.OutputStream;
public final class DocumentAtom extends RecordAtom public final class DocumentAtom extends RecordAtom
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private byte[] _header; private byte[] _header;
private static long _type = 1001l; private static long _type = 1001l;
@ -137,7 +141,7 @@ public final class DocumentAtom extends RecordAtom
showComments = source[start+39+8]; showComments = source[start+39+8];
// If there's any other bits of data, keep them about // If there's any other bits of data, keep them about
reserved = new byte[len-40-8]; reserved = IOUtils.safelyAllocate(len-40-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+48,reserved,0,reserved.length); System.arraycopy(source,start+48,reserved,0,reserved.length);
} }

View File

@ -20,6 +20,7 @@ package org.apache.poi.hslf.record;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -40,6 +41,9 @@ import org.apache.poi.util.LittleEndian;
*/ */
public class ExEmbedAtom extends RecordAtom { public class ExEmbedAtom extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/** /**
* Embedded document does not follow the color scheme. * Embedded document does not follow the color scheme.
*/ */
@ -91,7 +95,7 @@ public class ExEmbedAtom extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Get the record data. // Get the record data.
_data = new byte[len-8]; _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_data,0,len-8); System.arraycopy(source,start+8,_data,0,len-8);
// Must be at least 8 bytes long // Must be at least 8 bytes long

View File

@ -20,6 +20,7 @@ package org.apache.poi.hslf.record;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -29,6 +30,10 @@ import org.apache.poi.util.LittleEndian;
* @author Nick Burch * @author Nick Burch
*/ */
public final class ExHyperlinkAtom extends RecordAtom { public final class ExHyperlinkAtom extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* Record header. * Record header.
*/ */
@ -66,7 +71,7 @@ public final class ExHyperlinkAtom extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Get the record data. // Get the record data.
_data = new byte[len-8]; _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_data,0,len-8); System.arraycopy(source,start+8,_data,0,len-8);
// Must be at least 4 bytes long // Must be at least 4 bytes long

View File

@ -20,6 +20,7 @@ package org.apache.poi.hslf.record;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -29,6 +30,8 @@ import org.apache.poi.util.LittleEndian;
*/ */
public final class ExMediaAtom extends RecordAtom public final class ExMediaAtom extends RecordAtom
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/** /**
* A bit that specifies whether the audio or video data is repeated continuously during playback. * A bit that specifies whether the audio or video data is repeated continuously during playback.
@ -78,7 +81,7 @@ public final class ExMediaAtom extends RecordAtom
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Grab the record data // Grab the record data
_recdata = new byte[len-8]; _recdata = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_recdata,0,len-8); System.arraycopy(source,start+8,_recdata,0,len-8);
} }

View File

@ -21,6 +21,7 @@ package org.apache.poi.hslf.record;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -31,6 +32,10 @@ import org.apache.poi.util.LittleEndian;
public class ExObjListAtom extends RecordAtom public class ExObjListAtom extends RecordAtom
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/** /**
* Record header. * Record header.
*/ */
@ -68,7 +73,7 @@ public class ExObjListAtom extends RecordAtom
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Get the record data. // Get the record data.
_data = new byte[len-8]; _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_data,0,len-8); System.arraycopy(source,start+8,_data,0,len-8);
// Must be at least 4 bytes long // Must be at least 4 bytes long

View File

@ -20,6 +20,7 @@ package org.apache.poi.hslf.record;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -65,6 +66,9 @@ import org.apache.poi.util.LittleEndian;
*/ */
public class ExOleObjAtom extends RecordAtom { public class ExOleObjAtom extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/** /**
* The object) is displayed as an embedded object inside of a container, * The object) is displayed as an embedded object inside of a container,
*/ */
@ -148,7 +152,7 @@ public class ExOleObjAtom extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Get the record data. // Get the record data.
_data = new byte[len-8]; _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_data,0,len-8); System.arraycopy(source,start+8,_data,0,len-8);
// Must be at least 24 bytes long // Must be at least 24 bytes long

View File

@ -27,6 +27,7 @@ import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream; import java.util.zip.InflaterInputStream;
import org.apache.poi.util.BoundedInputStream; import org.apache.poi.util.BoundedInputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -34,6 +35,9 @@ import org.apache.poi.util.LittleEndian;
*/ */
public class ExOleObjStg extends PositionDependentRecordAtom implements PersistRecord { public class ExOleObjStg extends PositionDependentRecordAtom implements PersistRecord {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private int _persistId; // Found from PersistPtrHolder private int _persistId; // Found from PersistPtrHolder
/** /**
@ -72,7 +76,7 @@ public class ExOleObjStg extends PositionDependentRecordAtom implements PersistR
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Get the record data. // Get the record data.
_data = new byte[len-8]; _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_data,0,len-8); System.arraycopy(source,start+8,_data,0,len-8);
} }

View File

@ -22,6 +22,7 @@ import java.io.OutputStream;
import java.util.Arrays; import java.util.Arrays;
import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
@ -35,7 +36,11 @@ import org.apache.poi.util.StringUtil;
*/ */
public final class FontEntityAtom extends RecordAtom { public final class FontEntityAtom extends RecordAtom {
/**
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
/**
* record header * record header
*/ */
private byte[] _header; private byte[] _header;
@ -54,7 +59,7 @@ public final class FontEntityAtom extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Grab the record data // Grab the record data
_recdata = new byte[len-8]; _recdata = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_recdata,0,len-8); System.arraycopy(source,start+8,_recdata,0,len-8);
} }

View File

@ -27,6 +27,7 @@ import org.apache.poi.ddf.EscherClientDataRecord;
import org.apache.poi.ddf.EscherRecordFactory; import org.apache.poi.ddf.EscherRecordFactory;
import org.apache.poi.ddf.EscherSerializationListener; import org.apache.poi.ddf.EscherSerializationListener;
import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -38,6 +39,9 @@ import org.apache.poi.util.LittleEndian;
*/ */
public class HSLFEscherClientDataRecord extends EscherClientDataRecord { public class HSLFEscherClientDataRecord extends EscherClientDataRecord {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private final List<Record> _childRecords = new ArrayList<>(); private final List<Record> _childRecords = new ArrayList<>();
public List<? extends Record> getHSLFChildRecords() { public List<? extends Record> getHSLFChildRecords() {
@ -60,7 +64,7 @@ public class HSLFEscherClientDataRecord extends EscherClientDataRecord {
@Override @Override
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
int bytesRemaining = readHeader( data, offset ); int bytesRemaining = readHeader( data, offset );
byte remainingData[] = new byte[bytesRemaining]; byte remainingData[] = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH);
System.arraycopy(data, offset+8, remainingData, 0, bytesRemaining); System.arraycopy(data, offset+8, remainingData, 0, bytesRemaining);
setRemainingData(remainingData); setRemainingData(remainingData);
return bytesRemaining + 8; return bytesRemaining + 8;

View File

@ -17,6 +17,7 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@ -30,6 +31,10 @@ import java.io.OutputStream;
public final class HeadersFootersAtom extends RecordAtom { public final class HeadersFootersAtom extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* A bit that specifies whether the date is displayed in the footer. * A bit that specifies whether the date is displayed in the footer.
* @see #getMask() * @see #getMask()
@ -96,7 +101,7 @@ public final class HeadersFootersAtom extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Grab the record data // Grab the record data
_recdata = new byte[len-8]; _recdata = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_recdata,0,len-8); System.arraycopy(source,start+8,_recdata,0,len-8);
} }

View File

@ -20,6 +20,7 @@ package org.apache.poi.hslf.record;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -31,6 +32,10 @@ import org.apache.poi.util.LittleEndian;
*/ */
public class InteractiveInfoAtom extends RecordAtom { public class InteractiveInfoAtom extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* Action Table * Action Table
*/ */
@ -105,7 +110,7 @@ public class InteractiveInfoAtom extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Get the record data. // Get the record data.
_data = new byte[len-8]; _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_data,0,len-8); System.arraycopy(source,start+8,_data,0,len-8);
// Must be at least 16 bytes long // Must be at least 16 bytes long

View File

@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import org.apache.poi.hslf.model.textproperties.IndentProp; import org.apache.poi.hslf.model.textproperties.IndentProp;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -31,6 +32,10 @@ import org.apache.poi.util.POILogger;
* Specifies the Indent Level for the text * Specifies the Indent Level for the text
*/ */
public final class MasterTextPropAtom extends RecordAtom { public final class MasterTextPropAtom extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
/** /**
* Record header. * Record header.
*/ */
@ -71,7 +76,7 @@ public final class MasterTextPropAtom extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Get the record data. // Get the record data.
_data = new byte[len-8]; _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_data,0,len-8); System.arraycopy(source,start+8,_data,0,len-8);
try { try {
@ -108,7 +113,7 @@ public final class MasterTextPropAtom extends RecordAtom {
*/ */
private void write() { private void write() {
int pos = 0; int pos = 0;
_data = new byte[indents.size()*6]; _data = IOUtils.safelyAllocate(indents.size()*6, MAX_RECORD_LENGTH);
for (IndentProp prop : indents) { for (IndentProp prop : indents) {
LittleEndian.putInt(_data, pos, prop.getCharactersCovered()); LittleEndian.putInt(_data, pos, prop.getCharactersCovered());
LittleEndian.putShort(_data, pos+4, (short)prop.getIndentLevel()); LittleEndian.putShort(_data, pos+4, (short)prop.getIndentLevel());

View File

@ -17,6 +17,7 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@ -30,6 +31,10 @@ import java.io.OutputStream;
public final class NotesAtom extends RecordAtom public final class NotesAtom extends RecordAtom
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private byte[] _header; private byte[] _header;
private static long _type = 1009l; private static long _type = 1009l;
@ -86,7 +91,7 @@ public final class NotesAtom extends RecordAtom
} }
// There might be 2 more bytes, which are a reserved field // There might be 2 more bytes, which are a reserved field
reserved = new byte[len-14]; reserved = IOUtils.safelyAllocate(len-14, MAX_RECORD_LENGTH);
System.arraycopy(source,start+14,reserved,0,reserved.length); System.arraycopy(source,start+14,reserved,0,reserved.length);
} }

View File

@ -36,6 +36,7 @@ import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherSpgrRecord; import org.apache.poi.ddf.EscherSpgrRecord;
import org.apache.poi.ddf.EscherTextboxRecord; import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.sl.usermodel.ShapeType; import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -52,6 +53,11 @@ import org.apache.poi.util.POILogger;
// For now, pretending to be an atom. Might not always be, but that // For now, pretending to be an atom. Might not always be, but that
// would require a wrapping class // would require a wrapping class
public final class PPDrawing extends RecordAtom { public final class PPDrawing extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private byte[] _header; private byte[] _header;
private long _type; private long _type;
@ -100,7 +106,7 @@ public final class PPDrawing extends RecordAtom {
_type = LittleEndian.getUShort(_header,2); _type = LittleEndian.getUShort(_header,2);
// Get the contents for now // Get the contents for now
final byte[] contents = new byte[len]; final byte[] contents = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH);
System.arraycopy(source,start,contents,0,len); System.arraycopy(source,start,contents,0,len);
// Build up a tree of Escher records contained within // Build up a tree of Escher records contained within

View File

@ -18,6 +18,7 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import org.apache.poi.ddf.*; import org.apache.poi.ddf.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import java.io.OutputStream; import java.io.OutputStream;
@ -35,6 +36,10 @@ import java.util.Iterator;
*/ */
public final class PPDrawingGroup extends RecordAtom { public final class PPDrawingGroup extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private byte[] _header; private byte[] _header;
private EscherContainerRecord dggContainer; private EscherContainerRecord dggContainer;
//cached dgg //cached dgg
@ -46,7 +51,7 @@ public final class PPDrawingGroup extends RecordAtom {
System.arraycopy(source,start,_header,0,8); System.arraycopy(source,start,_header,0,8);
// Get the contents for now // Get the contents for now
byte[] contents = new byte[len]; byte[] contents = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH);
System.arraycopy(source,start,contents,0,len); System.arraycopy(source,start,contents,0,len);
DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory(); DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory();

View File

@ -29,6 +29,7 @@ import java.util.TreeMap;
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.util.BitField; import org.apache.poi.util.BitField;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -46,6 +47,10 @@ import org.apache.poi.util.POILogger;
public final class PersistPtrHolder extends PositionDependentRecordAtom public final class PersistPtrHolder extends PositionDependentRecordAtom
{ {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
private final byte[] _header; private final byte[] _header;
private byte[] _ptrData; // Will need to update this once we allow updates to _slideLocations private byte[] _ptrData; // Will need to update this once we allow updates to _slideLocations
private long _type; private long _type;
@ -109,7 +114,7 @@ public final class PersistPtrHolder extends PositionDependentRecordAtom
// count * 32 bit offsets // count * 32 bit offsets
// Repeat as many times as you have data // Repeat as many times as you have data
_slideLocations = new HashMap<>(); _slideLocations = new HashMap<>();
_ptrData = new byte[len-8]; _ptrData = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
System.arraycopy(source,start+8,_ptrData,0,_ptrData.length); System.arraycopy(source,start+8,_ptrData,0,_ptrData.length);
int pos = 0; int pos = 0;

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.hslf.record.SlideAtomLayout.SlideLayoutType; import org.apache.poi.hslf.record.SlideAtomLayout.SlideLayoutType;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -33,7 +34,10 @@ public final class SlideAtom extends RecordAtom {
public static final int USES_MASTER_SLIDE_ID = 0x80000000; public static final int USES_MASTER_SLIDE_ID = 0x80000000;
// private static final int MASTER_SLIDE_ID = 0x00000000; // private static final int MASTER_SLIDE_ID = 0x00000000;
private byte[] _header; //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 1_000_000;
private byte[] _header;
private static long _type = 1007l; private static long _type = 1007l;
private int masterID; private int masterID;
@ -109,7 +113,7 @@ public final class SlideAtom extends RecordAtom {
// If there's any other bits of data, keep them about // If there's any other bits of data, keep them about
// 8 bytes header + 20 bytes to flags + 2 bytes flags = 30 bytes // 8 bytes header + 20 bytes to flags + 2 bytes flags = 30 bytes
reserved = new byte[len-30]; reserved = IOUtils.safelyAllocate(len-30, MAX_RECORD_LENGTH);
System.arraycopy(source,start+30,reserved,0,reserved.length); System.arraycopy(source,start+30,reserved,0,reserved.length);
} }

View File

@ -17,6 +17,7 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@ -28,6 +29,10 @@ import java.io.OutputStream;
* @author Nick Burch * @author Nick Burch
*/ */
public final class SlidePersistAtom extends RecordAtom { public final class SlidePersistAtom extends RecordAtom {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 32;
private byte[] _header; private byte[] _header;
private static long _type = 1011l; private static long _type = 1011l;
@ -92,7 +97,7 @@ public final class SlidePersistAtom extends RecordAtom {
// Finally you have typically 4 or 8 bytes of reserved fields, // Finally you have typically 4 or 8 bytes of reserved fields,
// all zero running from 24 bytes in to the end // all zero running from 24 bytes in to the end
reservedFields = new byte[len-24]; reservedFields = IOUtils.safelyAllocate(len-24, MAX_RECORD_LENGTH);
System.arraycopy(source,start+24,reservedFields,0,reservedFields.length); System.arraycopy(source,start+24,reservedFields,0,reservedFields.length);
} }

Some files were not shown because too many files have changed in this diff Show More